// OVLテスト用req_sm.v
// req_start 信号を受けると、reqを1にアサートする。ackを受け取るとreqを0にディアサートする
`default_nettype none
module req_sm (
input wire clk,
input wire reset,
input wire req_start,
input wire ack,
output reg req
);
parameter [1:0] idle_req = 2'b01,
assert_req = 2'b10;
reg [1:0] cs_req;
always @(posedge clk) begin
if (reset) begin
cs_req <= idle_req;
req <= 1'b0;
end else begin
case (cs_req)
idle_req :
if (req_start) begin
cs_req <= assert_req;
req <= 1'b1;
end
assert_req :
if (ack) begin
cs_req <= idle_req;
req <= 1'b0;
end
endcase
end
end
endmodule
`default_nettype wire
// OVLテスト用 ack_sm.v
// 2つのreqを管理して、reqがアサートされている状態で、taがアサートされるとackを返す
`default_nettype none
module ack_sm (
input wire clk,
input wire reset,
input wire req0,
input wire req1,
input wire ta0, // Transfer Acknowledge
input wire ta1, // Transfer Acknowledge
output reg ack0,
output reg ack1
);
parameter [6:0] idle_req = 7'b0000001, // 最初のidle 状態
assert_req0 = 7'b0000010, // req0だけがアサートされている
assert_req1 = 7'b0000100, // req1だけがアサートされている
assert_req01 = 7'b0001000,
req0_ack = 7'b0010000,
req1_ack = 7'b0100000,
req01_ack = 7'b1000000;
reg [6:0] cs_main;
always @(posedge clk) begin
if (reset) begin
cs_main <= idle_req;
ack0 <= 1'b0; ack1 <= 1'b0;
end else begin
case (cs_main)
idle_req : begin
if (req0) begin
cs_main <= assert_req0;
ack0 <= 1'b0; ack1 <= 1'b0;
end else if (req1) begin
cs_main <= assert_req1;
ack0 <= 1'b0; ack1 <= 1'b0;
end
end
assert_req0 : begin
if (req1) begin
cs_main <= assert_req01;
ack0 <= 1'b0; ack1 <= 1'b0;
end else if (ta0) begin
cs_main <= req0_ack;
ack0 <= 1'b1; ack1 <= 1'b0;
end
end
assert_req1 : begin
if (req0) begin
cs_main <= assert_req01;
ack0 <= 1'b0; ack1 <= 1'b0;
end else if (ta1) begin
cs_main <= req1_ack;
ack0 <= 1'b0; ack1 <= 1'b1;
end
end
assert_req01 : begin
if (ta0 & ~ta1) begin
cs_main <= req0_ack;
ack0 <= 1'b1; ack1 <= 1'b0;
end else if (~ta0 & ta1) begin
cs_main <= req1_ack;
ack0 <= 1'b0; ack1 <= 1'b1;
end else if (ta0 & ta1) begin
cs_main <= req01_ack;
ack0 <= 1'b1; ack1 <= 1'b1;
end
end
req0_ack : begin
if (req1) begin
cs_main <= assert_req1;
ack0 <= 1'b0; ack1 <= 1'b0;
end else begin
cs_main <= idle_req;
ack0 <= 1'b0; ack1 <= 1'b0;
end
end
req1_ack : begin
if (req0) begin
cs_main <= assert_req0;
ack0 <= 1'b0; ack1 <= 1'b0;
end else begin
cs_main <= idle_req;
ack0 <= 1'b0; ack1 <= 1'b0;
end
end
req01_ack : begin
cs_main <= idle_req;
ack0 <= 1'b0; ack1 <= 1'b0;
end
endcase
end
end
endmodule
`default_nettype wire
// tb_req_ack.v
`default_nettype none
`timescale 1ns / 10ps
`include "std_ovl_defines.h"
module tb_req_ack;
reg clk;
reg reset;
reg req_start0, req_start1;
wire req0, req1;
wire ack0, ack1;
reg ta0, ta1;
wire [`OVL_FIRE_WIDTH-1:0] fire_ta0_ack0_as, fire_ta1_ack1_as;
wire [`OVL_FIRE_WIDTH-1:0] fire_req0_ack0_as, fire_req1_ack1_as;
parameter CLK_PERIOD = 20;
// 50MHzクロック
always begin
#(CLK_PERIOD/2) clk = 1'b1 ;
#(CLK_PERIOD/2) clk = 1'b0 ;
end
// reset
initial begin
reset = 1'b1;
#100 reset = 1'b0;
end
req_sm req_sm0 (
.clk(clk),
.reset(reset),
.req_start(req_start0),
.ack(ack0),
.req(req0)
);
req_sm req_sm1 (
.clk(clk),
.reset(reset),
.req_start(req_start1),
.ack(ack1),
.req(req1)
);
ack_sm ack_sm_i (
.clk(clk),
.reset(reset),
.req0(req0),
.req1(req1),
.ta0(ta0),
.ta1(ta1),
.ack0(ack0),
.ack1(ack1)
);
// req_start0とta0の関係を生成する
initial begin
req_start0 <= 1'b0;
ta0 <= 1'b0;
@(negedge reset); // リセットが0になるのを待つ
#100;
REQ_START_TA0(3'd1);
REQ_START_TA0(3'd2);
REQ_START_TA0(3'd3);
REQ_START_TA0(3'd2);
REQ_START_TA0(3'd1);
REQ_START_TA0(3'd3);
REQ_START_TA0(3'd2);
#200 $stop;
end
// req_start1とta1の関係を生成する
initial begin
req_start1 <= 1'b0;
ta1 <= 1'b0;
@(negedge reset); // リセットが0になるのを待つ
#100;
REQ_START_TA1(3'd2);
REQ_START_TA1(3'd1);
REQ_START_TA1(3'd2);
REQ_START_TA1(3'd3);
REQ_START_TA1(3'd3);
REQ_START_TA1(3'd1);
REQ_START_TA1(3'd2);
end
// task REQ_START_TA0
task REQ_START_TA0;
input [2:0] loop_count;
begin :REQ_START_TA0_PROCESS
integer i;
@(posedge clk); // clkの立ち上がりまでwait
#1 ; // 遅延を挟んで
req_start0 = 1'b1;
@(posedge clk); // clkの立ち上がりまでwait
#1; // 遅延を挟んで
req_start0 = 1'b0;
for(i=loop_count; i>0; i=i-1) begin
@(posedge clk);
#1;
end
ta0 = 1'b1;
@(posedge clk); // clkの立ち上がりまでwait
#1 ; // 遅延を挟んで
ta0 = 1'b0;
end
endtask
// task REQ_START_TA1
task REQ_START_TA1;
input [2:0] loop_count;
begin :REQ_START_TA1_PROCESS
integer i;
@(posedge clk); // clkの立ち上がりまでwait
#1 ; // 遅延を挟んで
req_start1 = 1'b1;
@(posedge clk); // clkの立ち上がりまでwait
#1; // 遅延を挟んで
req_start1 = 1'b0;
for(i=loop_count; i>0; i=i-1) begin
@(posedge clk);
#1;
end
ta1 = 1'b1;
@(posedge clk); // clkの立ち上がりまでwait
#1 ; // 遅延を挟んで
ta1 = 1'b0;
end
endtask
// アサーション
// ta0がアサートされた次のクロックでack0がアサートされる
ovl_next #(
`OVL_ERROR, // severity_level
1, // num_cks(1クロック後にアサート)
1, // check_overlapping (off)
1, // check_missing_start (on)
`OVL_ASSERT, // property_type
// "ERROR: ta0がアサートされた次のクロックでack0がアサートされていない",
"ERROR: ack0 isn't asserted of with the next clock that ta0 was asserted.",
`OVL_COVER_BASIC, // coverage_level
`OVL_POSEDGE, // clock_edge
`OVL_ACTIVE_HIGH, // reset_polarity
`OVL_GATE_CLOCK // gating_type
) ta0_ack0_assertion (
clk,
reset,
1'b1, // enable
ta0, // start event
ack0, // test_expr
fire_ta0_ack0_as // fire
);
// ta1がアサートされた次のクロックでack1がアサートされる
ovl_next #(
`OVL_ERROR, // severity_level
1, // num_cks(1クロック後にアサート)
1, // check_overlapping (off)
1, // check_missing_start (on)
`OVL_ASSERT, // property_type
// "ERROR: ta1がアサートされた次のクロックでack1がアサートされていない",
"ERROR: ack1 isn't asserted of with the next clock that ta1 was asserted.",
`OVL_COVER_BASIC, // coverage_level
`OVL_POSEDGE, // clock_edge
`OVL_ACTIVE_HIGH, // reset_polarity
`OVL_GATE_CLOCK // gating_type
) ta1_ack1_assertion (
clk,
reset,
1'b1, // enable
ta1, // start event
ack1, // test_expr
fire_ta1_ack1_as // fire
);
// req0アサートされた後で、ack0 が2~4クロックの間に1になる
ovl_frame #(
`OVL_ERROR, // severity_level
2, // min_cks
4, // max_cks
`OVL_IGNORE_NEW_START, // action_on_new_start
`OVL_ASSERT, // property_type
// "ERROR: req0がアサートされた後の2~4クロック後にack0が1にならない",
"ERROR: ack0 isn't asserted after 2-4 clocks after req0 was asserted.",
`OVL_COVER_BASIC, // coverage_level
`OVL_POSEDGE, // clock_edge
`OVL_ACTIVE_HIGH, // reset_polarity
`OVL_GATE_CLOCK // gating_type
) req0_ack0_assertion (
clk,
reset,
1'b1, // enable
req0, // start event
ack0, // test_expr
fire_req0_ack0_as // fire
);
// req1アサートされた後で、ack1 が2~4クロックの間に1になる
ovl_frame #(
`OVL_ERROR, // severity_level
2, // min_cks
4, // max_cks
`OVL_IGNORE_NEW_START, // action_on_new_start
`OVL_ASSERT, // property_type
// "ERROR: req1がアサートされた後の2~4クロック後にack1が1にならない",
"ERROR: ack1 isn't asserted after 2-4 clocks after req1 was asserted.",
`OVL_COVER_BASIC, // coverage_level
`OVL_POSEDGE, // clock_edge
`OVL_ACTIVE_HIGH, // reset_polarity
`OVL_GATE_CLOCK // gating_type
) req1_ack1_assertion (
clk,
reset,
1'b1, // enable
req1, // start event
ack1, // test_expr
fire_req1_ack1_as // fire
);
endmodule
`default_nettype wire
OVL_ERROR : OVL_NEXT : ERROR: ta0がアサートされた次のクロックでack0がアサートされていない : Test expression is not asserted after elapse of num_cks cycles from start event : severity 1 : time 29000 : tb_req_ack.ta0_ack0_assertion.ovl_error_t
OVL_ERROR : OVL_FRAME : ERROR: req0がアサートされた後の2~4クロック後にack0が1にならない : Test expression is not TRUE within specified maximum max_cks cycles from start event : severity 1 : time 33000 : tb_req_ack.req0_ack0_assertion.ovl_error_t
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | - | - | - | - | 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | - | - | - | - | - | - |