2022-06-14 12:50:47 +03:00

110 lines
2.2 KiB
Systemverilog

`timescale 1ps/1ps
/* verilator lint_off DECLFILENAME */
/* verilator lint_off MULTITOP */
/* verilator lint_off STMTDLY */
/* verilator lint_off INFINITELOOP */
/* verilator lint_off INITIALDLY */
module i2c_receiver_tb;
logic clock = 1'b0;
logic reset = 1'b1;
/* Master clock 100MHz (10ns period) */
always #(10ns/2) clock = ~clock;
parameter SCL_PERIOD = 364793; // ~300ns
logic scl_async;
logic sda_async;
event scl_low_ev;
event scl_high_ev;
initial begin
scl_async = 1'b1;
forever begin
#(SCL_PERIOD/4) scl_async = 1'b1;
#(SCL_PERIOD/4) -> scl_high_ev;
#(SCL_PERIOD/4) scl_async = 1'b0;
#(SCL_PERIOD/4) -> scl_low_ev;
end
end
logic i_scl;
logic i_sdi;
logic o_sdo;
logic [7:0] o_data;
logic o_strobe;
logic o_start;
logic o_stop;
logic i_ack;
i2c_receiver DUT (.*);
logic [1:0] scl_sync;
logic [1:0] sda_sync;
always_ff @(posedge clock)
if (reset) begin
scl_sync <= '1;
sda_sync <= '1;
end
else begin
scl_sync <= {scl_sync[0], scl_async};
sda_sync <= {sda_sync[0], sda_async};
end
assign i_scl = scl_sync[1];
assign i_sdi = sda_sync[1];
task send_start;
wait(scl_async == 1'b0);
sda_async = 1'b1;
@(scl_high_ev);
sda_async = 1'b0;
endtask
task send_stop;
wait(scl_async == 1'b0);
sda_async = 1'b0;
@(scl_high_ev);
sda_async = 1'b1;
endtask
task send_byte(logic [7:0] b);
for (int n = 7; n >= 0; n -= 1) begin
@(scl_low_ev);
sda_async = b[n];
end
@(scl_low_ev);
wait(scl_async == 1'b1);
endtask
initial begin
reset = 1'b1;
repeat(2) @(posedge clock) #1;
reset = 1'b0;
repeat(2) @(posedge clock) #1;
i_ack = 1'b1;
send_start;
send_byte(8'h6a);
send_byte(8'ha5);
send_stop;
repeat(1000) @(posedge clock) #1;
$finish;
end
`ifdef DUMP
initial begin
$dumpfile("i2c_receiver_tb.fst");
$dumpvars(0, i2c_receiver_tb);
end
`endif
endmodule // i2c_receiver_tb