Resolving a warning in verilog: read after blocking assignment in same process - verilog

I've this code which is throwing some warning messages which I'm trying to resolve.
module someModuleName(...)
...
...
reg [3:0] i;
wire [3:0] onstate_count;
wire [3:0] ack_count;
reg [3:0] j;
bit switchState;
always #(*) begin :EVAL_ACK
switchState = 1'b0;
for (i = 0; i < onstate_count; i = i+1) begin
if (onStateControls[i] == 1'b1) begin
switchState = 1'b1;
end
end
for (j = 0; j < ack_count; j = j+1) begin
if (ack_expression_type[j] == 1'b0) begin
if (switchState) begin
ack[j] = ack_logic_value[j];
end else begin
ack[j] = !ack_logic_value[j];
end
end else begin
ack[j] = ack_logic_value[j];
end
end
end
endmodule
The warning mesage I'm getting is:
Warning-[SM_TPL] Transaction path loss after synthesis
In module 'someModuleName', transaction path through signal 'i' will be
lost after synthesis due to read after blocking assignment in same process.
-
Warning-[SM_TPL] Transaction path loss after synthesis
In module 'someModuleName', transaction path through signal 'switchState' will be
lost after synthesis due to read after blocking assignment in same process.
-
Warning-[SM_TPL] Transaction path loss after synthesis
In module 'someModuleName', transaction path through signal 'j' will be
lost after synthesis due to read after blocking assignment in same process.
I tried making i, j as integer and genvar but no effect, I'm new to verilog and don't know how to resolve this warning.
Any help would be highly appreciated.
Thanks.

Synthesizers require loops to static unroll.
A loop must be able to static unroll to be synthesizable.
Using a snip it from your original code:
switchState = 1'b0;
for (i = 0; i < onstate_count; i = i+1) begin // <-- onstate_count is not a compile time constant, therefore cannot static unroll
if (onStateControls[i] == 1'b1) begin
switchState = 1'b1;
end
end
The equivalent synthesizer friendly version would be:
switchState = 1'b0;
for (i = 0; i < 16; i = i+1) begin // <-- loop is static
if (i < onstate_count) begin // <-- condition check
if (onStateControls[i] == 1'b1) begin
switchState = 1'b1;
end
end
end
A similar change needs to be made to for (j = 0; j < ack_count; j = j+1). The ack also needs to be assigned a value for indexes greater than ack_count or it will infer a latches; and most FPGA synthesizers do not support latches.

Try this code. Also are onstate_count and ack_count variables constants?
module someModuleName(...)
...
...
genvar i,j;
wire [3:0] onstate_count;
wire [3:0] ack_count;
bit switchState;
generate
for (i = 0; i < onstate_count; i = i+1) begin
always #(*) begin :EVAL_ACK
switchState = 1'b0;
if (onStateControls[i] == 1'b1) begin
switchState = 1'b1;
end
end
end
endgenerate
generate
for (j = 0; j < ack_count; j = j+1) begin
always #(*) begin
if (ack_expression_type[j] == 1'b0) begin
if (switchState) begin
ack[j] = ack_logic_value[j];
end else begin
ack[j] = !ack_logic_value[j];
end
end else begin
ack[j] = ack_logic_value[j];
end
end
end
endgenerate
endmodule

Related

Modulating a signal on-off at 10kHz

I have written the code for the input clk = 10MHz and output_clk = 5MHz. I want to modulate the output_clk on-off at 10kHz as shown in the example signal. But, my current code only modifies the output_clk to be 10kHz rather than modulating the signal on-off at 10kHz while output_clk remains 5MHz. Any suggestions how to achieve the same?
Please see the example output_clk signal I want as the output.
// mclk1 = 10MHz
always#(50)
begin
mclk1 <= ~mclk1;
end
reg [31:0]count_500;
always#(posedge mclk1)
begin
if (count_500 == 500-1)
begin
mdata1 <= ~mdata1;
count_500 <= 0;
end
else
begin
count_500 <= count_500 + 1;
end
end
You can create a new signal which follows mclk1 but is gated by the 10kHz signal:
wire mclk1gated = mdata1 ? mclk1 : 0;
Here is a complete code example:
module tb;
bit mclk1,mdata1;
// mclk1 = 10MHz
always#(50)
begin
mclk1 <= ~mclk1;
end
reg [31:0]count_500=0;
always#(posedge mclk1)
begin
if (count_500 == 500-1)
begin
mdata1 <= ~mdata1;
count_500 <= 0;
end
else
begin
count_500 <= count_500 + 1;
end
end
wire mclk1gated = mdata1 ? mclk1 : 0;
initial begin
#300us $finish;
end
endmodule

Illegal reference to net rddata in FIFO

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.

Can't resolve multiple constant drivers for net Quartus error

this is a very basic question but if somebody can help me with these errors, I'd really appreciate it. I am an EE undergrad, new to Verilog, and I'd appreciate any help/explanation.
The errors I received were:
10028 Can't resolve multiple constant drivers for "led" at compare_block.sv (66)
10029 Constant driver at compare_block.sv(61)
What are the multiple constant drivers here? Originally, I had the led assignment (led <= led_val) within the second always block, and I thought moving it up to the first always block would change the errors, but it did not.
module compare_block (clk, reset_n, result, led);
parameter data_width = 8; /
parameter size = 1000;
input clk, reset_n;
input [data_width:0] result;
logic [(data_width):0] data_from_rom;
logic [9:0] addr_to_rom;
output reg led;
reg [(data_width):0] comp_sig [size-1:0];
reg [data_width:0] comp_sig_temp;
reg [(data_width):0] filt_sig [size-1:0];
reg [(data_width):0] ans_sig [size-1:0];
integer i, iii;
reg [9:0] ii ;
integer sum_array;
wire [(data_width+3):0] array_avg;
reg [data_width:0] summed_arr [size-2 : 0];//container for all summation steps
wire total_sum;
reg ans_sig_done;
reg [data_width : 0] summed_ans;
reg [data_width:0] max_val, error_val;
initial begin
i = 0;
ii = 0;
led=0;
data_from_rom='b000000000;
summed_ans='b000000000;
max_val='b000000000;
for (iii=0;iii<(size-1);iii=iii+1) begin
filt_sig[iii]=0;
ans_sig [iii]=0;
comp_sig[iii]=0;
summed_arr[iii]=0;
end
end
//port map to ROM
rom_compare ref_wave(
.clk(clk),
.addr(addr_to_rom), //text file?
.data(data_from_rom)
);
//Moore FSM
localparam [3:0]
s0=0, s1 = 1, s2 = 2, s3 = 3, s4 = 4, s5 = 5;
reg [3:0] state_reg, state_next;
initial state_next = 0;
always #(posedge clk, negedge reset_n) begin
if (reset_n == 'b0) begin //reset is active low
state_reg <= s0;
end else begin
state_reg <= state_next;
led <= led_val;
end
end
always #(state_reg) begin
state_next = state_reg;
led=0;
case (state_reg)
s0 : begin //initial state, reset state
if (!reset_n) begin
led <= 0;
ii <= 0;
end else begin
state_next <= s1;
end
end
s1 : begin
if (ii>(size)) begin
ii <= 0;
end else begin
addr_to_rom <= ii;
state_next <= s2;
end
end
s2 : begin
comp_sig_temp <= data_from_rom;
filt_sig [ii] <= result;
state_next <= s3;
end
s3 : begin
comp_sig[ii] <= comp_sig_temp;
state_next <= s4;
end
s4 : begin
ans_sig[ii] <= filt_sig[ii] - comp_sig[ii];
state_next <= s5;
end
s5 : begin
if (ii>(size-2)) begin
ans_sig_done = 1;
end else begin
ans_sig_done = 0;
end
ii <= ii+1;
state_next <= s0;
end
endcase
end
reg [(data_width+2):0] sum;
integer j;
always #* begin
sum = 0;
if (ans_sig_done == 1) begin
for (j=4; j<(size-1); j=j+2) begin
sum = sum +ans_sig[j];
if (ans_sig[j] > max_val) begin
max_val = ans_sig[j];
end
end
end
end
assign array_avg = sum >> 'd3; //2^3 = 8
always #(clk, result) begin //posedge clk, result
filt_sig [i] <= result;
i <= i + 1;
end
assign error_val = max_val >> 'd2; //approx 25% of max value of array
reg led_val;
always #(*)
begin
if (array_avg < error_val) begin
led_val <= 'b1;
end else begin
led_val <= 'b0;
end
end
endmodule
I figured it out!
The two instances were me trying to initialize one led = 0 in one always block and then assigning led <= led_val in another. You can't refer to an output in two different always blocks.

Cause of inferred latches (not else or default statement) in Verilog

Quartus is telling me that I have inferred latches for input_val, ii, output_val, delayed, and addr_to_rom. I have looked at previous posts and made changes so that all my if statements have an else component and that my case statement has a default option.
What else could be causing all of these inferred latches?
(updated code below)
module simple_fir(clk, reset_n, output_val);
parameter data_width = 8;
parameter size = 1024;
input wire clk;
input wire reset_n;
//input reg [(data_width):0] input_val;
reg [(data_width):0] input_val;
output reg [data_width:0] output_val;
reg [(data_width):0] delayed;
reg [data_width:0] to_avg;
reg [9:0] ii ;
reg [9:0] i ;
reg [data_width:0] val;
reg [data_width:0] output_arr [(size-1):0];
logic [(data_width):0] data_from_rom; //precalculated 1 Hz sine wave
logic [9:0] addr_to_rom;
initial delayed = 0;
initial i = 0;
initial ii = 0;
//port map to ROM
rom_data input_data(
.clk(clk),
.addr(addr_to_rom), //text file?
.data(data_from_rom)
);
//Moore FSM
localparam [3:0]
s0=0, s1 = 1, s2 = 2, s3 = 3, s4 = 4, s5 = 5, s6 = 6;
reg [3:0] state_reg, state_next;
initial state_next = 0;
always #(posedge clk, negedge reset_n) begin //posedge clk, reset_n
if (reset_n == 'b0) begin //reset is active low
state_reg <= s0;
end else begin
state_reg <= state_next;
end
end
always #* begin
state_next = state_reg; // default state_next
case (state_reg)
s0 : begin //initial state, reset state
if (!reset_n) begin
output_val = 0;
delayed = 0;
to_avg= 0;
i = 0;
ii = 0;
end else begin
state_next = s1;
end
end
s1 : begin
if (ii>(size-2)) begin
ii = 0;
end else begin
addr_to_rom = ii;
end
input_val = input_val;
delayed = delayed;
state_next = s2;
end
s2 : begin
input_val = data_from_rom;
ii = ii+1;
delayed = delayed;
state_next = s3;
end
s3 : begin
delayed = input_val;
state_next = s4;
end
s4 : begin
addr_to_rom = ii;
input_val = input_val;
delayed = delayed;
state_next = s5;
end
s5 : begin
input_val = data_from_rom;
delayed = delayed;
//i=i+1;
//ii <= ii+1;
state_next = s6;
end
s6 : begin
to_avg = input_val + delayed; //summing two values
val = (to_avg >> 1); //taking the average
output_arr[ii-1] = val; //indexing starts on [2]
output_val = val;
state_next = s0;
input_val = input_val;
end
default: begin
addr_to_rom = addr_to_rom;
data_from_rom = data_from_rom;
delayed = delayed;
input_val = input_val;
to_avg = to_avg;
val = val;
output_val = output_val;
ii = ii;
end
endcase
end
endmodule
You have 6 states in your combo always block, but you are assigning to delayed in only 3 of them. This implies that you want to retain state, which infers latches. You should make sure delayed is assigned some value in all states (and in all branches of if/else, if applicable.
Also, you have an incomplete sensitivity list. You likely want to change:
always #(state_reg) begin
to:
always #* begin
#* is the implicit sensitivity list, which triggers the always block whenever a change occurs to any signal on the RHS of an assignment.
you have to look at the ways state machines are programmed. Usually states are calculated using flop and the final assignment is a combinatorial. You have it vice versa. Therefore you have issues. Something like the following should work for you. Sorry, i did not test it. The code needs to use non-blocking assignments except in the place where you caculate an intermediate value.
always #*
state_reg = state_next;
always #(posedge clk, negedge reset_n) begin //posedge clk, reset_n
if (reset_n == 'b0) begin //reset is active low
state_next <= s0;
end
else begin
case (state_reg)
S0: begin
output_val <= 0;
delayed <= 0;
i <= 0;
ii <= 0;
end
s1 : begin
if (ii>(size-2)) begin
ii <= 0;
end else begin
addr_to_rom <= ii;
end
input_val <= input_val;
delayed <= delayed;
state_next <= s2;
end
s2 : begin
input_val <= data_from_rom;
ii <= ii+1;
state_next <= s3;
end
s3 : begin
delayed <= input_val;
state_next <= s4;
end
s4 : begin
addr_to_rom <= ii;
state_next <= s5;
end
s5 : begin
input_val <= data_from_rom;
state_next <= s6;
end
s6 : begin
// calculating intermediate value, need blocking assignments here
to_avg = input_val + delayed; //need blocking here
val = (to_avg >> 1); //need blocking here
output_arr[ii-1] <= val; //indexing starts on [2]
output_val <= val;
state_next <= s0;
end
endcase
end // else
end // always
I noticed you used a coding style that a default assignment state_next = state_reg is placed at the very top of the always block. That makes state_next always have a legal driver if it is not explicitly assigned. This is also required for other combinational signals. Otherwise, latch inferred. Besides, the signal data_from_rom, which I assume is an output from module rom_data, has mutiple drivers.

Module instantiation with the "number sign"

I have the main module with FIFO stuff.
Here it is:
module syn_fifo #(
parameter DATA_WIDTH = 8, // inpit capacity
parameter DATA_DEPTH = 8 // the depth of the FIFO
)
(
input wire clk,
input wire rst,
// Write_______________________________________________
input wire [DATA_WIDTH-1:0]din, // the input data
input wire wren, // Write anable
output wire full,
// Read________________________________________________
output wire [DATA_WIDTH-1:0]dout, // The output data
input wire rden, // Read enable
output wire empty
);
integer q_size; // The queue size(length)
integer golova; // The queue beginning
integer hvost; // The end of queue
reg [DATA_WIDTH-1:0]fifo[DATA_DEPTH-1:0];
assign full = (q_size == DATA_DEPTH) ? 1'b1: 1'b0; // FIFO is full
/*
True { full = (q_size==DATA_TEPTH) = 1 }, then wire "full" goes to "1" value
False { full = (q_size==DATA_TEPTH) = 0 }, then wire "full" goes to "0" value
*/
assign empty = (golova == hvost); // FIFO is empty
assign dout = fifo[hvost]; // FWFT (other write mode)
integer i;
//___________(The queue fullness)___________________
always #(posedge clk or posedge rst)
begin
if (rst == 1'b1)
begin
for (i = 0; i < DATA_DEPTH; i = i + 1) // incrementing the FIFO
fifo[i] <= 0; // Resetting the FIFO
golova <= 0; // Resetting the queue start variable
end
else
begin //Write_______________________________________
if (wren && ~full)
begin
fifo[golova] <= din; // putting data in to the golova
if (golova == DATA_DEPTH-1) // restrictions for the queue beginning
golova <= 0; // Reset the beginning
else
golova <= golova + 1; // other occurence incrementing
end
end
end
//Reading
always #(posedge clk or posedge rst)
begin
if (rst == 1'b1)
begin
hvost <= 0;
end
else
begin
if (rden && !empty)
/*for staying inside the queue limits - make the check of non equality of the "hvost" & "queue size"*/
begin
if (hvost == DATA_DEPTH-1) // if hvost = DATA_DEPTH-1, then
hvost <= 0; // Reset hvost
else
hvost <= hvost + 1;
end
end
end
always # (posedge clk)
begin
if (rst == 1'b1) begin
q_size <= 0;
end
else
begin
case ({wren && ~full, rden && ~empty} )
2'b01: q_size <= q_size + 1; // RO
2'b10: q_size <= q_size - 1; // WO
default: q_size <= q_size; // read and write at the same time
endcase
end
end
endmodule
Also i've got the testbench module down delow:
`timescale 1ns / 1ps
module fifo_tb();
localparam CLK_PERIOD = 10;
reg clk;
reg rst;
always begin
clk <= 1'b0;
#(CLK_PERIOD / 2);
clk <= 1'b1;
#(CLK_PERIOD / 2);
end
localparam DATA_WIDTH = 8;
localparam DATA_DEPTH = 4;
reg [DATA_WIDTH-1:0]din;
reg wren;
reg rden;
wire [DATA_WIDTH-1:0]dout;
wire empty;
wire full;
wire wr_valid;
wire rd_valid;
task write;
input integer length;
begin
if (length) begin
#(posedge clk);
wren <= 1'b1;
while (length) begin
#(posedge clk);
if (wr_valid) begin
length <= length - 1;
if (length == 1) begin
wren <= 1'b0;
end
end
end
end
end
endtask
task read;
input integer length;
begin
if (length) begin
#(posedge clk);
rden <= 1'b1;
while (length) begin
#(posedge clk);
if (rd_valid) begin
length <= length - 1;
if (length == 1) begin
rden <= 1'b0;
end
end
end
end
end
endtask
initial begin
rst <= 1'b0;
wren <= 1'b0;
rden <= 1'b0;
#50;
rst <= 1'b1;
#50;
rst <= 1'b0;
#200;
/* Test Start */
//write(4);
//read(4);
/* Test Stop */
#1000;
$finish;
end
assign wr_valid = wren & ~full;
assign rd_valid = rden & ~empty;
always #(posedge clk) begin
if (rst == 1'b1) begin
din <= 0;
end else begin
if (wr_valid == 1'b1) begin
din <= din + 1;
end
end
end
// write?
always begin
#400;
write(5);
#15;
write(7);
#25;
write(3);
#15;
write(9);
#15;
write(1);
#10000;
end
// read?
always begin
#420;
read(3);
#37;
read(13);
#21;
read(7);
#15;
read(9);
#15;
read(4);
#20;
read(7);
#10000;
end
initial begin
$dumpfile("test.vcd");
$dumpvars(0,fifo_tb);
end
syn_fifo #(.DATA_WIDTH(DATA_WIDTH),
.DATA_DEPTH(DATA_DEPTH)) dut ( .clk(clk),
.rst(rst),
.din(din),
.wren(wren),
.full(full),
.dout(dout),
.rden(rden),
.empty(empty));
endmodule
Trying to compile all of it with iVerilog + GTKwave + Win10 by next command:
C:\Program Files\iverilog\bin>iverilog -o fifo.v fifo_tb.v
The compiler gives me the next message:
fifo_tb.v:138:error: Unknown module type:syn_fifo
2 error(s) during elaboration.
These modules were missing:syn_fifo referenced 1 times
At the necessary line "138" maybe the main mistake is covered by the "Number sign" in module instantiation?
/*132|*/ initial begin
/*133|*/ $dumpfile("test.vcd");
/*134|*/ $dumpvars(0,fifo_tb);
/*135|*/ end
/*136|*/
/*137|*/ syn_fifo #(.DATA_WIDTH(DATA_WIDTH),
/*138|*/ .DATA_DEPTH(DATA_DEPTH)) dut ( .clk(clk),
/*139|*/ .rst(rst),
/*140|*/ .din(din),
/*141|*/ .wren(wren),
/*142|*/ .full(full),
/*143|*/ .dout(dout),
/*144|*/ .rden(rden),
/*145|*/ .empty(empty));
/*146|*/
/*147|*/ endmodule
I'm not shure of that.
Seems like you are indicating fifo.v to be your output file, try:
iverilog -o syn_fifo.tb -s fifo_tb fifo_tb.v fifo.v
-o -> output file
-s -> top module (in this case, the test one)
(after everything, include all the files)
Then, to run it:
vvp syn_fifo.tb
Thank you, dear #m4j0rt0m
I just forgot to type in the output file name at the CMD window. Was very exhausted so haven't noticed such a detail)))
Usually it looks like:
iverilog -o OUTPUT_FILE_NAME fifo_tb.v fifo.v
And also I tried your advice, and it's finally done!

Resources