125 lines
2.7 KiB
Verilog
125 lines
2.7 KiB
Verilog
`timescale 1ns/1ps
|
|
|
|
module tb_cdc_strobe_data;
|
|
|
|
localparam integer WIDTH = 16;
|
|
localparam integer NUM_TX = 5;
|
|
|
|
// Source domain
|
|
reg s_clk;
|
|
reg s_rst;
|
|
reg s_pulse;
|
|
reg [WIDTH-1:0] s_data;
|
|
wire s_busy;
|
|
wire s_accepted;
|
|
|
|
// Destination domain
|
|
reg d_clk;
|
|
reg d_rst;
|
|
wire d_pulse;
|
|
wire [WIDTH-1:0] d_data;
|
|
|
|
reg [WIDTH-1:0] exp_data [0:NUM_TX-1];
|
|
integer rx_idx;
|
|
integer tx_idx;
|
|
|
|
cdc_strobe_data #(
|
|
.WIDTH(WIDTH),
|
|
.STABLE_SAMPLES(2)
|
|
) dut (
|
|
.s_clk(s_clk),
|
|
.s_rst(s_rst),
|
|
.s_pulse(s_pulse),
|
|
.s_data(s_data),
|
|
.s_busy(s_busy),
|
|
.s_accepted(s_accepted),
|
|
.d_clk(d_clk),
|
|
.d_rst(d_rst),
|
|
.d_pulse(d_pulse),
|
|
.d_data(d_data)
|
|
);
|
|
|
|
initial s_clk = 1'b0;
|
|
always #625 s_clk = ~s_clk; // 800 kHz
|
|
|
|
initial d_clk = 1'b0;
|
|
always #33.333 d_clk = ~d_clk; // 15 MHz (asynchronous to s_clk)
|
|
|
|
task send_word;
|
|
input [WIDTH-1:0] value;
|
|
begin
|
|
@(posedge s_clk);
|
|
while (s_busy)
|
|
@(posedge s_clk);
|
|
|
|
s_data <= value;
|
|
s_pulse <= 1'b1;
|
|
@(posedge s_clk);
|
|
|
|
if (!s_accepted) begin
|
|
$display("[%0t] ERROR: expected s_accepted for value 0x%0h", $time, value);
|
|
$fatal(1);
|
|
end
|
|
|
|
s_pulse <= 1'b0;
|
|
s_data <= {WIDTH{1'b0}};
|
|
end
|
|
endtask
|
|
|
|
always @(posedge d_clk) begin
|
|
if (!d_rst && d_pulse) begin
|
|
if (rx_idx >= NUM_TX) begin
|
|
$display("[%0t] ERROR: unexpected extra d_pulse with data=0x%0h", $time, d_data);
|
|
$fatal(1);
|
|
end
|
|
|
|
if (d_data !== exp_data[rx_idx]) begin
|
|
$display("[%0t] ERROR: rx[%0d] expected 0x%0h, got 0x%0h",
|
|
$time, rx_idx, exp_data[rx_idx], d_data);
|
|
$fatal(1);
|
|
end
|
|
|
|
$display("[%0t] INFO: rx[%0d] = 0x%0h", $time, rx_idx, d_data);
|
|
rx_idx <= rx_idx + 1;
|
|
end
|
|
end
|
|
|
|
initial begin
|
|
$dumpfile("out.vcd");
|
|
$dumpvars(0, tb_cdc_strobe_data);
|
|
|
|
s_rst = 1'b1;
|
|
d_rst = 1'b1;
|
|
s_pulse = 1'b0;
|
|
s_data = {WIDTH{1'b0}};
|
|
rx_idx = 0;
|
|
tx_idx = 0;
|
|
|
|
exp_data[0] = 16'h1234;
|
|
exp_data[1] = 16'h00A5;
|
|
exp_data[2] = 16'hBEEF;
|
|
exp_data[3] = 16'h5AA5;
|
|
exp_data[4] = 16'hCAFE;
|
|
|
|
repeat (4) @(posedge s_clk);
|
|
s_rst = 1'b0;
|
|
repeat (3) @(posedge d_clk);
|
|
d_rst = 1'b0;
|
|
|
|
for (tx_idx = 0; tx_idx < NUM_TX; tx_idx = tx_idx + 1)
|
|
send_word(exp_data[tx_idx]);
|
|
|
|
wait (rx_idx == NUM_TX);
|
|
$display("[%0t] PASS: received %0d/%0d transfers correctly", $time, rx_idx, NUM_TX);
|
|
#20;
|
|
$finish;
|
|
end
|
|
|
|
initial begin
|
|
#100000000;
|
|
$display("[%0t] ERROR: timeout waiting for transfers", $time);
|
|
$fatal(1);
|
|
end
|
|
|
|
endmodule
|