Verilog: Re-assigning a variable in an always block - verilog

I want to create a logic where I update the value of a register whenever there is a pulse.
In this, I need to update the all the register bits (8) to 1 except for one variable bit (x in below snippet) which needs to be set to 0.
For this I have a simple logic in place but I am not sure if this is synthesizable. I have not run lint yet.
always #(posedge clk or negedge resetn)
begin
if (resetn == 1'b0) begin
mask <= 8'b1;
end
else begin
if (pulse) begin
mask[7:0] <= 8'hFF;
mask[x] <= 1'b0;
end
else
mask[7:0] <= mask[7:0];
end
end
Is this the best way to do it. I don't think so. Please suggest what should be the right way to do it.

Yes, you can make multiple assignments to the same variable (whole or a select of the variable) in the same always block. The last assignment wins.
Also, you should remove the mask[7:0] <= mask[7:0]; statement. It is unnecessary any sequential always block retains the value of any unassigned variable. This dummy assignment can interfere with a testbench's attempt to override the behavior for debugging or error injection.

looks good,
as mentioned you can remove:
else
mask[7:0] <= mask[7:0];
you might consider also adding synchronized reset in a form of "kill" or something so you wouldn't have to use the a-synchronized reset "resetn"

Related

Blocked and non-blocking assignment error in verilator

I'm testing SystemVerilog code using verilator, and it looks like below.
output [31:0] data_out1;
reg [31:0] data_out1;
always #(rst_b or addr1 or data_in1 or write_mask1)
begin
if((write_mask1 != 32'b0) && (rst_b == 1'b1))
begin
data_out1 <= 32'hxxxxxxxx;
... do something ....
end
always #(posedge clk)
begin
if((write_mask1 != 32'b0) && (rst_b == 1'b1))
begin
data_out1 <= 32'hxxxxxxxx;
... do something ..
end
It has two always blocks, and in each block, data_out1 is assigned in non-blocking. But, it shows a "Blocked and non-blocking assignments to same variable" error.
I do not use blocking assignment, and I can't understand why such an error occurs. I would appreciate if anyone can help.
When I run verilator on your code snippet, I get messages like the following:
%Warning-COMBDLY: Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=).
%Warning-COMBDLY: *** See the manual before disabling this,
%Warning-COMBDLY: else you may end up with different sim results.
%Error-BLKANDNBLK: Unsupported: Blocked and non-blocking assignments to same variable: data_out1
The 1st warning message indicates that verilator interprets your 1st always block as combinational logic, not sequential logic, and it treats the nonblocking assignment operator (=>) as a blocking assignment.
Since your 1st block does not use #(posedge clk), it is treated as combinational logic.
Also, you should not make assignments to the same signal from multiple blocks.
Lastly, you should not use nonblocking assignment to infer combinational logic.
There are two issues:
The code in the post is assigning the same signal from two always blocks. This can't be done, data_out1 must be driven from a single always block.
The always block without the clock infers combinational logic. The correct way to model combinational logic is by using blocking assignments (=).
The 2nd always block is ok (but not clean, because the rst_b is not at the first condition alone, it might cause problem for some simulator), working as a FF with sync low-active reset. The problem is the 1st always block.
Based on your modeling with <= in the 1st block, if write_mask1 changes to trigger the sensitivity list, you want to assign data_out1 depending on the old value of write_mask1 at the time point that write_mask1 has been updated with the new value. This behavior is inferred latch, because it needs the memory to hold the old value before the event, but it is also not a valid behavior of a FF. It seems that Verilator interprets this inferred latch still as "blocking assignment". (By the way, latch itself won't cause error, because it is indeed a right way to model if you have latches for purposes like clock gating)
If it is SystemVerilog (instead of Verilog), i would try to use always_comb for combinational logic, and always_ff for sequential. (and always_latch for latch). In your case, the simplest clean way to model is to be aware of which part is combitional and which sequential. I'd model it as:
always_ff #(posedge clk) // to add "or negedge rst_b" if you want async reset
begin
if(!rst_b)
begin
data_out1 <= 32'hxxxxxxxx; // some reset value
end
else if(write_mask1 != 32'b0)
begin
data_out1 <= 32'hxxxxxxxx; // the value you want to update
end
end
// if there is no other condition, it will keep the old value based on the FF behavior
... do something ..
end
If you really mean to have 2 blocks, one doing combinational, one sequential, here we are:
always_comb begin
if(write_mask1 != 32'b0) begin
data_out1_next = 32'hxxxxxxxx;
end
else begin
// now it's necessary to write else-clause because it's not a FF -- it has no memory
data_out1_next = data_out1;
end
end
always_ff #(posedge clk) // to add "or negedge rst_b" if you want async reset
begin
if(!rst_b) begin
data_out1 <= 32'hxxxxxxxx; // some reset value
end
else begin
data_out1 <= data_out1_next;
end
end

Asynchronous reset warning issue

This design contains one or more registers or latches with an active
asynchronous set and asynchronous reset. While this circuit can be built,
it creates a sub-optimal implementation in terms of area, power and
performance.
Initial_LFSR2 initial_value(RNTI,NCELL_ID,nss,nf,init) ;
always#(posedge scr_clk or posedge scr_rst) begin // Asynchronous Reset
if(scr_rst) begin
LFSR1 <= 31'b1000000000000000000000000000000 ;
LFSR2 <= init ;
counter <= 0 ; // reinitialized the initialzation steps counter
input_counter <= 0 ;
end
help please
The preferred solution is to have LFSR2 reset value be a constant. A parameter could be an expression of constants/parameters or a function with constants/parameters as inputs. It might be a bit of effort to change you code but this is what needs to be done to get "optimal implementation in terms of area, power and performance".
parameter LFSR2_INIT = initial_LFSR2_func(RNTI,NCELL_ID,nss,nf);
always #(posedge scr_clk or posedge scr_rst) begin
if (scr_rst) begin
LFSR2 <= LFSR2_INIT;
end
else begin
LFSR2 <= next_LFSR2;
end
end
If you absolutely must have your reset value determined by combinational logic, then there is a last resort option. It is "sub-optimal implementation in terms of area, power and performance" compared to the parameter solution, but probably will be better than what you currently have. Be warned, the more complex the logic on init, the more "sub-optimal" it will be.
This likely will not work if you are targeting for FPGA; as they tend to have limited support for flops with asynchronous set/reset. You did tag the question with xilinx which is for FPGAs. You really need to figure out why you need asynchronous set/reset at all. Try to get your code to work with only synchronous flops (no async set/reset). If you need async set/reset, then spend the extra effort to figure out how to make parameter approach work.
Because this is a last resort option, it will not be displayed by default.
Uniquify each flop of with individual async set and reset signals.
wire [LFSR2_WIDTH-1:0] lfsr2_set = {LFSR2_WIDTH{src_rst}} & init;
wire [LFSR2_WIDTH-1:0] lfsr2_rst = {LFSR2_WIDTH{src_rst}} & ~init;
genvar gidx;
generate
for(gidx=0; gidx<LFSR2_WIDTH; gidx=gidx+1) begin : LFSR2_genblk
always #(posedge src_clk, posedge lfsr2_rst[gidx], posedge lfsr2_set[gidx]) begin
if (lfsr2_rst[gidx]) begin
LFSR2[gidx] <= 1'b0;
end
else if (lfsr2_set[gidx]) begin
LFSR2[gidx] <= 1'b1;
end
else begin
LFSR2[gidx] <= next_LFSR2[gidx];
end
end
end
endgenerate
The logic will add area. The extra routing and time to stabilize with impact performance. Stabilize time will also impact power. Power and performance will get worse if init toggles a with intermediate values while src_rst is high.

Verilog: functionality like always & synthesizable

Is there any other functionality like always (that would only run if the sensitive signal changes and won't iterate as long as signal stays the same) which can be cascaded, separately or within the always , but is synthesizable in Verilog.
While I don't think there's a construct specifically like this in Verilog, there is an easy way to do this. If you do an edge detect on the signal you want to be sensitive to, you can just "if" on that in your always block. Like such:
reg event_detected;
reg [WIDTH-1:0] sensitive_last;
always # (posedge clk) begin
if (sensitive_signal != sensitive_last) begin
event_detected <= 1'b1;
end else begin
event_detected <= 1'b0;
end
sensitive_last <= sensitive_signal;
end
// Then, where you want to do things:
always # (posedge clk) begin
if (event_detected ) begin
// Do things here
end
end
The issue with doing things with nested "always" statements is that it isn't immediately obvious how much logic it would synthesize to. Depending on the FPGA or ASIC architecture you would have a relatively large register and extra logic that would be instantiated implicitly, making things like waveform debugging and gate level synthesis difficult (not to mention timing analysis). In a world where every gate/LUT counts, that sort of implicitly defined logic could become a major issue.
The assign statement is the closest to always you you can get. assign can only be for continuous assignment. The left hand side assignment must be a wire; SystemVerilog also allows logic.
I prefer the always block over assign. I find simulations give better performance when signals that usually update at the same time are group together. I believe the optimizer in the synthesizer can does a better job with always, but this might depend on the synthesizer being used.
For synchronous logic you'll need an always block. There is no issue reading hardware switches within the always block. The fpga board may already de-bounce the input for you. If not, then send the input through a two phase pipe line before using it with your code. This helps with potential setup/hold problems.
always #(posedge clk) begin
pre_sync_human_in <= human_in;
sync_human_in <= pre_sync_human_in;
end
always #* begin
//...
case( sync_human_in )
0 : // do this
1 : // do that
// ...
endcase
//...
end
always #(posedge clk) begin
//...
if ( sync_human_in==0 ) begin /* do this */ end
else begin /* else do */ end
//...
end
If you want to do a hand-shake having the state machine wait for a human to enter a multi-bit value, then add to states that wait for the input. One state that waits for not ready (stale bit from previous input), and the other waiting for ready :
always #(posedge clk) begin
case(state)
// ...
PRE_HUMAN_IN :
begin
// ...
state <= WAIT_HUMAN__FOR_NOT_READY;
end
WAIT_HUMAN_FOR_NOT_READY :
begin
// ready bit is still high for the last input, wait for not ready
if (sync_human_in[READ_BIT])
state <= WAIT_HUMAN_FOR_NOT_READY;
else
state <= WAIT_HUMAN_FOR_READY;
end
WAIT_HUMAN_FOR_READY :
begin
// ready bit is low, wait for it to go high before proceeding
if (sync_human_in[READ_BIT])
state <= WORK_WITH_HUMAN_INPUT;
else
state <= WAIT_HUMAN_FOR_READY;
end
// ...
endcase
end

Combining Blocking and NonBlocking in Verilog

If I want statements to happen in parallel and another statement to happen when all other statements are done with, for example:
task read;
begin
if (de_if==NOP) begin
dp_op <= 3'b000;
dp_phase = EXEC;
end
else begin
if (de_if==EXEC_THEN) begin
dp_const <= de_src3[0];
dp_src <= de_src3;
dp_op <= {NOP,de_ctrl3};
dp_dest <= de_dest1;
end
else if (get_value(de_ctrl1,de_src1)==dp_mem[de_src2]) begin
dp_const <= de_src3[0];
dp_src <= de_src3;
dp_op <= {NOP,de_ctrl3};
dp_dest <= de_dest1;
end
else begin
dp_const <= de_src4[0];
dp_src <= de_src4;
dp_op <= {NOP,de_ctrl4};
dp_dest <= de_dest2;
end
#1 dp_phase=READ;
end
end
endtask
In this code I want the statement dp_phase = READ to only be executed after all other assignments are done, how do I do it?
As you can see what I did is wait 1 clock before the assignment but i do not know if this is how its done ...
You need a state machine. That's the canonical way to make things happen in a certain sequence. Try to remember that using a hardware description language is not like a regular programming language...you are just describing the kind of behavior that you would like the hardware to have.
To make a state machine you will need a state register, one or more flip-flops that keep track of where you are in the desired sequence of events. The flip-flops should be updated on the rising clock edge but the rest of your logic can be purely combinational.

Verilog Synthesis fails on if statement containing two variables

I encountered a problem with synthesis where if I had two variables in an if statement, Synthesis will fail (with a very misleading and unhelpful error message).
Given the code snippet below
case(state)
//other states here
GET_PAYLOAD_DATA:
begin
if (packet_size < payload_length) begin
packet_size <= packet_size + 1;
//Code to place byte into ram that only triggers with a toggle flag
next_state = GET_PAYLOAD_DATA;
end else begin
next_state = GET_CHKSUM2;
end
end
I get an error in Xilinx ISE during synthesis:
ERROR:Xst:2001 - Width mismatch detected on comparator next_state_cmp_lt0000/ALB. Operand A and B do not have the same size.
The error claims that next_state isn't correct, but if I take out payload_length and assign a static value to it, it works perfectly fine. As both packet_size and payload_length are of type integer, they are the same size and that is not the problem. Therefore I assume its a similar problem to for loops not being implementable in hardware unless it is a static loop with a defined end. But If statements should work as it is just a comparator between 2 binary values.
What I was trying to do here is that when a byte is received by my module, it will be added into RAM until the the size of the entire payload (which I get from earlier packet data) is reached, then change to a different state to handle the checksum. As the data only comes in 1 byte at a time, I recall this state multiple times until the counter reaches the limit, then I set the next state to something else.
My question is then, how do I achieve the same results of calling my state and repeat until the counter has reached the length of the payload without the error showing up?
EDIT:
Snippets of how packet_size and payload_length are declared, as requested in comments
integer payload_length, packet_size;
initial begin
//other stuff
packet_size <= 0;
end
always # (posedge clk) begin
//case statements with various states
GET_PAYLOAD_LEN:
begin
if (rx_toggle == 1) begin
packet_size <= packet_size + 1;
addr <= 3;
din <= rx_byte_buffer;
payload_length <= rx_byte_buffer;
next_state = GET_PAYLOAD_DATA;
end else begin
next_state = GET_PAYLOAD_LEN;
end
end
rx_byte_buffer is a register of the input data my module receives as 8 bits wide, while packet_size increments in various other states of the machine prior to the one you see above.
I have gotten around the error by switching the if statement conditionals around, but still want to understand why that would change anything.
There are some errors that stick out right away about the code, while they may not fix this problem, they will need to be corrected because it will cause a difference in simulation and hardware tests.
The nextstate logic needs to be in a different always block that does not change based on the posedge of clock. The sensitivity list needs to include things like "state" and/or "*". And if you wanted the nextstate logic to be registered like it is now (which you don't) you should use a nonblocking assignment, this is described in great deal in the cummings paper, provided below.
http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA_rev1_2.pdf
the code should look something like this:
always # (*) begin
//case statements with various states
GET_PAYLOAD_LEN:
begin
if (rx_toggle == 1) begin
packet_size_en = 1'b1;
//these will need to be changed in a similar manner
addr <= 3;
din <= rx_byte_buffer;
payload_length <= rx_byte_buffer;
/////////////////////////////////////////////////////
next_state = GET_PAYLOAD_DATA;
end else begin
next_state = GET_PAYLOAD_LEN;
end
end
always#(posedge clk) begin
if(pcket_size_en)
packet_size <= packet_size +1 ;
end
Also, the first thing I would try is to make these a defined length, by making them of type reg (I assume that you wont be needing a signed number so it should have no difference on simulation), outside of generate blocks, you should try to not let synthesis play around with integers.

Resources