`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