Getting strange error in verilog (vcs) when trying to use if/else blocks - verilog

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.

Related

Two always block in the same module. If the following technique is wrong someone suggest me an alternative way

I am using two always block in the same module. Will it cause an error to synthesizable code? The source code is written in Verilog given below
module Mux (input wire[7:0] iterate, input wire deterministicEnable, input wire bistMode, input wire enable, input wire clk, input wire rst, output reg[127:0] valueO);
reg [9:0] seedVal[0:2];
reg[31:0] generatePattern [0:3],temp;
integer i;
always begin
#(deterministicEnable)begin
if(deterministicEnable==1)begin
temp<={22'b000000000000,seedVal[iterate]};
end
end
end
always#(posedge clk)begin
if(rst)begin
temp<=32'b11111111111111111111111111111111;
seedVal[0]<=10'b1001100101;
seedVal[1]<=10'b1111111111;
seedVal[2]<=10'b0000011111;
generatePattern[0]<=32'b00000000000000000000000000000000;
generatePattern[1]<=32'b00000000000000000000000000000000;
generatePattern[2]<=32'b00000000000000000000000000000000;
generatePattern[3]<=32'b00000000000000000000000000000000;
end
else begin
if((bistMode==1) && (enable==1))begin
for(i=0;i<4;i=i+1)begin
temp = {(temp[31] ^ temp[25] ^ temp[22] ^ temp[21] ^ temp[15] ^ temp[11] ^ temp[10] ^ temp[9] ^ temp[7] ^ temp[6] ^ temp[4] ^ temp[3] ^ temp[1] ^ temp[0]), temp[31:1]};
generatePattern[i] = temp;
end
valueO = {generatePattern[3],generatePattern[2],generatePattern[1],generatePattern[0]};
end
end
end
endmodule
As David suggested, this is not synthesizable because you drive temp from 2 different always blocks. To make it working, you need to combine both of them into a single one.
the first always is a complete mess which will behave as a messed-up flop in simulation due to truncated sensitivity list. Even if a synthesis tools would do something with the block, the result will not match simulation.
The second block might be synthesizable, but it will probably behave differently in hardware than in simuilation due to mixed use of blocking/non-blocking assignments for the same vars.
So, what to do.
you need to create a single always block out of 2 of them. It is difficult to see what your intent is, but in general it will probably look like:
always #(posedge clk) begin
if (rst) ...
else if (deterministicEnable) ...
else if if((bistMode==1) && (enable==1)) ..
end
it seems that both temp and generatePattern are internal variables and they do not need any reset. So, remove them from the if (rst) cluase. I do not see a need for temp at all in your code. You can remove it completely. There is also no use for the seedVal, so i do not see why you initialize them at all.
you are correct by using blocking assignments (=) for assigning to temp and to generatePattern, because they are internal vars. However value0 is not internal and you should have used an nba (<=) to assign. For that reason the value0 variable should be initialized with the rst signal, it is not.
No, this is not synthesisable, an always block creates a driver for all the signals assigned in it and each signal must always have only one driver (ignoring some exceptions for tristate not relevant here).
always begin
#(deterministicEnable)begin
is also not synthesisable as far as I know. If you want a combinational (not clocked), use always #* begin.

Bit by bit comparison between two variables in Verilog

Currently, I am beginning to write the firmware by Verilog for one idea. It is comparing bit by bit between two variables and then using one binary counter to count the number of different bits.
For example:
I have two variables in verilog
A : 8'b00100001;
B : 8'b01000000;
Then I give the condition to compare bit by bit between two variables. If there is difference between 1 bit of A and 1 bit of B at same bit position, binary counter will count.
This is my verilog code:
module BERT_test(
input CLK,
input RST,
input [7:0] SIG_IN,
input [7:0] SIG_OUT,
output [7:0] NUM_ERR
);
integer i;
reg[7:0] sign_in;
reg[7:0] sign_out;
always #(posedge CLK) begin
sign_in[7:0] <= SIG_IN[7:0];
sign_out[7:0] <= SIG_OUT[7:0];
end
reg [15:0] bit_err;
// Combinational Logic
always #* begin
bit_err = 8'b0;
for (i=0;i<8;i=i+1) begin
if (sign_in[i] == sign_out[i]) begin
bit_err = bit_err + 8'b0;
end else begin
bit_err = bit_err + 8'b1;
end
end
assign NUM_ERR = bit_err;
end
endmodule
Then I had a mistake
Reference to vector wire 'NUM_ERR' is not a legal reg or variable lvalue
I do not know how to solve this problem. Are there any solutions for this problem or how I need to modify my firmware, please suggest me.
You are driving NUM_ERR (a net) from an always block. It is not permitted to drive nets from always blocks (or initial blocks). You need to move this line:
assign NUM_ERR = bit_err;
outside the always block.
You should not use an assign statement inside an always block. This is legal but is deprecated and means something weird. If you have included this line inside the always block by mistake, then indenting you code properly would have shown it up.
You have an assign WITHIN an always block. Move it outside.
Adding zero to bit error if the bits are the same is superfluous.
if (sign_in[i] != sign_out[i])
bit_err = bit_err + 8'b1;
Also bit error is 16 bits so it is not wrong to add 8'b1 but misleading.

Verilog Module Instantiation and empty begin end

I have made two verilog modules. The first one takes a nine-bit number and returns the position of first occurrence of 1 in it.
module findPositionOf_1(
input [8:0] data,
output reg [3:0] position
);
always #(data)
begin
if(data==9'b0000_00000)
position=4'b0000;
else if(data[0]==1)
position=4'b0000;
else if(data[1]==1)
position=4'b0001;
else if(data[2]==1)
position=4'b0010;
else if(data[3]==1)
position=4'b0011;
else if(data[4]==1)
position=4'b0100;
else if(data[5]==1)
position=4'b0101;
else if(data[6]==1)
position=4'b0110;
else if(data[7]==1)
position=4'b0111;
else if(data[8]==1)
position=4'b1000;
end
endmodule
The second module is returning the second occurrence of 1. It is calling the first module first changing that bit to zero and again finding the occurrence of 1.
module findPositionOf_2nd_1(
input [8:0] r1_data,
output [3:0] position1
);
reg [3:0] pos,pos2;
reg [8:0] temp;
integer i;
always #(r1_data)
begin
findPositionOf_1 f1(.data(r1_data), .position(pos));
i=pos;
temp=r1_data;
temp[i]=0;
findPositionOf_1 f2(temp,pos2);
if(pos2==4'b0000)
position1=0;
else
position1=pos2;
end
endmodule
I am getting the following errors during compilation. Please help.
Checker 'findPositionOf_1' not found. Instantiation 'f1' must be of a
visible checker.
A begin/end block was found with an empty body. This
is permitted in SystemVerilog, but not permitted in Verilog. Please
look for any stray semicolons.
By the way you write code it seems like you've not completely grasped how verilog(and other HDL languages) is different from "normal", procedural, coding.
You seem to assume that everything inside your always# block will execute from top to bottom, and that modules are similar to functions. This is not the case. You need to think about how you expect the hardware to look when you've designed your module.
In this case you know that you want two findPositionOf_1 modules. You know that you want the result from the first (u_f1) to affect the input of the second (u_f2). To do this, instantiate the two modules and then determine the interconnect between them.
We can create a vector with a 1 in position pos by left-shifting '1 pos number of times (1<<pos). By xor-ing the bits together, the statement r1_data ^ 1<<pos will remove the unwanted 1.
module findPositionOf_2nd_1(input [8:0] r1_data, output [3:0] position1 );
wire [3:0] pos,pos2;
wire [8:0] temp;
findPositionOf_1 u_f1(.data(r1_data), .position(pos));
findPositionOf_1 u_f2(.data(temp), .position(pos2));
assign temp = r1_data ^ (1<<pos);
assign position1 = pos2;
endmodule
You have instantiated your module inside an always block which is a procedural block, which is syntactically incorrect. Secondly, you have used your first module as a function call, which is not permitted. As said, you need to have a separate testbench, where you can connect your both modules and check. Make the position of occurance of 1st one as input to the findPositionOf_2nd_1 module. For your question, perhaps this should help
Why can't I instantiate inside the procedural block in Verilog

Verilog: tristates for synthesis, and difference between conditional and case?

How do I convert a tristate bus to 2-state logic for synthesis?
I've made a little test
module test1( inout tristate, output flattened);
assign flattened = tristate ? 1 : 0;
endmodule
module test2( inout tristate, output reg flattened);
always #(tristate) begin
case(tristate)
0: flattened = 0;
default: flattened = 1;
endcase
end
endmodule
`timescale 1ns / 1ps
module test_tb;
reg tristateEnable;
reg tristateValue;
wire tristate = tristateEnable ? tristateValue : 1'bz;
wire flattened1, flattened2;
test1 uut1(tristate, flattened1);
test2 uut2(tristate, flattened2);
initial begin
tristateValue = 1'b0;
tristateEnable = 1;
#10 tristateValue = 1'b1;
#10 tristateEnable = 1'b0;
end
endmodule
Simulating it I got that module test1 sets flattened to X and module test2 sets it to 1, the latter is what I wanted, but I haven't synthesized it yet. Is there a better / standard way of doing this?
You've asked two questions: (1) what is the difference between the conditional operator and the case statement, and (2) how to handle tri-state values.
On the language question:
In short, Verilog has a 4-state data type, and the operators handle the 4 states differently.
The case statement does a "4-state test", otherwise known as "case equality". The case expression (tristate in your example) is compared against 0, 1, x, and z. When it is z, the default branch is taken, so flattened is 1, as you found.
The conditional ('ternary') operator also does a 4-state test, and finds tristate as z. It doesn't know what to do now, so it combines the two values you supplied (0 and 1) into a resulting x, which is what you see. Basically, it's trying to be smart. See table 5-21 in the 2005 LRM.
Note that the if statement does not do a 4-state test.
Tristates: you're confused because your control signal (tristate) goes to z; it's the data signal (flattened) that should go to z.
You don't 'flatten' tristates for synthesis; you normally model a pull-up or pull-down. This will be specific to your technology, but you may just need to instantiate a pullup or pulldown component. Your synthesiser may or may not do this automatically for you if you have code like
assign sig_o = (ena == 1'b1)? sig_i : 1'bz;
You need to read your synthesiser docs to be sure. Note that you should only ever use a conditional operator like this if ena is guaranteed to be 2-state (0/1).

Generate statement inside verilog task

I want to use generate statement inside a task. The following code is giving compile errors (iverilog).
task write_mem; //for generic use with 8, 16 and 32 bit mem writes
input [WIDTH-1:0] data;
input [WIDTH-1:0] addr;
output [WIDTH-1:0] MEM;
integer i;
begin
generate
genvar j;
for(j=0; j<i;j++)
MEM[addr+(i-j-1)] = data[(j*8):((j*8) + 8)-1];
endgenerate
end
endtask // write_mem
I also tried putting generate just after the line integer i, but still its producing errors. Any thoughts?
EDIT: I also tried putting genvar declaration between begin and generate statement in the above code. Its still producing compiler errors
Thanks in advance,
Jay Aurabind
What you are trying is not possible - a generate region (generate..endgenerate block) is only allowed in the module description (aka "top level"), i.e. the same level where you have parameters, wires, always- and inital-regions, etc. (see Syntax 12-5 in the IEEE Std. 1364-2005). Within a task a generate region is e.g. as invalid as an assign statement.
However, you can use a non-generate for-loop in a task (this is also synthesizeable).
Either way, you can not count from 0 to i-1 in synthesizeable code as 'i' is not constant. Also note that j++ is not valid verilog, you must write j=j+1 instead. Finally you probably want to use a nonblocking assignment (<=) instead of a blocking assignment (=), but this depends on how you intent to use this task.
genvars should be defined before the generate statement:
genvar j;
generate
for(j=0; j<i;j++)
MEM[addr+(i-j-1)] = data[(j*8):((j*8) + 8)-1];
endgenerate
Although your usage here does not look like it needs a generate statement a for loop would have done.
As pointed out by #CliffordVienna generate statements are for building hierarchy and wiring based on compile time constants. ie parameters can be changed for reusable code but are constant in a given simulation. Tasks do not contain hierarchy and therefore the use of a generate is invalid.
Any for loop that can be unrolled is synthesizable, some thing like:
task write_mem; //for generic use with 8, 16 and 32 bit mem writes
input [WIDTH-1:0] data;
input [WIDTH-1:0] addr;
output [WIDTH-1:0] mem;
integer i = WIDTH / 8; // CONSTANT
begin
for(j=0; j<i;j++) begin
mem[addr+(i-j-1)] = data[(j*8):((j*8) + 8)-1];
end
end
endtask // write_mem
Tasks are synthesizable as long as they do not contain any timing control, which yours does not. From the information given this should be synthesizable.
NB: I would separate data width and addr width, they might be the same now but you might want to move to 8 bit addressing and 16 bit data.

Resources