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
Related
I am working on RTL coding of rs232 protocol in verilog I wrote the Tx/Rx codes in two different files.
I wanted to know whether these lines[as shown below] are legal in verilog. By legal I mean do they produce synthesizable output? I have initialized count_tx to 12. Basically, I want serial output through dataframe_tx. I know we can do this through the logical shift left, but I used this method.
In the waveform analyzer, I could see dataframe_tx always zero. That is where I started doubting these lines.
.
.
.
S_SENDING:begin
dataframe_tx = temp_tx[12-count_tx];
count_tx = count_tx - 1;
if(count_tx)
next_tx = S_SENDING;
else begin
next_tx = S_DONE;
done_tx = 1'b1;
end
end
.
.
.
.
To answer your question: The code fragment you posted consists of legal SystemVerilog constructs.
If one adds proper declarations of the objects you are referencing, adds the obvious missing case statement and wraps the whole in an always_ff block it will compile and thus generate synthesizable code.
You asked about syntax and not semantics. Will it work? Hard to tell from the fragment. But the intent of your if statement seems to be checking if the vector is non-zero. Consider if( |count_tx ) instead.
I added few lines to your code to make if syntactically OK. I also tool the liberty to change the assignments to non-blocking as these would be otherwise inferred by the tool. Still remains as a fragment but I hope it may help.
module Sandbox(
input logic clk
// inputs and outputs ...
);
logic dataframe_tx;
logic [12:0] temp_tx;
logic done_tx;
logic [3:0] count_tx;
enum {S_SENDING, S_DONE} next_tx;
always_ff #(posedge clk) // as an example
begin
case (next_tx)
// something ...
S_SENDING: begin
dataframe_tx <= temp_tx[12-count_tx];
count_tx <= count_tx - 1;
if( |count_tx )
next_tx <= S_SENDING;
else begin
next_tx <= S_DONE;
done_tx <= 1'b1;
end
end
// something ....
S_DONE: /* your code */;
endcase
end
endmodule
Good luck!
When I compile my code I get these error msg for following lines. can someone explain it.
This is verilog code for a processor
assign Imm = instruction[7:0];
assign OUT1addr = instruction[2:0];
assign OUT2addr = instruction[10:8];
assign INaddr = instruction[18:16];
assign address = instruction[23:16];
assign address = instruction[7:0];
The following message comes for ABOVE LINES
tgt-vvp sorry: procedural continuous assignments are not yet fully supp
orted. The RHS of this assignment will only be evaluated once, at the time the assignment statement is executed.
You did not do what I asked which is show me where that code is.
From the error message I very much suspect that code is inside an always block:
always #( ...)
...
assign Imm = instruction[7:0];
This is called "a procedural continuous assignment".
The alternative is:
always #( ...)
...
Imm = instruction[7:0];
This is a standard assignment.
There is a significant difference between the two. You would normally not use the first form (unless you really, really know what you are doing.)
Thus the solution is to remove all the 'assign' keywords if they are inside an always block.
Outside an always you need the assign:
always #( * )
begin
...
x = y ^ z;
end
assign write = valid & select;
The short answer is you should probably remove the assign keyword.
The assign keyword has two different meanings depending on context you do not show.
When used at the top level of a module, the assign keyword is a permanent process sensitive to RHS changes and assigns it to the LHS wire. The assign statement has equivalent functionality to the always block below
module mod;
...
assign Awire = B + C;
always #(B or C) begin
Areg = B + C;
end
endmodule
When used inside a procedural process, it is a temporary process that assigns the LHS variable every time the RHS changes. The two always blocks below have the same functionality
module top;
...
always #(sel)
begin
if (sel)
assign Areg = B;
else
assign Areg = C;
end
always #(sel or B or C) // #*
begin
if (sel)
Areg = B;
else
Areg = C;
end
endmodule
Unfortunately, almost all synthesis tools require you to write your code with a complete sensitivity list as in the latter always block. Thus this eliminates allowing the use of assign inside a procedural block.
When I try to synthesize my verilog project i get the following errors:
ERROR:Xst:2634 - "shiftman.v" line 15: For loop stop condition should depend on loop variable or be static.
ERROR:Xst:2634 - "shiftman.v" line 22: For loop stop condition should depend on loop variable or be static.
I think I understand what causes the error, but I can't find a way to fix it.
module shiftman(in,sh,out);
input[47:0] in;
input[8:0] sh;
output[47:0] out;
reg[47:0] out;
reg[7:0] r;
reg i;
always#(in or sh)
begin
r=sh[7:0];
out=in;
if(sh[8]==0)
for(i=0; i<r; i=i+1)
begin
out[23:0]={1'b0,out[23:1]};
end
else
for(i=0; i<r; i=i+1)
begin
out[47:24]={1'b0,out[47:25]};
end
end
endmodule
The reason your synthesis is failing is because you cannot uses variable-iteration loops in synthesizable code. When synthesizing, the tool will attempt to unroll the loop, but it cannot do this if the termination condition for the loop is not static or determinable at synthesis. Your condition i <= r is such a condition as we cannot unroll the loop without knowing r, which is an input to the module and thus, not static.
In order to fix this, youll need to rewrite your code in a way that the synthesis tool can process. By the looks of it, you are simply logically shifting either the top or bottom of in by sh[7:0] depending on sh[8]. In order to do this, you don't need looping at all, but can use the >> (logical right shift operator). So, your always block would look more like this:
always #(*) begin
out = in;
if (sh[8])
out[47:24] = in[47:24] >> sh[7:0];
else
out[23:0] = in[23:0] >> sh[7:0];
end
I am trying to write an "inverter" function for a 2's compliment adder. My instructor wants me to use if/else statements in order to implement it. The module is supposed to take an 8 bit number and flip the bits (so zero to ones/ones to zeros). I wrote this module:
module inverter(b, bnot);
input [7:0] b;
output [7:0]bnot;
if (b[0] == 0) begin
assign bnot[0] = 1;
end else begin
assign bnot[0] = 0;
end
//repeat for bits 1-7
When I try and compile and compile it using this command I got the following errors:
vcs +v2k inverter.v
Error-[V2005S] Verilog 2005 IEEE 1364-2005 syntax used.
inverter.v, 16
Please compile with -sverilog or -v2005 to support this construct: generate
blocks without generate/endgenerate keywords.
So I added the -v2005 argument and then I get this error:
vcs +v2k -v2005 inverter.v
Elaboration time unknown or bad value encountered for generate if-statement
condition expression.
Please make sure it is elaboration time constant.
Someone mind explaining to me what I am doing wrong? Very new to all of this, and very confused :). Thanks!
assign statements like this declare combinatorial hardware which drive the assigned wire. Since you have put if/else around it it looks like you are generating hardware on the fly as required, which you can not do. Generate statements are away of paramertising code with variable instance based on constant parameters which is why in this situation you get that quite confusing error.
Two solutions:
Use a ternary operator to select the value.
assign bnot[0] = b[0] ? 1'b0 : 1'b1;
Which is the same as assign bnot[0] = ~b[0].
Or use a combinatorial always block, output must be declared as reg.
module inverter(
input [7:0] b,
output reg [7:0] bnot
);
always #* begin
if (b[0] == 0) begin
bnot[0] = 1;
end else begin
bnot[0] = 0;
end
end
Note in the above example the output is declared as reg not wire, we wrap code with an always #* and we do not use assign keyword.
Verliog reg vs wire is a simulator optimisation and you just need to use the correct one, further answers which elaborate on this are Verilog Input Output types, SystemVerilog datatypes.
I am trying to write a simple module to output a 14-bit number based on the value of four input signals. My attempt is shown below.
module select_size(
input a,
input b,
input c,
input d,
output [13:0] size
);
if (a) begin
assign size = 14'h2222;
end
else begin
if (b) begin
assign size = 14'h1111;
end
else begin
if (c) begin
assign size = 14'h0777;
end
else begin
assign size = 14'h0333;
end
end
end
endmodule
Upon compilation, I receive the following error:
ERROR:HDLCompiler:44 - Line 67: c is not a constant
I don't understand why that particular if-statement isn't working if the other two preceding it are. I have tried changing the condition to
if (c == 1) begin
but to no avail.
Does anybody know how to solve this error? Thank you!
Two problems:
1) You need to put if statements inside an always block.
If you use verilog-2001, you can use
always #*
if ....
end
end
Otherwise specify all the inputs in the sensitivity list:
always #(a or b or c or d)
if ....
end
end
2) Constant assignments are not allowed inside if statements.
Remove the assign keyword from any statements inside the if block:
if (a) begin
size = 14'h2222;
end
You will also have to declare size as a reg type.
However my preference would be to rewrite the entire module with conditional operator, I find it much preferrable to read. This following module achieves the same result:
module select_size(
input a,
input b,
input c,
input d,
output [13:0] size
);
assign size = a ? 14'h2222 :
b ? 14'h1111 :
c ? 14'h0777 :
14'h0333 ;
endmodule
As #Tim has already answered, using reg types inside always blocks or wire with assign.
#Tim has also described the nested ternary assignments, while in the example are written very well, they are generally seen as bad practice. They imply a very long combinatorial path and can be hard to maintain. The combinatorial path may be optimised by synthesis which should imply a mux with optimised selection logic.
Easier to maintain code will have a lower cost of ownership, and as long as it does not lead to a larger synthesised design it is normally preferred.
My implementation would be to use a casez, (? are don't cares). I find the precedence of each value easier to see/debug.
module select_size(
input a,
input b,
input c,
input d,
output logic [13:0] size //logic (SystemVerilog) or reg type
);
always #* begin
casez ({a,b,c})
3'b1?? : size = 14'h2222 ;
3'b01? : size = 14'h1111 ;
3'b001 : size = 14'h0777 ;
3'b000 : size = 14'h0333 ;
default: size = 'bx ;
endcase
end
endmodule