I'm writing my first ever I2C program in Verilog and I'm struggling with the TestBench.
I want to test the I2C Slave in isolation, but I'm unable to set different SDA values: SDA is always 1, or X.
Am I going about testing the wrong way? My thoughts are I should be able to on every clock, set the SDA and see what happens.
Playground here: https://edaplayground.com/x/6snM
module Slave(
inout SDA,
input SCL);
reg [4:0] IDLE = 4'b0000;
reg [4:0] START = 4'b0001;
reg [4:0] ADDRESS = 4'b0010;
reg [4:0] READ_WRITE = 4'b0011;
reg [4:0] DATA = 4'b0100;
reg [4:0] WRITE_ACK = 4'b0101;
reg [4:0] STOP = 4'b0110;
reg [4:0] state = 4'b0000;
reg [6:0] slaveAddress = 7'b0001000;
reg [6:0] addressCounter = 7'b0000000;
reg readWrite = 1'b0;
reg write_ack = 0;
assign SDA = write_ack ? 0 : 1'bz;
always @(posedge SCL)
begin
case (state)
IDLE:
begin
if (SDA == 0 && SCL == 1)
begin
state <= ADDRESS;
end
end
START:
begin
readWrite <= 0;
end
ADDRESS:
begin
if (slaveAddress[addressCounter] != SDA)
begin
state <= STOP;
addressCounter <= 0;
end
addressCounter <= addressCounter + 1;
if (addressCounter >= 6)
begin
write_ack <= 1;
state <= READ_WRITE;
end
end
READ_WRITE:
begin
write_ack <= 0;
state <= DATA;
end
endcase
end
endmodule
I want to drive SDA so that I can pass in a sequence of bits, but whatever I do, SDA remains the same (1) or X.
module Slave_TB ();
reg clk;
wire SDA;
wire SCL;
pullup(SDA);
pullup(SCL);
reg [8:0] bitsToSend = 9'b000100010;
integer ii=0;
initial begin
clk = 0;
forever begin
clk = #1 ~clk;
end
end
Slave UUT
(.SDA(SDA),
.SCL(SCL));
initial
begin
$display("Starting Testbench...");
clk = 0;
force SCL = clk;
#10
for(ii=0; ii<9; ii=ii+1)
$display("SDA %h to %h", SDA, bitsToSend[ii]);
#1 force SDA = bitsToSend[ii];
#10;
$finish();
end
initial
begin
// Required to dump signals to EPWave
$dumpfile("dump.vcd");
$dumpvars(0);
end
endmodule