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

112 lines
2.4 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_io_output_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
parameter IO_BYTES_COUNT = 2;
parameter [6:0] I2C_ADDRESS = 7'h5a;
localparam DATA_WIDTH = IO_BYTES_COUNT * 8;
logic i_scl;
logic i_sdi;
logic o_sdo;
logic [DATA_WIDTH-1:0] o_data;
i2c_io_output #(.I2C_ADDR(I2C_ADDRESS),
.IO_BYTES_COUNT(IO_BYTES_COUNT))
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;
send_start;
send_byte(8'hb4);
send_byte(8'ha5);
send_byte(8'h38);
send_byte(8'h42);
send_stop;
repeat(1000) @(posedge clock) #1;
$finish;
end
`ifdef DUMP
initial begin
$dumpfile("i2c_io_output_tb.fst");
$dumpvars(0, i2c_io_output_tb);
end
`endif
endmodule // i2c_io_output_tb