110 lines
2.2 KiB
Systemverilog
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
|