Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How can I stop the simualtion at stop bit for i2c master verilog code?

25 views
Skip to first unread message

Qazi Zabeer

unread,
Jun 5, 2023, 6:15:12 PM6/5/23
to

I am trying to write Verilog code for I2C master and there are a couple of problems I am facing. I was able to compile and run its testbench on Quartus and modelsim, respectively.However, what I am trying to do is to have it swtich back to reset mode on(reset = 1) once the state reaches STATE_STOP(Basically have it stay in STATE_IDLE), so what can I add to either the code or the testbench to make it that way? The simulation continues after STATE_STOP, which I am not able to understand, and so I have to, at an arbitrary time, add either $finish or reset = 1 in the testbench. Here is the code:

`timescale 1ns/1ps

module I2C_Master(
input wire clk,
input wire reset,
input wire [7:0]data,
input wire [6:0]add,
input wire readorwrite,
output reg i2c_sda,
output reg i2c_scl
);

localparam STATE_IDLE = 0;
localparam STATE_START = 1;
localparam STATE_ADDR = 2;
localparam STATE_RW = 3;
localparam STATE_WACK = 4;
localparam STATE_DATA = 5;
localparam STATE_STOP = 6;
localparam STATE_WACK2 = 7;


reg [7:0] state;
reg [7:0] count;

always @(posedge clk) begin
if (reset == 1)
i2c_scl <= 1;
else begin
if (state == STATE_START)
i2c_scl <= 0;
else if (state == STATE_IDLE || state == STATE_STOP)
i2c_scl <= 1;
else
i2c_scl <= ~i2c_scl;
end
end

always @(posedge clk) begin
if (reset == 1) begin
state <= 0;
i2c_sda <= 1;
count <= 8'd0;
end
else begin
case(state)

STATE_IDLE: begin
i2c_sda <= 1;
state <= STATE_START;
end

STATE_START: begin
i2c_sda <= 0;
state <= STATE_ADDR;
count <= 6;
end

STATE_ADDR: begin
i2c_sda <= add[count];
if (count == 0) state <= STATE_RW;
else count <= count - 1;
end

STATE_RW: begin
i2c_sda <= readorwrite;
state <= STATE_WACK;
end

STATE_WACK: begin
i2c_sda <= 0;
state <= STATE_DATA;
count <= 7;
end

STATE_DATA: begin
i2c_sda <= data[count];
if (count == 0) state <= STATE_WACK;
else count <= count - 1;
end

STATE_WACK2: begin
i2c_sda <= readorwrite;
state <= STATE_STOP;
end

STATE_STOP: begin
i2c_sda <= 0;
end
endcase
end

end
endmodule
The testbench:

module I2C_MasterTB;

reg clk;
reg reset;
reg [7:0]data;
reg [6:0]add;
reg readorwrite;

wire i2c_sda;
wire i2c_scl;

I2C_Master uut (
.clk(clk),
.reset(reset),
.data(data),
.add(add),
.readorwrite(readorwrite),
.i2c_sda(i2c_sda),
.i2c_scl(i2c_scl)
);

initial begin
clk = 0;
forever begin
clk = #1 ~clk;
end
end

initial begin
reset = 1;
add <= 7'h50;
data <= 8'haa;
readorwrite <= 0;

#10;

reset = 0;

#100;

reset = 1;

end

endmodule
As I already mentioned, I only arbitrarly chose a time period to finish the simulation, but I cant seem to think of the way to the end the simulation as soon as it reaches the last state and have it stay in idle state.

Charlie

unread,
Jun 5, 2023, 8:51:33 PM6/5/23
to
It looks like your 'state machine' goes into a loop at STATE_DATA and
never gets to STATE_STOP.

STATE_DATA line now: if (count == 0) state <= STATE_WACK;

Probably should be: if (count == 0) state <= STATE_WACK2;

Note the 2 at the end.

Charlie

<snip>

0 new messages