I have an array of registers/buses and a single result bus defined as follows.
wire [BW-1:0] bus_array[NUM-1:0];
reg [BW-1:0] and_result;
where
parameter BW = 4;
parameter NUM = 8;
I wish to perform a BW-bit AND operation on the elements of the array and assign the result to the register and_result.
I try doing this as follows.
integer l;
generate
genvar m;
for (m=0; m<BW; m=m+1)
begin : BW_LOOP
always # (*)
begin
and_result[m] = 1'b1;
for (l=0; l<NUM; l=l+1)
and_result[m] = and_result[m] & bus_array[l][m];
end
end
endgenerate
However when I simulate this in Modelsim 10.1e, I get the following error.
Error: (vsim-3601) Iteration limit reached at time 2 ns
If I do not use the generate loop, and instead have BW instances of the always # (*) block, the simulation works okay.
I can infer from the error message, that there is a problem with the generate for loop, but I am not able to resolve the problem.
Most likely a bug with ModelSim. Reproducible on EDAplayground with ModelSim10.1d. Works fine with Riviera2014 (After localizing l inside the generate loop). I'm guessing that and_result[m] is somehow in the #(*) sensitivity list, which it shouldn't be.
l needs to be localized or it will be accessed in parallel with the generated always blocks; creating a potential raise condition.
One workaround is to use SystemVerilog and use always_comb instead of always #(*).
A backwarnd compatable solution is to change and_result[m] = and_result[m] & bus_array[l][m]; to if (bus_array[l][m]==1'b0) and_result[m] = 1'b0; which is equivalent code. This keeps and_result[m] only on as a left hand expression so it cannot be in the sensitivity list.
genvar m;
for (m=0; m<BW; m=m+1)
begin : BW_LOOP
integer l; // <== 'l' is local to this generate loop
always # (*)
begin
and_result[m] = 1'b1;
for (l=0; l<NUM; l=l+1) begin
if (bus_array[l][m]==1'b0) begin
and_result[m] = 1'b0;
end
end
end
Working code here
Related
i was trying to make a floating point adder in SystemVerilog. When i saw the schematic generated i noticed the presence of a latch. The code is:
module ADDER (
input ieee_effloat In1_ADD, In2_ADD,
input ieee_float A_ADD,
output ieee_float Out_ADD
);
logic [24:0] MantissaSum; //Can generate an overflow, expand at 25 bit
always_comb
begin
MantissaSum = In1_ADD.Eff_Mantissa + In2_ADD.Eff_Mantissa; //Sum the mantissas
if(MantissaSum[24] == 1'b1) //If overflow
begin
MantissaSum >>= 1; //Shift the mantissa of 1
Out_ADD.Exponent = A_ADD.Exponent + 1; //<== Here is the latch (?)
Out_ADD.Mantissa = MantissaSum [22:0]; //Select the first 23 bit
end
else
begin
Out_ADD.Mantissa = MantissaSum [22:0]; //Select the first 23 bit
end
end
assign Out_ADD = '{1'b0, Out_ADD.Exponent, Out_ADD.Mantissa};
endmodule
The types are defined:
`ifndef FPU_MACROFLAG
`define FPU_MACROFLAG
package FPU_DEFINITION;
typedef struct packed {
logic Sign;
logic [7:0] Exponent;
logic [22:0] Mantissa;
} ieee_float; //IEEE-753 floating point number rapresentation
typedef struct packed {
logic Eff_Sign;
logic [7:0] Eff_Exponent;
logic [23:0] Eff_Mantissa;
} ieee_effloat; //IEEE-753 floating point number rapresentation effective mantissa
endpackage
import FPU_DEFINITION::*;
`endif
I don't know why this happen, I even closed the if with the else...
The way the latch is created in verilog is when you do not assign all outputs in all branches of an always block. In your situation:
always_comb
begin
you create a default value for MantissaSum. This way it is always assigned.
MantissaSum = In1_ADD.Eff_Mantissa + In2_ADD.Eff_Mantissa;
now, when you shift it in one of the branches and do not do anything in the other one the previous statement will take care of it.
if(MantissaSum[24] == 1'b1) //If overflow
begin
MantissaSum >>= 1; //Shift the mantissa of 1
However, here is you problem. your Out_ADD.Exponent is only assigned in the true branch of the if statement. If ManticcaSum[24] is not 1, then its value is supposed to be the same as before. This is a latch behavior.
Out_ADD.Exponent = A_ADD.Exponent + 1; //<== Here is the latch (?)
The rest is ok. Out_ADD.Mantissa is assigned in all branches.
Out_ADD.Mantissa = MantissaSum [22:0]; //Select the first 23 bit
end
else
begin
Out_ADD.Mantissa = MantissaSum [22:0]; //Select the first 23 bit
end
end
If this is what you want, you shold split this always block in two: one with always_comb, the second as always_latch, which takes care of the exponent. Or you should review your algorithm.
I believe the problem lies in the line Out_ADD.Mantissa = MantissaSum [22:0]; because in the true and the false condition this statement is executed, I think the synthesized version of your code will infer a latch with the enable = !MantissaSum[24] ( not 100% sure), I think the following change will keep the same logic and remove the latch.. just remove the line Out_ADD.Mantissa = MantissaSum [22:0]; from both the true and the false conditions and instead outside of the always_comb block type the following assign Out_ADD.Mantissa = MantissaSum [22:0];, tell me if that solved your problem
I am new to SystemVerilog and I would like to know how multiple assignments to the same signal are handled inside an always_comb block.
I am analyzing an FSM written by someonelse and I don't understand which would be the next state (signal named "ctrl_fsm_ns") if all the if-statements are true. Searching on google, I found out that here blocking assignments are used, so I expect that the last if-statement will decide the next state (so it is like a certain priority is assigned to each if-statement). But what if inside each if-block different signals are asserted? They will be all asserted even if the next state will be the last one, for example?
Here is the piece of code I don't understand.
always_comb
begin
...
unique case (ctrl_fsm_cs)
...
FIRST_FETCH:
begin
is_decoding_o = 1'b0;
// Stall because of IF miss
if ((id_ready_i == 1'b1) )
begin
ctrl_fsm_ns = DECODE;
end
// handle interrupts
if (irq_req_ctrl_i & irq_enable_int) begin
// This assumes that the pipeline is always flushed before
// going to sleep.
ctrl_fsm_ns = IRQ_TAKEN_IF;
halt_if_o = 1'b1;
halt_id_o = 1'b1;
end
if ((debug_req_pending || trigger_match_i) & (~debug_mode_q))
begin
ctrl_fsm_ns = DBG_TAKEN_IF;
halt_if_o = 1'b1;
halt_id_o = 1'b1;
end
end
Your question to the code above is a general programming question and not Verilog-specific. Because there are only blocking assignments in use, the code is entirely procedural.
Since the code isn't using an "if-else-if" sequence, but just "if-if-if", all the "if" conditions will be evaluated IN ORDER, and all assignments will happen IN ORDER, thus the final assignment will win out (as Dave said).
In your comments above you asked about what if (A_expr,B_expr,C_expr) where all true? Then (A,B,C) will all be set to 1.
A_expr=1; B_expr=1; C_expr=1;
if (A_expr) A = 1;
if (B_expr) B = 1;
if (C_expr) C = 1;
For each variable in the always_comb block, the last assignment is the final value. The tool analyzes the procedural flow to make sure every variable that is being assigned has at least one assignment in every possible flow through the code. If there is any possibility that a variable could be read without being written to, that is considered latch behavior and would be illegal for an always_comb block.
You need to look at the code before or after the case statement to see if there are any other assignments to the halt_ variables.
An example based on your comments:
always_comb begin
A = 0; B = 1; C = 2;
if (I) A = X;
if (J) B = Y;
if (K) begin B = Z; C = Z; end
end
That is equivalent to these three continuous assignments:
assign A = I ? X : 0;
assign B = K ? Z : (J ? Y : 1 );
assign C = K ? Z : 2;
Each if statement becomes a multiplexor, and the latter statements have the higher priority.
I need to check if the imaginary part is very small and set it to zero if it is in order to eliminate some floating point errors that result in very small non-zero imaginary parts when it should be zero.
My code is as follows:
kz2 = SQRT((n2*(2.0*PI*eta))**2 - kxarray(p)**2)
kz1 = SQRT((n1*(2.0*PI*eta))**2 - kxarray(p)**2)
if (aimag(kz2) < 0.0005) then
kz2 = (REAL(kz2),0.0)
end if
if (aimag(kz1) < 0.0005) then
kz1 = (REAL(kz1), 0.0)
end if
Unfortunately the compiler just returns:
gaussian1.f90:122.18:
kz2 = (REAL(kz2),0.0)
1
Error: Expected a right parenthesis in expression at (1)
gaussian1.f90:126.18:
kz1 = (REAL(kz1), 0.0)
1
Error: Expected a right parenthesis in expression at (1)
Any advice would be greatly appreciated - am I even going about this problem the right way?
UPDATE: I managed to avoid the problem by using:
if (aimag(kz2) < 0.0005) then
kz2 = real(kz2)
end if
if (aimag(kz1) < 0.0005) then
kz1 = real(kz1)
end if
But what would I do if I wanted to set the imaginary part to a non-zero amount?
In Fortran 2008 there are even more possibilities. You can access real and imaginary parts as derived type components, e.g.
a = c%re
b%im = 5
So, to set imaginary part of z to zero in new compilers you can try z%im = 0 .
I think you are looking for the CMPLX function, which converts real or integer arguments to a complex number. So it you example you should be able to do something like this:
kz1 = cmplx(real(kz1), 0.)
The (1.0,1.0) style parenthesis notation you have tried is only valid for constant values, not forming a complex number from the values held in variables.
I'm looking to be able to parametric some behavioral level Verilog using the generate block. The module is for a re-configurable readout and FIFO block, mainly so we can code this up one and just use a parameter at the top level.
Lets say we have:
always #(posedge write_out_clk or posedge RESETN)
begin
if (RESETN)
SENSE_ADDR <= 0;
else if (enb[0] == 1)
SENSE_ADDR <= 1; // for example but may be some other wire/bus etc
else if (enb[1] == 2)
SENSE_ADDR <= 1; // for example but may be some other wire/bus etc
else
SENSE_ADDR <= SENSE_ADDR;
end
end
This is behavioral so the specifics of implementation are left to the compiler with user given timing constraints etc. This works for 'n' else-if statements within the block if I hard code them, currently synthesis and simulation are both working for 16 statements.
My question however is how to parameterise this using generate? Clearly if 'n=8' its not too much of a big deal to hard code it. What if 'n=64' or 'n=128' etc. Seems a shame to hard code it if the rest of the module is fully parameterized using the generate for 'n'...
I have tried doing something like:
genvar elseif_generate;
generate
for (elseif_generate=0; elseif_generate<FIFO_SUB_BLOCKS; elseif_generate=elseif_generate+1)
begin: elseif_generate_logic
always #(posedge write_out_clk or posedge RESETN)
begin
if (RESETN)
SENSE_ADDR <= 0;
else if (enb[elseif_generate] == 1)
SENSE_ADDR <= some_wire[elseif_generate];
else
SENSE_ADDR <= SENSE_ADDR;
end
end
endgenerate
This however leads to Multi-source errors for the output wire 'SENSE_ADDR'. This leads me to the further question. Clearly a generate block is not suitable here but how would I go about implementing parameterised code replication for this block? Basically I want the functionality of the behavioral, hard coded if-else always block in a parameterised form...
Does this serve your needs? No generate required.
module mux #(
parameter WIDTH = 5,
parameter NUM = 2,
parameter NUMLG = $clog2(NUM)
) (
input [NUMLG -1:0] sel,
input [WIDTH - 1:0] in [0:NUM-1],
output [WIDTH - 1:0] out
);
assign out = in[sel];
endmodule
If your simulator doesn't support SystemVerilog that well you'll have to modify this to blow out the input array but the concept is the same.
You don not need a generate block. Add a combination always block to calculate next_SENSE_ADDR that will be flopped to SENSE_ADDR.
always #(posedge write_out_clk or posedge RESETN)
begin
if (RESETN)
SENSE_ADDR <= 0;
else
SENSE_ADDR <= next_SENSE_ADDR;
end
integer idx;
always #* begin // #(SENSE_ADDR or enb or some_wire)
next_SENSE_ADDR = SENSE_ADDR; // default, value if enb is all 0
// count down because lsb has higher priority
for ( idx=FIFO_SUB_BLOCKS-1; idx>=0; idx-- ) begin
if ( enb[idx] )
next_SENSE_ADDR = some_wire[idx];
end
end
I am reading some Fortran code, and every so often the previous programmer throws in the statement 'n = n'. What is the purpose of this? Some example code:
if (cmult.lt.5.) then
kx = 0
do k=ipd(ii),lpd(ii)
kx = kx + 1
p1(kx) = epp_rfc(ipp,k)
epp_rfc(ipp,k) = cmult*epp_rfc(ipp,k) + x
zero(ix)
p2(kx) = epp_rfc(ipp,k)
n = n
enddo
if (cmult.gt.0.) then
n = n
endif
else
nk = lpd(ii) - ipd(ii) + 1
do k=ipd(ii),lpd(ii)
kx = kx + 1
p1(kx) = epp_rfc(ipp,k)
epp_rfc(ipp,k) = pp(imem) + zero(ix)
p2(kx) = epp_rfc(ipp,k)
n = n
enddo
endif
Code like this is frequently used to allow the programmer to set a breakpoint in debuggers that don't support conditional breakpoints.
By setting a breakpoint on that line, it will only be hit if cmult.gt.0.
The fact that n = n is used for checking the value of cmult.gt.0. and is used as 'condition breakpoint' is coincidental in a sense that it's not the reason why n = n appears in the above code snippet.
The real reason why n = n is used in this case lies in the fact that scope in the source code is never translated by the most popular compilers to assembly language (the computer is not smart enough to understand what 'scope' is unless its explicitly programmed by the programmer and if it did the programs will run 100s of time slower ... because of the extra instructions emitted for the logic to support scoping). It's only there to constraint the programmer in the source code and introduce a structure to the code so that linker & compiler can do their job - or issue error if violate scoping.
Because scope doesn't exist enddo cannot be paused at unless the comipler takes care to insert some instruction(like nop) and debug symbols for it to magically allow the debugger to stop at enddo. Without n = n the outcome of this line p2(kx) = epp_rfc(ipp,k) cannot be checked as the values reset at the top of the loop. This is why n = n is used to stop after the p2(kx) = epp_rfc(ipp,k) and check the final result on each itteration. After it when this code comes:
if (cmult.gt.0.) then
n = n
endif
is used for convenience (again you cannot stop at endif or else) purposes and yes this is kind of conditional breakpoint. But n = n is again used because you cannot stop after checking if (cmult.gt.0.) - you can stop at it but not after it - the next instruction will be after the outer if else. I hope this makes sense.
Edit: If it still doesn't make too much sense here is additional info: in order to check the value of p2(kx) after p2(kx) = epp_rfc(ipp,k) has executed the debugger has to emit instructions to check/fetch it - hence it is required to know a) what is the size of p2(kx) b) it's location - remember the last instruction(s)! and c) emit the appropriate instructions to fetch the value p2(kx). All to complicated for the debugger as this is actually logic - the debugger has to be 'smart' (falls into AI domain), if a debugger could do this Terminator would have existed by now.