Files
fpga_modem/sim/tb/tb_cdc_strobe_data.v

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