Qazi Zabeer
unread,Jun 5, 2023, 6:15:12 PM6/5/23You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
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.