Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Synchronous FIFO design code review

+1
−0

As a personal project, I have designed a synchronous FIFO in Verilog HDL. But while testing with a testbench, I observed that the FIFO values are flushed out after one clock cycle when read-enable is triggered but not exactly when the read-enable is triggered(i.e rd_en=1). I request for some help in this case like why it is happening and how to fix it. I have pasted my console output here and the waveforms output of dut signals here.

Signals of FIFO

wr_data --> writes data into FIFO
wr_en   --> write enable, required to write data into FIFO
rd_data --> reads data from the FIFO
rd_en   --> read enable, required to read data from the FIFO
full    --> tells the status of FIFO is full or not
empty   --> tells the status of FIFO is empty or not
wr_ptr  --> write pointer
rd_ptr  --> read pointer
clk     --> clock
rst     --> reset
sync_fifo -> this is the actual FIFO memory

Verilog Design Code:

 `// Code your design here
 module sync_fifo_design(wr_data,wr_en,rd_data,rd_en,full,empty,clk,rst);

//Input and Output declarations
parameter data_width = 8;
parameter depth = 256;
input [data_width-1:0]wr_data;
input wr_en,rd_en,clk,rst;
output reg [data_width-1:0]rd_data;
output reg full,empty;

//here address width i.e for pointers is logarithmically related to depth of fifo
reg [$clog2(depth)-1:0]wr_ptr,rd_ptr;
reg [data_width-1:0]sync_fifo[0:depth-1];

initial begin
 wr_ptr=0;
 rd_ptr=0;  
end

//full and empty conditions
always@(*) begin
 if(rd_ptr==wr_ptr+1)
  full<=1'b1;
 else
  full<=1'b0;

 if(rd_ptr==wr_ptr)
   empty<=1'b1;
 else
   empty<=1'b0;
 end

//reset
always@(posedge clk) begin
 if(rst) begin
  wr_ptr<=0;
  rd_ptr<=0;
  rd_data<=0;
 end
end

 //Writing data into fifo
always@(posedge clk) begin
 if(wr_en && !full) begin
    sync_fifo[wr_ptr]<=wr_data;
    wr_ptr<=wr_ptr+1;
 end
end

//read data from fifo
always@(posedge clk)begin
 if(rd_en && !empty)begin
   rd_data<=sync_fifo[rd_ptr];
    rd_ptr<=rd_ptr+1;
 end
end
endmodule `

Testbench Code:

`module tb();
 //input and output signals declaration
 parameter data_width = 8;
 reg [data_width-1:0]wr_data;
 reg wr_en,rd_en,clk,rst;
 wire [data_width-1:0]rd_data;
 wire full,empty;

 //module instantiation
sync_fifo_design dut(.wr_data(wr_data),.wr_en(wr_en),.rd_data(rd_data),.rd_en(rd_en),.full(full),.empty(empty),.clk(clk),.rst(rst));

 //stimuli
initial begin
 clk=0;
 rst=1;
 wr_en=0;
 rd_en=0;
 rst=0;
 //writing values 5,10,15,20 into FIFO

 @(posedge clk)wr_en=1;wr_data=3'b101;
 @(posedge clk)wr_data=4'b1010;
 @(posedge clk)wr_data=4'b1111;
 @(posedge clk)wr_data=5'b10100;
 @(posedge clk)wr_en=0;rd_en=1;
 end

 always
  #1 clk=~clk;
 initial begin
  $monitor("wr_data =%d,wr_en=%b,rd_en=%b,rst=%b,rd_data=%d",wr_data,wr_en,rd_en,rst,rd_data);
  $dumpfile("dump.vcd"); $dumpvars;
  #30 $finish;
 end
endmodule`
History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

1 answer

+0
−0

Your current FIFO acts as a standard FIFO. What you desire is a First Word Fall Through (FWFT) FIFO or a showahead FIFO. Changing the rd_data to be combinational logic instead of registered logic is the way to do this, the modification would look like this:

//read data from fifo

always@(posedge clk)begin 
  if(rd_en && !empty)begin 
     //rd_data<=sync_fifo[rd_ptr]; // this would yield a value next cc
      rd_ptr<=rd_ptr+1;
  end
end

// remove 'reg' from rd_data port and make a continuous assignment
assign rd_data = sync_fifo[rd_ptr];

An image of GTKWave output from a simulation of the modified FIFO HDL that acts like a FWFT FIFO

Changing the read enable (rd_en) net name to a read acknowledge (rd_ack) may be a more descriptive label in this case.

More information can be found at places like Eli Billauer's spin-off FPGA blog: https://www.01signal.com/using-ip/fpga-fifo/variants/

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.

0 comment threads

Sign up to answer this question »