同步FIFO任务t_write报赋值语句左值语法错误,请求排查
Hey there, let's break down the error you're seeing in your t_write task—it's a straightforward fix once you spot it, plus I'll point out a few other tweaks to make your FIFO more robust.
The Root Cause of the Syntax Error
In Verilog, when you access elements of a memory array (like your FIFO register array), you must use square brackets [] instead of parentheses (). Your code uses parentheses for array indexing in both the t_read and t_write tasks, which is invalid syntax—this is exactly what's triggering the "l-value" error.
Here's where you went wrong:
// Wrong in t_read: RD_DATA = FIFO(READ_PTR); // Wrong in t_write: FIFO(WRITE_PTR) = WR_DATA;
Fixing the Array Indexing
Replace the parentheses with square brackets in both tasks. The corrected tasks look like this:
task automatic t_read; begin RD_DATA = FIFO[READ_PTR]; // Use [] instead of () COUNT = COUNT - 1; READ_PTR = READ_PTR + 1; end endtask task automatic t_write; begin FIFO[WRITE_PTR] = WR_DATA; // Use [] instead of () WRITE_PTR = WRITE_PTR + 1; COUNT = COUNT + 1; end endtask
Bonus: Additional Improvements for Your FIFO
While we're at it, here are a few other adjustments to make your code more flexible and correct:
- Pointer/Count Bit Width: Your
COUNT,READ_PTR, andWRITE_PTRare declared as 1-bit registers (reg COUNT = 0;). This will only work whenDdepth=2—for any larger depth, you'll get overflow issues. Change their declarations to use a width based on the depth parameter:reg [$clog2(Ddepth)-1:0] COUNT = 0; reg [$clog2(Ddepth)-1:0] READ_PTR = 0; reg [$clog2(Ddepth)-1:0] WRITE_PTR = 0;$clog2calculates the minimum number of bits needed to represent the depth (e.g., 2 bits forDdepth=4, 3 bits forDdepth=8, etc.). - Reset Logic: Your reset block checks
if(RSTB)—but since your port is namedRSTB(typically meaning active-low reset), you probably want to trigger reset whenRSTBis low. Adjust the always block to:always @(posedge CLK) begin if(!RSTB) // Active-low reset begin COUNT = 0; READ_PTR = 0; WRITE_PTR = 0; end end - Combination Logic Sensitivity: Your
always @(COUNT)block forFULLandEMPTYworks here, but usingalways @*is safer—it automatically includes all inputs to the block, preventing accidental missing sensitivity list entries:always @* begin FULL = (COUNT == Ddepth); EMPTY = (COUNT == 0); end
Full Corrected Code
Here's the complete fixed version of your FIFO module with all the above changes:
module sync_fifo #(parameter Dwidth = 16, Ddepth = 2) ( output reg [Dwidth-1:0] RD_DATA, output reg FULL, EMPTY, input [Dwidth-1:0] WR_DATA, input WRITE, READ, CLK, RSTB ); reg [$clog2(Ddepth)-1:0] COUNT = 0; reg [$clog2(Ddepth)-1:0] READ_PTR = 0; reg [$clog2(Ddepth)-1:0] WRITE_PTR = 0; reg [Dwidth-1:0] FIFO[Ddepth-1:0]; task automatic t_read; begin RD_DATA = FIFO[READ_PTR]; COUNT = COUNT - 1; READ_PTR = READ_PTR + 1; end endtask task automatic t_write; begin FIFO[WRITE_PTR] = WR_DATA; WRITE_PTR = WRITE_PTR + 1; COUNT = COUNT + 1; end endtask always @* begin FULL = (COUNT == Ddepth); EMPTY = (COUNT == 0); end always @(posedge CLK) begin if(!RSTB) begin COUNT = 0; READ_PTR = 0; WRITE_PTR = 0; end end always @(posedge CLK) begin if(!RSTB) begin if(READ & !WRITE) begin if(!EMPTY) t_read; else $display("FIFO is empty"); end end end always @(posedge CLK) begin if(!RSTB) begin if(!READ & WRITE) begin if(!FULL) t_write; else $display("FIFO is full"); end end end always @(posedge CLK) begin if(!RSTB) begin if(READ & WRITE) begin if(!EMPTY && !FULL) begin t_read; t_write; end else if(FULL) begin t_read; $display("FIFO is full"); end else if(EMPTY) begin t_write; $display("FIFO is empty"); end end end end endmodule
内容的提问来源于stack exchange,提问作者badri18

