The below code is for a FIFO. It is showing an error as illegal reference to net datatype as rddata at line 38 in tb (highlighted by adding a comment "//error line").
Why do I get this error?
module fifo(clk,rst,error,empty,full,rddata,wrdata,wr_en,rd_en);
parameter WIDTH = 8;
parameter DEPTH = 16;
input clk,rst,rd_en,wr_en;
input [WIDTH-1:0]wrdata;
output reg [WIDTH-1:0]rddata;
output reg empty,full,error;
reg [WIDTH-1:0]mem[DEPTH-1:0];
reg [3:0]rd_ptr;
reg [3:0]wr_ptr;
reg wr_toggle,rd_toggle;
integer i;
always#(posedge clk)
begin
if(rst==1)
begin
empty = 1;
full = 0;
error = 0;
rd_ptr = 0;
wr_ptr = 0;
wr_toggle = 0;
rd_toggle = 0;
for(i=1;i<DEPTH;i=i+1)
begin
mem[i] = 0;
end
end
else
begin
if(wr_en ==1)begin
if(full==1)begin
$display("ERROR:Writing to full FIFO");
error = 1;
end
else
begin
mem[wr_ptr] = wrdata;
if(wr_ptr == DEPTH-1)begin
wr_toggle = ~wr_toggle;
wr_ptr = 0;
end
else begin
wr_ptr = wr_ptr + 1;
end
end
end
if(rd_en ==1)begin
if(empty==1)begin
$display("ERROR:REading from EMPTY FIFO");
error = 1;
end
end
else
begin
mem[rd_ptr] = rddata;
if(rd_ptr == DEPTH-1)begin
rd_toggle = ~rd_toggle;
rd_ptr = 0;
end
else begin
rd_ptr = rd_ptr + 1;
end
end
end
end
always#(wr_ptr or rd_ptr)
begin
full = 0;
empty = 0;
if(wr_ptr == rd_ptr && wr_toggle == rd_toggle)begin
empty = 1;
full = 0;
end
if(wr_ptr == rd_ptr && wr_toggle != rd_toggle)begin
empty = 0;
full = 1;
end
end
endmodule
//TEST BENCH
`include "fifo.v"
module tbfifo();
parameter WIDTH = 8;
parameter DEPTH = 16;
reg clk,rst,rd_en,wr_en;
reg [WIDTH-1:0]wrdata;
wire [WIDTH-1:0]rddata;
wire empty,full,error;
integer i;
fifo_buff dut (clk,rst,error,empty,full,rddata,wrdata,wr_en,rd_en);
initial
begin
clk = 0;
forever #5 clk = ~clk;
end
initial
begin
rst = 1;
repeat(2) #(posedge clk);
rst = 0;
for(i=0;i<DEPTH;i=i+1)begin
#(posedge clk);
wr_en = 1;
wrdata = $random;
end
#(posedge clk);
wr_en = 0;
wrdata= 0;
for(i=0;i<DEPTH;i=i+1)begin
#(posedge clk);
rd_en = 1;
rddata <= $random; //error line
end
#(posedge clk);
rd_en = 0;
#100;
$finish;
end
endmodule
rddata is an output port of the fifo_buff module. In the testbench, there is a wire named rddata which connects to the fifo instance.
The problem is that the testbench then tries to drive the signal:
rddata <= $random; //error line
That is illegal. You can not make a procedural assignment (inside an initial block, for example) to a wire. And, you should not try to drive that signal from the testbench since it is already driven by the module instance, because that would results in multiple drivers (contention). You must remove this line.
for (i=0; i<DEPTH; i=i+1) begin
#(posedge clk);
rd_en = 1;
end
#(posedge clk);
rd_en = 0;
Typically, you would monitor an output signal in the testbench (display its value or compare it against a reference model). This is usually done in a separate process (always block, for example) from the input driving process.
Related
I am trying to simulate the following code for an synchronous ram in Verilog.
When I am trying to write in a specific address, dataOut is not coming the way I was expecting. It is skipping 1 address while reading data in the specified address.
Can anyone tell me the problem?
Here is GtkWave simulation result:
module ram
# (parameter ADDR_WIDTH = 4,
parameter DATA_WIDTH = 10,
parameter DEPTH = 1 << ADDR_WIDTH
)
( input clk,
input [ADDR_WIDTH-1:0] addr,
input [DATA_WIDTH-1:0] dataIn,
input enable,
input write,
input read,
input resetRam,
output[DATA_WIDTH-1:0] dataOut
);
reg [DATA_WIDTH-1:0] tmp_data;
reg [DATA_WIDTH-1:0] mem [DEPTH-1:0];
//reset
always #(posedge clk) begin
if(enable & resetRam) begin
for (integer i = 0; i < 2**ADDR_WIDTH; i = i + 1)
begin
mem[i] = {DATA_WIDTH{1'b0}};
end
end
end
//write
always # (posedge clk) begin
if (enable & write & !read)
mem[addr] <= dataIn;
end
//read
always # (posedge clk) begin
if (enable & !write & read)
tmp_data <= mem[addr];
end
assign dataOut = enable & read & !write ? tmp_data : 'hz || enable & resetRam ? 10'b0 : 'hz;
endmodule
module ram_tb;
parameter ADDR_WIDTH = 4;
parameter DATA_WIDTH = 10;
parameter DEPTH = 1 << ADDR_WIDTH;
reg clk;
reg enable;
reg write;
reg read;
reg resetRam;
reg [ADDR_WIDTH-1:0] addr;
wire [DATA_WIDTH-1:0] dataIn;
wire [DATA_WIDTH-1:0] dataOut;
reg [DATA_WIDTH-1:0] tb_data;
ram #(.DATA_WIDTH(DATA_WIDTH)) iram(
.clk(clk),
.addr(addr),
.dataIn(dataIn),
.enable(enable),
.write(write),
.read(read),
.resetRam(resetRam),
.dataOut(dataOut)
);
always #10 clk = ~clk;
assign dataIn = !read ? tb_data : 'hz ;
initial begin
$monitor("addrs = %b resetRam=%b Write = %b read=%b dataIn = %b dataOut = %b", addr,resetRam,write,read,dataIn,dataOut);
$dumpfile("ram_tb.vcd");
$dumpvars(0,ram_tb);
{clk, enable, write, addr, tb_data, read,resetRam} <= 0;
// //writing all the adrress with random value
// for (integer i = 0; i < DEPTH; i= i+1) begin
// #(posedge clk) addr <= i; write = 1; enable =1; read = 0; tb_data <= $random;
// end
// //reading them
// for (integer i = 0; i < DEPTH; i= i+1) begin
// #(posedge clk) addr = i; write = 0; enable = 1; read = 1;
// end
//Writing at specific address
#(posedge clk) addr = 4'b1000; write = 1; enable =1; read = 0; tb_data <= $random;
#(posedge clk) addr = 4'b1111; write = 1; enable =1; read = 0; tb_data <= $random;
#(posedge clk) addr = 4'b1001; write = 1; enable =1; read = 0; tb_data <= $random;
#(posedge clk) addr = 4'b0001; write = 1; enable =1; read = 0; tb_data <= $random;
//reading them
#(posedge clk) addr = 4'b1000;write = 0; enable =1; read = 1;
#(posedge clk) addr = 4'b1111;write = 0; enable =1; read = 1;
#(posedge clk) addr = 4'b1001;write = 0; enable =1; read = 1;
#(posedge clk) addr = 4'b0001;write = 0; enable =1; read = 1;
// //reset memory
// for (integer i = 0; i < DEPTH; i= i+1) begin
// repeat (1) #(posedge clk) addr <= i; enable <= 1; resetRam <=1;
// end
#200 $finish;
end
endmodule
//iverilog -o ram_tb.vpp ram.v
//vvp ram_tb.vpp
You have a race condition. You should use nonblocking assignments (<=) in your design and testbench for all synchronous signals.
In the design, change:
mem[i] = {DATA_WIDTH{1'b0}};
to:
mem[i] <= {DATA_WIDTH{1'b0}};
In the testbench, use:
//Writing at specific address
#(posedge clk) addr <= 4'b1000; write <= 1; enable <=1; read <= 0; tb_data <= $random;
#(posedge clk) addr <= 4'b1111; write <= 1; enable <=1; read <= 0; tb_data <= $random;
#(posedge clk) addr <= 4'b1001; write <= 1; enable <=1; read <= 0; tb_data <= $random;
#(posedge clk) addr <= 4'b0001; write <= 1; enable <=1; read <= 0; tb_data <= $random;
//reading them
#(posedge clk) addr <= 4'b1000;write <= 0; enable <=1; read <= 1;
#(posedge clk) addr <= 4'b1111;write <= 0; enable <=1; read <= 1;
#(posedge clk) addr <= 4'b1001;write <= 0; enable <=1; read <= 1;
#(posedge clk) addr <= 4'b0001;write <= 0; enable <=1; read <= 1;
With the above changes, I get your expected output with iverilog on edaplayground.
I'm trying to write a simple 4-bit stack of depth 8 with push/pop signals but it's behaving in a very odd manner. One of my if statements works fine and the other one does not run at all. Here's my code:
module Stack_8x4(
input wire clk,
input wire reset,
input wire push,
input wire pop,
input wire [3:0] data_in,
output reg [3:0] data_out,
output reg empty,
output reg full
);
reg [3:0] index;
reg [3:0] stack [7:0];
always #(posedge reset) begin
index <= -1;
data_out = 4'd0;
empty = 1;
full = 0;
end
always #(posedge clk) begin
if (push & !pop) begin
empty = 0;
if(!full) begin
index = index + 1;
stack[index] = data_in;
if(index > 6) full = 1;
end
end
if (pop & !push) begin
full = 0;
if(!empty) begin
data_out = stack[index];
index = index - 1;
if(index < 0) empty= 1;
end else data_out = 0;
end
end
endmodule
As you can see, the logic for push and pop is almost the same. My question is why does the line if(index < 0) empty= 1; does not work while if(index > 6) full = 1; works just fine?
Here's a test bench and simulation for more details:
module sim();
reg clk;
reg reset;
reg push;
reg pop;
reg [3:0] data_in;
wire [3:0] data_out;
wire full;
wire empty;
//wire [3:0]i;
always begin
clk = 0;
#5
clk = 1;
#5
clk = 0;
end
initial begin
// setup
reset = 1;
push = 0;
pop = 0;
data_in = 0;
#10
reset = 0;
// idle
#20
// push 1, 2, 3, 4, 5, 6, 7, 8, 9 to fill the module and test for idling at full
push = 1;
data_in = 1;
#10
data_in = 2;
#10
data_in = 3;
#10
data_in = 4;
#10
data_in = 5;
#10
data_in = 6;
#10
data_in = 7;
#10
data_in = 8;
#10
data_in = 9;
#10
data_in = 10;
#10
data_in = 11;
#10
pop = 1;
#10
push = 0;
#30
pop = 0;
push = 1;
#30
push = 0;
#20
pop = 1;
// pop
//pop = 1;
end
Stack_8x4 S (
.clk(clk),
.push(push),
.pop(pop),
.reset(reset),
.data_in(data_in),
.data_out(data_out),
.full(full),
.empty(empty)
);
endmodule
Your main issue is in the attempt to use signed data with unsigned variables. So, index <= -1;, index < 0 just do not work as you expect. My suggestion is to forget about signed arithmetic and do unsigned only.
Other issues:
you should use only a single always block to do reset and non-reset work.
you should use non-blocking assignments everywhere in your always #posedge blocks
for some reason you do not use 2 elements in your stack (6, 7) due to 'index < 6'.
So, here is my re-write of your code:
always #(posedge clk) begin
if (reset) begin
index <= 0;
data_out <= 4'd0;
empty <= 1;
full <= 0;
end
else if (push & !pop) begin
if(index < 8) begin
full<= 0;
stack[index] <= data_in;
index <= index + 1;
end
else
full <= 1;
end
else if (pop & !push) begin
if(index == 0) begin
empty <= 1;
data_out <= 0;
end
else begin
empty <= 0;
index <= index - 1;
data_out <= stack[index];
end
end // if (pop & !push)
end // always # (posedge clk)
i wrote a fifo in system verilog
i try to push some data to this fifo (i wrote a tb) and when i push data the fifo_wr_ptr, fifo_fre_space,fifo_used_space don't update (only data write to mem[0])
i will be glad for help (why my ptr don't increment by 1 for example)
Thanks alot!
and here is my simulation that shows my problem:
i attached my code:
module fifo
#(parameter WIDTH = 32, parameter DEPTH = 64 ) ( clk, rst_l, sw_rst, fifo_din, fifo_push_en, fifo_pop_en, fifo_dout, fifo_o_full, fifo_o_empty, fifo_used_space, fifo_free_space );
function integer log2; //can use the $clog2() function
input [31:0] value;
reg [31:0] value_tmp;
begin value_tmp = value; for(log2=0; value_tmp>0; log2=log2+1)
value_tmp=(value_tmp>>1);
end endfunction
localparam DEPTH_LOG2 = log2(DEPTH);
//interface input clk; input rst_l; input sw_rst; input[WIDTH-1:0] fifo_din; input fifo_push_en; input fifo_pop_en; output logic[WIDTH-1:0] fifo_dout; output logic fifo_o_full; output logic fifo_o_empty; output logic[DEPTH_LOG2-1:0] fifo_used_space; output logic[DEPTH_LOG2-1:0] fifo_free_space; logic debug_flag; //internal logic logic[WIDTH-1:0] mem[DEPTH_LOG2-1:0]; logic[DEPTH_LOG2-1:0] fifo_rd_ptr,fifo_wr_ptr;
assign fifo_o_empty = (fifo_used_space==0); assign fifo_o_full = (fifo_free_space==0);
always # (posedge clk or negedge rst_l) begin if(~rst_l) begin
fifo_free_space <= DEPTH;
fifo_used_space <= 0;
fifo_rd_ptr <= 0;
fifo_wr_ptr <= 0;
debug_flag <=0 ;
end else if (~sw_rst) begin
fifo_free_space <= DEPTH;
fifo_used_space <= 0;
fifo_rd_ptr <= 0;
fifo_wr_ptr <= 0;
debug_flag <= 0;
end else if(fifo_push_en==1 && fifo_o_full==0 && fifo_pop_en==0) begin //the fifo isn't full and can perform the write trasaction (and no read transaction)
fifo_used_space <= fifo_used_space + 1;
fifo_free_space <= fifo_free_space - 1;
mem[fifo_wr_ptr]<= fifo_din;
debug_flag <= 1;
if(fifo_wr_ptr == (DEPTH - 1))
fifo_wr_ptr <= 0;
else
fifo_wr_ptr++;
end else if (fifo_pop_en==1 && fifo_o_empty==0 && fifo_push_en==0) begin // the fifo isn't empty and can perform the read trasaction (and no write trasaction)
fifo_used_space <= fifo_used_space - 1;
fifo_free_space <= fifo_free_space + 1;
fifo_dout <= mem[fifo_rd_ptr];
if(fifo_rd_ptr == (DEPTH - 1)) begin
fifo_rd_ptr <= 0;
end else begin
fifo_rd_ptr <= fifo_rd_ptr + 1;
end end else begin
fifo_rd_ptr <= fifo_rd_ptr;
//fifo_wr_ptr <= fifo_wr_ptr;
//fifo_dout <= fifo_dout;
//fifo_used_space <= fifo_used_space;
fifo_free_space <= fifo_free_space; end end
endmodule
and here is the tb code:
`define WIDTH 32
`define DEPTH 64
module fifo_tb();
function integer log2; //can use the $clog2() function
input [31:0] value;
reg [31:0] value_tmp;
begin
value_tmp = value;
for(log2=0; value_tmp>0; log2=log2+1)
value_tmp=(value_tmp>>1);
end
endfunction
localparam DEPTH_LOG2 = log2(`DEPTH);
logic clk,rst_l,sw_rst,fifo_push_en,fifo_pop_en,fifo_o_full,fifo_o_empty;
logic[`WIDTH-1:0] fifo_din,fifo_dout,tempdata;
logic[DEPTH_LOG2-1:0] fifo_used_space,fifo_free_space;
fifo #(`WIDTH,`DEPTH) ff(.clk(clk), .rst_l(rst_l), .sw_rst(sw_rst), .fifo_din(fifo_din),
.fifo_push_en(fifo_push_en), .fifo_pop_en(fifo_pop_en),
.fifo_dout(fifo_dout), .fifo_o_full(fifo_o_full), .fifo_o_empty(fifo_o_empty),
.fifo_used_space(fifo_used_space), .fifo_free_space(fifo_free_space) );
initial
begin
clk =0;
rst_l = 0;
sw_rst= 0;
fifo_push_en=0;
fifo_pop_en=0;
fifo_din=0;
tempdata=0;
#15 rst_l=1;
#1 sw_rst=1;
push(10);
push(20);
push(30);
push(40);
pop(tempdata);
push(tempdata);
end
always
#5 clk=~clk;
task push;
input[`WIDTH-1:0] data;
if(fifo_o_full)
$display("--- Cannot push: Buffer full ----");
else begin
$display("Pushed: ",data);
#(posedge clk);
fifo_din = data;
fifo_push_en=1;
#(posedge clk);
fifo_push_en=0;
end
endtask
task pop;
output [`WIDTH-1:0] data;
if(fifo_o_empty)
$display("Cannot pop: buffer empty ---");
else begin
#(posedge clk);
fifo_pop_en=1;
#(posedge clk);
fifo_pop_en=0;
data=fifo_dout;
$display("----- Poped : ",data);
end
endtask
endmodule
Taking aside the oddity related to pointer incrementation, the code itself is confusing and difficult to deal with. Pasting reference FIFO module that should do the job, this also should help you to grasp on basics of coding style.
//----------------------------------------------------
// Module Name: fifo_sync.v
//----------------------------------------------------
// Description: generic sync FIFO module
//----------------------------------------------------
module fifo_sync #
(
parameter FIFO_DATA_WIDTH = 'd32,
parameter FIFO_PTR_WIDTH = 'd6
)
(
//------------------------------------------------
// Inputs
//------------------------------------------------
input clk,
input rst_n,
input wr_en,
input [FIFO_DATA_WIDTH-1:0] wr_data,
input rd_en,
//------------------------------------------------
// Outputs
//------------------------------------------------
output reg [FIFO_DATA_WIDTH-1:0] rd_data,
output stat_full,
output stat_empty,
output [ FIFO_PTR_WIDTH-1:0] stat_occupancy
);
//------------------------------------------------
// Local Parameters
//------------------------------------------------
localparam FIFO_DEPTH = 2**(FIFO_PTR_WIDTH-1);
//------------------------------------------------
// Internal Register(s)/Wire(s)/Integer(s)
//------------------------------------------------
reg [ FIFO_PTR_WIDTH-1:0] wr_ptr;
reg [ FIFO_PTR_WIDTH-1:0] rd_ptr;
reg [FIFO_DATA_WIDTH-1:0] fifo_array [FIFO_DEPTH-1:0];
integer int_i;
//------------------------------------------------
// Write Pointer Logic
//------------------------------------------------
always #(posedge clk or negedge rst_n)
begin: p_wr_ptr
if (!rst_n)
wr_ptr <= {FIFO_PTR_WIDTH{1'b0}};
else if (wr_en & !stat_full)
wr_ptr <= wr_ptr + 1'b1;
end
//------------------------------------------------
// Read Pointer Logic
//------------------------------------------------
always #(posedge clk or negedge rst_n)
begin: p_rd_ptr
if (!rst_n)
rd_ptr <= {FIFO_PTR_WIDTH{1'b0}};
else if (rd_en & !stat_empty)
rd_ptr <= rd_ptr + 1'b1;
end
//------------------------------------------------
// Status Interface
//------------------------------------------------
// FIFO full status flag
assign stat_full = (wr_ptr[FIFO_PTR_WIDTH-1] ^ rd_ptr[FIFO_PTR_WIDTH-1]) & (wr_ptr[FIFO_PTR_WIDTH-2:0] == rd_ptr[FIFO_PTR_WIDTH-2:0]);
// FIFO empty status flag
assign stat_empty = (wr_ptr == rd_ptr);
// FIFO occupancy status
assign stat_occupancy = wr_ptr - rd_ptr;
//-----------------------------------------------
// FIFO Write
//-----------------------------------------------
always #(posedge clk or negedge rst_n)
begin: p_fifo_write
if (!rst_n)
for (int_i = 0; int_i < FIFO_DEPTH - 1; int_i = int_i + 1)
fifo_array[int_i] <= {FIFO_DATA_WIDTH{1'b0}};
else if (wr_en & !stat_full)
fifo_array[wr_ptr] <= wr_data;
end
//-----------------------------------------------
// FIFO Read
//-----------------------------------------------
always #(posedge clk or negedge rst_n)
begin: p_fifo_read
if (!rst_n)
rd_data <= {FIFO_DATA_WIDTH{1'b0}};
else if (rd_en & !stat_empty)
rd_data <= fifo_array[rd_ptr];
end
endmodule
I'm trying to create an I2C protocol in verilog to read data from a sensor (TMP007)then show the data received using led but to no avail. I've been trying to put led (eg. LED_GREEN[2] =1;) in the state to test the flow of the state. Only the LED_GREEN1 and LED_GREEN[0] are lighten up. So I guess the problem does occur in STATE_WACK2. Anyone can help?
module tmpi2c(
input wire clk,
input wire reset,
inout reg i2c_sda,
output wire i2c_scl,
output reg [17:0] LED_RED, // LED Red[17:0]
output reg [7:0] LED_GREEN
);
// write to device address 0x40, 0x01h
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_WACK2 = 6;
localparam STATE_ADDR2 = 7;
localparam STATE_RW2 = 8;
localparam STATE_WACK3 = 9;
localparam STATE_READ = 10;
localparam STATE_WACK4 = 11;
localparam STATE_READ2 = 12;
localparam STATE_WACK5 = 13;
localparam STATE_STOP = 14;
localparam STATE_DISPLAY = 15;
reg enable; //(r=1, w=0)
reg clki2c = 0;
reg [9:0]counter = 0; // 10-bit counter size
reg [9:0] timer = 0;
reg [7:0] state;
reg [6:0] addr;
reg [7:0] data;
reg [7:0] count;
reg [15:0] value =0;
reg [4:0] ge,shi,bai;
reg i2c_scl_enable =0;
assign i2c_scl = (i2c_scl_enable == 0) ? 1 : ~clki2c;
reg i2c_sda_en;
wire i2c_sda_in = i2c_sda ;
// counter size calculation according to input and output frequencies
parameter sys_clk = 50000000; // 50 MHz system clock
//parameter clk_out = 400000; // 0.4 MHz clock output
parameter clk_out = 200000; // 0.2 MHz clock output
//parameter clk_out = 1; // 1Hz clock output
parameter max = sys_clk / (2*clk_out); // max-counter size
//clock divider from 50Mhz to 0.4Mhz
always#(posedge clk or posedge reset)
begin
if(reset) begin
counter <=0;
clki2c <= 0;
end
else begin
if (counter < max) begin
counter <= counter + 1'd1;
end
else begin
counter <= 0;
clki2c <= ~clki2c;
end
end
end
//end clock divider
always#(posedge clki2c) begin
if (!i2c_sda_en) begin i2c_sda = i2c_sda ;
end else begin
i2c_sda = 1'bz;
end
if (reset == 1)
begin
state <= 0;
//i2c_sda <= 1;
//i2c_scl <= 1;
i2c_sda_en <= 1;// i2c_sda ==z;
addr <= 7'h40;
count <= 8'd0;
data <= 8'h01;
LED_RED[17:0] = 0;
LED_GREEN[7:0] = 0;
end
else begin
case(state)
STATE_IDLE: begin //idle
state <= STATE_START;
end
STATE_START: begin //start
i2c_sda_en <= 0;
state <=STATE_ADDR;
count <= 6;
end
STATE_ADDR: begin //msb address bit
LED_GREEN[0] =1;
i2c_sda <= addr[count];
if (count ==0) state <= STATE_RW;
else count <= count -1;
end
STATE_RW: begin
i2c_sda <=0; //write here
state <=STATE_WACK;
end
STATE_WACK: begin
i2c_sda_en <= 1;
if(i2c_sda_in==1)
begin
state <= STATE_WACK;
end
else
begin
state <= STATE_DATA;
end
count <= 7 ;
i2c_sda_en <= 0;
end
STATE_DATA: begin
LED_GREEN[1] =1;
i2c_sda <= data[count];
if (count == 0) state <= STATE_WACK2;
else count <= count -1;
end
STATE_WACK2: begin
i2c_sda_en <= 1;
if(i2c_sda_in==1)
begin
state <= STATE_WACK2;
end
else
begin
state <= STATE_ADDR2;
//LED_GREEN[1] =1;
end
count <= 6;
i2c_sda_en <= 0;
end
STATE_ADDR2: begin
LED_GREEN[2] =1;
i2c_sda <= addr[count];
if (count ==0) state <= STATE_RW2;
else count <= count -1;
end
STATE_RW2: begin
i2c_sda <=1; //read here
state <=STATE_WACK3;
end
STATE_WACK3: begin
i2c_sda_en <= 1;
if(i2c_sda_in==1)
begin
state <= STATE_WACK2;
end
else
begin
state <= STATE_READ;
end
count <= 15;
//i2c_sda_en <= 0;
end
STATE_READ: begin
LED_GREEN[3] =1;
value[count] <= i2c_sda_in;
if (count == 8) state<= STATE_WACK4;
else count <= count -1;
end
STATE_WACK4: begin
i2c_sda_en <= 0;
i2c_sda <=1; //Master should leave SDA high to terminate a single-byte read operation.
state <= STATE_READ2;
count <= 7;
i2c_sda_en <= 1;
end
STATE_READ2: begin
LED_GREEN[4] =1;
value[count] <= i2c_sda_in;
if (count == 0) state<= STATE_WACK5;
else count <= count -1;
end
STATE_WACK5: begin
i2c_sda_en <= 0;
i2c_sda <=1; //Master should leave SDA high to terminate a two-byte read operation.
state <= STATE_STOP;
end
STATE_STOP: begin
//i2c_sda <=1;
state <= STATE_DISPLAY;
end
STATE_DISPLAY: begin
LED_RED[17] = value[15];
LED_RED[16] = value[14];
LED_RED[15] = value[13];
LED_RED[14] = value[12];
LED_RED[13] = value[11];
LED_RED[12] = value[10];
LED_RED[11] = value[9];
LED_RED[10] = value[8];
LED_RED[9] = value[7];
LED_RED[8] = value[6];
LED_RED[7] = value[5];
LED_RED[6] = value[4];
LED_RED[5] = value[3];
LED_RED[4] = value[2];
LED_RED[2] = value[0];
LED_RED[3] = value[1];
//display delay
if (timer < 100000) timer <= timer+1;
else timer <= 0;
state <= STATE_IDLE;
end
endcase
end
end
endmodule
I'm trying to make an I2C protocol on Verilog, and I was typing what this guy was typing (a video on YouTube that explains how to make a I2C BUS protocol)
module step1(
input wire clk,
input wire reset,
output reg i2c_sda,
output reg i2c_scl
);
//goal is to write to device addres 0x50, 0xaa
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 [6:0] addr;
reg [7:0] data;
reg [7:0] count;
always #(posedge clk) begin
if (reset == 1) begin
state <= 0;
i2c_sda <= 1;
i2c_scl <= 1;
addr <= 7'h50;
count <= 8'd0;
data <= 8'haa;
end
else begin
case(state)
STATE_IDLE: begin //idle
i2c_sda <= 1;
state <= STATE_START;
end // end state idle
STATE_START: begin //start
i2c_sda <= 1;
state <= STATE_ADDR;
count <= 6;
end // end of state start
STATE_ADDR: begin // fisrt addres bit or the most significant adress bit
i2c_sda <= addr[count];
if (count == 0) state <= STATE_RW;
else count <= count - 1;
end // end of state ADDR
STATE_RW: begin // Read or Write opperation
i2c_sda <= 1;
state <= STATE_WACK;
end // end state RW
STATE_WACK: begin
state <= STATE_DATA;
count <= 7;
end // end of state WACK
STATE_DATA: begin
i2c_sda <= data[count];
if (count == 0) state <= STATE_WACK2;
else count <= count-1;
end // end of state DATA
STATE_WACK2: begin
state <= STATE_STOP;
end // end state WACK2
STATE_STOP: begin
i2c_sda <= 1;
state <= STATE_IDLE;
end // end of state STOP
end// end of case
end // end of the else
end // end of if
endmodule
But, when I try to compile, the following error pops out. I really don't understand why, because all end are correct (at least for me):
ERROR:HDLCompiler:806 - "/home/yunta23/Documentos/Digital1/VideosYou/primero/step1/step1.v" Line 97: Syntax error near "end".
A case statement requires the endcase keyword, not an end keyword. Change:
end// end of case
to:
endcase