Generate statement inside an always block, Is it possible? - verilog

I would like to know more information about Generate statements I know that you can replicate modules, and always blocks (like in the other post) but,
Would it be possible to create a parametrized case like this?
always # (negedge clk)
begin
if (state==1)
begin
case(CS_sel)
begin
generate
genvar i;
for (i=0; i<N_DACS; i=i+1)
begin: for1
i:begin
num <= mod_in[(i+1)*BITS-1:i*BITS];
div <= mod_out[(i+1)*BITS-1:i*BITS];
end // i:
end // for1
endgenerate
default: begin
num <= mod_in[BITS-1:0];
div <= mod_out[BITS-1:0];
end // default
end // case (CS_sel)
endcase // case (CS_sel)
end // if (state==1)
end // always
First of all, I would like to know if this is possible and how could I do it,
After this, if you know another option to create a synchronous multiplexer in verilog, it would be great!
Thank you!

The generate block cannot be used inside a always block but have to be placed outside. So one has actually the possiblity to build multiple different always block and chose between them via generate if constructs.
But just by looking at the given code I suggest the use of a different approach using proper slicing with fixed width and flexible offset:
if(CS_sel < N_DACS) begin
num <= mod_in[BITS*CS_sel +:BITS];
div <= mod_out[BITS*CS_sel +:BITS];
end else begin
//default stuff
num <= mod_in[BITS-1:0];
div <= mod_out[BITS-1:0];
end
This works because it is effectively similar to
wire [BITS-1:0] subset0;
assign subset0 = mod_in >> (BITS*CS_sel);
[...]
num <= subset0[BITS-1:0];
The direct use of something like mod_in[(i+1)*BITS-1:i*BITS] is not possible as this would theoretically allow for flexible width which (standard) verilog does not support by now to the best of my knowledge.

Related

Verilog: Re-assigning a variable in an always block

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"

Assigning x (dont care) to a register reset value or combinatorical output to improve area efficiency [duplicate]

This question already has answers here:
How can I assign a "don't care" value to an output in a combinational module in Verilog
(2 answers)
Closed 2 years ago.
My question is regarding FPGA design - if I have some registers in my design that I dont care what will be their reset value, can I set the reset value to x? will that improve area efficiency (will the synthesizer be able to utilize this and generate the design in a more efficient way?)
For example,
always #(posedge clk or negedge reset_n) begin
if(~reset_n) begin
reg_1 <= 'x
end
...
end
Edit:
And another question in a similar topic - assuming I have a state machine for example that I dont care what will some outputs be in some states - does setting them to 'x improve area efficiency?
for example, if I have a fsm with two states, STATE_1, STATE_2, and two outputs will the synthesis tool be able to utilize the following code:
always_comb begin
case(state):
STATE_1:begin
out_1 = 1;
out_2 = x;
end
STATE_2:begin
out_1 = x;
out_2 = 0;
end
end
better than this:
always_comb begin
case(state):
STATE_1:begin
out_1 = 1;
out_2 = 0;
end
STATE_2:begin
out_1 = 0;
out_2 = 0;
end
end
(under the assumption that I dont care what is out_2 in STATE_1, and what is out_1 in STATE_2).
Thanks
Using 'x in sequantial logic
Yes, Verilog-wise, you could use this syntax. However, in your particular example, it does not really make sense to do this and you could consider it to be a bad coding practive. Instead of explicitly assigning 'x, you can also omit the asynchronous reset.
The following two processes will synthesise to the same flip-flop. I would personally recommend to use the latter style.
// Assigning 'x to tell synthesis tool that there is no reset value
always #(posedge clk or negedge reset_n)
if(~reset_n)
reg_1 <= 'x;
else
reg_1 <= reg_1_next;
// Omitting the asynchronous reset from the sensitivity list to tell
// synthesis tool that there is no reset
always #(posedge clk)
reg_1 <= reg_1_next;
In general: if you have different variables which must be either resetable or non-resetable, you should split their assignment into different always-blocks. This generally makes your code better readable. See the example below:
// Do NOT do this
always #(posedge clk or negedge reset_n)
if(~reset_n)
begin
vld <= 1'b0;
reg_1 <= 'x;
end
else
begin
vld <= vld_next;
reg_1 <= reg_1_next;
end
// Do this
always #(posedge clk or negedge reset_n)
if(~reset_n)
vld <= 1'b0;
else
vld <= vld_next;
always #(posedge clk)
reg_1 <= reg_1_next;
Bonus
Having said that, there are cases where it could make sense to assign 'x in the reset condition to tell the synthesis tool to not generate resetable flops for particular variables. Please take a look at this answer: https://stackoverflow.com/a/21477457/7949378
Lets create an example, based on this answer. Lets say you have a struct with 1 valid-signal (vld) and 2 data signals (data_a and data_b). The data is only valid when vld is 1'b1. In other words, we can save area by only resetting vld and not resetting data_a and data_b.
Now, we want to use the full potential of structs, and simply assign the full struct instead of the seperate members (see struct_example_q <= struct_example_next;). This means we cannot split this always-block into two seperate processes (like I recommened before). In that case, we must explicitly tell the synthesis tool to not reset the data signals.
See the code below:
typedef struct {
logic vld;
logic [31:0] data_a;
logic [31:0] data_b;
} struct_example_t;
struct_example_t struct_example_next;
struct_example_t struct_example_q;
always #(posedge clk or negedge reset_n)
if (!reset_n)
begin
/**
* Only reset the valid-bit
* We could use '{default:'x} to simplify this even further
**/
struct_example_q.data_a <= 'x;
struct_example_q.data_b <= 'x;
struct_example_q.vld <= 1'b0;
end
else
begin
struct_example_q <= struct_example_next;
end
Using 'x in combinatorial logic
Lets first look at your RTL:
always_comb begin
case(state):
STATE_1:begin
out_1 = 1;
out_2 = x;
end
STATE_2:begin
out_1 = x;
out_2 = 0;
end
end
I want to note that this is not really the best example. Assuming that the FSM is full—i.e., that STATE_1 and STATE_2 are the only two states state can take—you would achieve exactly the same with the code below, assuming you don't case anyway about out_1 and out_2 in the other states.
always_comb begin
out_1 = 1;
out_2 = 0;
end
Now, for the sake of the example, lets assume that we cannot rewrite this. In that case, you should set default values before your case-statement. This prevents the synthesis logic from infering latches in your don't-care state, but it also helps you to not run into issues with 'x once you start doing gate-level simulations (GLS). Using your example, you RTL would look like the code below. (Again note that the case here is kind of redundant.)
always_comb begin
out_1 = 1;
out_2 = 0;
case(state):
STATE_1:begin
out_1 = 1;
end
STATE_2:begin
out_2 = 0;
end
end
You will see that this strategy makes sense once you have more elaborate FSMs.
Bonus
I want to give an example where using unique or priority can make sense (instead of using 'x as default value). Take a look at the RTL below and assume that select == 3'b0 will never occur:
always_comb
begin
out_1 = 'x;
case (1'b1)
select[0]: out_1 = a & b;
select[1]: out_1 = a ^ b;
select[2]: out_1 = a | b;
endcase
end
Setting a default value for out_1 will prevent the logic from inferring a latch (since it does not know that select == 3'b0 can never occur). Furthermore, the 'x here will help the synthesis tool to optimize this logic (not necessarily w.r.t. area!). However, as we discussed before, using 'x is generally considered to be bad practice.
Instead of using a default value, you can use the priority keyword to tell the synthesis tool that all valid cases have been listed and that the tool must evaluate your cases in order. Because of that, the following case will also be considered as full:
always_comb
priority case (1'b1)
select[0]: out_1 = a & b;
select[1]: out_1 = a ^ b;
select[2]: out_1 = a | b;
endcase
If you, additionally, can be sure that select is a onehot signal ($countones(select) == 1), you can use the unique keyword. This will tell the synthesis tool that this is full-parallel case
always_comb
unique case (1'b1)
select[0]: out_1 = a & b;
select[1]: out_1 = a ^ b;
select[2]: out_1 = a | b;
endcase
Note that simulators will trry to enforce these assumptions by throwing errors at you if you violate the assumptions that are necessary to use priority or unique.

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.

Trouble using 'generate' in verilog always block

I am try to generate some conditions in a case statement in Verilog.
I have a parameter known as MANT_WIDTH and the number of conditions in the case statement depends on the value of MANT_WIDTH
for example I have
always #(*) begin
case (myvariable)
{MANT_WIDTH{1'b1}}:
begin new_variable = {1'b0, {MANT_WIDTH{1'b1}}}; end
genvar n;
generate
for (n = 2; n <= MANT_WIDTH-1; n = n+1) begin: NORMALIZE
{(MANT_WIDTH-n){1'b0}},{n{1'b1}}}:
begin new_variable = {{n{1'b1}},1'b0;
end
endgenerate
default:
begin new_variable = {(MANT_WIDTH+1){1'b0}}; end
endmodule
end
there might be some conditions in this code that don't make sense (incorrect bit widths, etc.) but the gist of what I am trying to do is here.
The problem I am having is that I am getting the following errors when I try to simulate this code using ncverilog:
for (n = 2; n <= MANT_WIDTH-1; n = n+1) begin: NORMALIZE
|
ncvlog: *E, ILLPRI (fpmodule.v,278|6): illegal expression primary [4.2(IEEE)]
also I get illegal lvalue syntax [9.2[IEEE)]
I need to count leading zeros. I didn't actually paste my real code, I just need some way to count leading zeros, but I have a few special cases that will have to put outside of a for loop.
THANK YOU SO MUCH!
It is not legal to use a generate in an always block. They are only valid in the module declaration scope.
module;
//Valid here
endmodule
I have a parameter known as MANT_WIDTH and the number of conditions in
the case statement depends on the value of MANT_WIDTH
There is no way to directly control the number of case statements using a parameter.
I can't tell what you're trying to calculate(new_variable = {myvariable,1'b0}?) but rarely do you need generate loops to achieve a shift of some sort nor does it look like you need leading zeros here.
I resorted to using the following compiler directives:
`ifdef
`else
`endif
So therefore I could define a block a code as such:
`define MYMACRO 1;
`ifdef MYMACRO
// some code
`else
`ifdef ANOTHERMACRO
// different code
`endif
`endif

Resources