I am studying verilog as part of my university course however my module lecturer left so I was hoping for some help here,
An example we have been given for a parametric n-bit gray to binary code converter, as follows:
module bin_n_gray #(parameter n=4) (input [n-1 : 0] gray, output [n-1 : 0] bin);
integer i;
always # (*)
for(i = 0; i < n; i = i+1)
bin[i] = ^(gray >> i);
endmodule
My question:
As the bin[i] variable is on the left hand side of an assignment statement within an # always block shouldn't this variable be declared as output reg [n-1 : 0] bin?
As I thought that a variable on the left hand side of an assignment statement of a process block i.e always / initial should be declared as a reg datatype?
As the bin[i] variable is on the left hand side of an assignment statement within an '# always' block shouldn't this variable be declared as 'output reg [n-1 : 0] bin?
Yes, it should require the reg as you say, at least according to Xilinx XST. The code as given in your question errs when synthesizing using that tool (and is missing an unrelated semicolon).
First let's begin by understanding what a procedural block in Verilog is, exactly (with the assumption that we're using Verilog to develop hardware, such as an FPGA design). Procedural blocks are always blocks (of two types, combinational and sequential) as well as few other types of blocks we won't cover here. The first thing to know is that in a procedural block, the only assignments allowed are those that have a reg on the left hand side.
This doesn't necessarily mean that a physical register/flipflop will be created. In this case, one will not be. The reason is the declaration of the block as always # (*). This declaration means that the process is combinational (i.e. not sequential, not having any internal state or clock signal). As a result, no physical flip-flops are created.
Alternatively, you can have a procedural block declared as always # (posedge some_clock_signal). This means that sequential logic is created, and physical flip-flops (or other means of storage such as the distributed memory in FPGA lookup tables) may be used. The takeaway is that you're still declaring as reg there, but now you're actually creating registers.
There is one case where you use wire (or output), which is by continuous assignment (for example, assign a = b & c), which falls outside a procedural block. In this example, I'm using generate to do the same thing as the loop in your original code:
module bin_n_gray #(parameter n=4) (input [n-1 : 0] gray, output [n-1 : 0] bin);
genvar i;
generate
for (i=0; i < n; i=i+1)
begin: graydecoder // arbitrary label needed by generate syntax
assign bin[i] = ^(gray >> i);
end
endgenerate
endmodule
Related
I have read through all similar posts, but none address the issue I'm having, namely that line 41 assign Y[b]=~Y[b]; causes error "Illegal left-hand side in continuous assignment."
I haven't assigned any regs so I don't see what the issue is. If I replace b with an actual number (say, 3) it works fine. But I need b as a variable here.
// Hamming code 1-bit error correction
module HCG(I,e,O);
input [4:1] I; // input BCD
input [7:1] e; // noise simulation
wire [7:1] X; // Hamming code
wire [7:1] Y; // Hamming code after addition of noise
wire [3:1] P; // Parity at start
wire [3:1] S; // Parity at end
wire b; // the error bit
output [4:1] O; // corrected output
assign X[1]=I[1]^I[2]^I[4]; // Hamming code generator
assign X[2]=I[1]^I[3]^I[4];
assign X[3]=I[1];
assign X[4]=I[2]^I[3]^I[4];
assign X[5]=I[2];
assign X[6]=I[3];
assign X[7]=I[4];
assign P[1]=X[1]; // Parity at start
assign P[2]=X[2];
assign P[3]=X[4];
assign Y[1]=e[1]^X[1]; // noise added
assign Y[2]=e[2]^X[2];
assign Y[3]=e[3]^X[3];
assign Y[4]=e[4]^X[4];
assign Y[5]=e[5]^X[5];
assign Y[6]=e[6]^X[6];
assign Y[7]=e[7]^X[7];
assign S[1]=Y[3]^Y[5]^Y[7]; // Parity at end
assign S[2]=Y[3]^Y[6]^Y[7];
assign S[3]=Y[5]^Y[6]^Y[7];
assign b=(S[1]!=P[1])? b:b+1; // if parity of 2^0 not the same, add 1 to b
assign b=(S[2]!=P[2])? b:b+2; // if parity of 2^1 not the same, add 2 to b
assign b=(S[3]!=P[3])? b:b+4; // if parity of 2^2 not the same, add 4 to b
assign Y[b]=~Y[b]; // correct the incorrect bit
assign O[1]=Y[3]; // assigning outputs
assign O[2]=Y[5];
assign O[3]=Y[6];
assign O[4]=Y[7];
endmodule
The lines between module and endmodule are executed concurently. (It seems like you think they are executed sequentially.) Therefore, you are driving all the bits of Y in these lines
assign Y[1]=e[1]^X[1]; // noise added
assign Y[2]=e[2]^X[2];
assign Y[3]=e[3]^X[3];
assign Y[4]=e[4]^X[4];
assign Y[5]=e[5]^X[5];
assign Y[6]=e[6]^X[6];
assign Y[7]=e[7]^X[7];
and then are driving one of the bits of Y again in this line:
assign Y[b]=~Y[b]; // correct the incorrect bit
So (a) you have a short circuit and (b) which bit has the short circuit? That depends on b. So, the position of the short circuit depends on the state of one of the internal wires. You have described a circuit that can reconfigure itself depending on its inputs. Verilog won't let you do that. Verilog is a hardware description language. Conventional digital hardware can't reconfigure itself depending on the state of its inputs.
The problem is the continuous assignment you are doing. To quote from the IEEE Std 1800-2012. (Section 10.3) on continuous assignments:
Continuous assignments shall drive values onto nets or variables, both vector (packed) and scalar. This assignment shall occur whenever the value of the right-hand side changes. Continuous assignments provide a way to model combinational logic without specifying an interconnection of gates.
When you do assign Y[b]=~Y[b], the assignment itself automatically causes the right-hand side to change again, which triggers the assignment again.
Verilog standard lists legal lhs values for the continuous assignment as the following (Table 10-1):
Net or variable (vector or scalar)
Constant bit-select of a vector net or packed variable
Constant part-select of a vector net or packed variable
Concatenation or nested concatenation of any of the above left-hand sides
in your case Y[b] is not a constant selection, because b is not a constant. Therefore syntactically your lhs is illegal and you get this message from the compiler.
On a side note you have a zero-delay loop here. See other answers for explanation.
I'm new to Verilog, ISE, FPGAs. I'm trying to implement a simple design into an FPGA, but the entire design is being optimized away. It is basically an 2D array with some arbitrary values. Here is the code:
module top(
output reg out
);
integer i;
integer j;
reg [5:0] array [0:99][0:31];
initial begin
for(i=0;i<100;i=i+1) begin
for(j=0;j<32;j=j+1) begin
array[i][j] = j;
out = array[i][j];
end
end
end
endmodule
It passes XST Synthesis fine, but it fails MAP in the Implementation process. Two Errors are given:
ERROR:Map:116 - The design is empty. No processing will be done.
ERROR:Map:52 - Problem encountered processing RPMs.
The entire code is being optimized away in XST. Why? What am I doing wrong?
The reason your design is being synthesized away is because you have not described any logic in your module.
The only block in your design is an initial block which is typically not used in synthesis except in limited cases; the construct mainly used for testbenches in simulation (running the Verilog through ModelSim or another simluator).
What you want is to use always blocks or assign statements to describe logic for XST to synthesize into a netlist for the FPGA to emulate. As the module you provided has neither of these constructs, no netlist can be generated, thus nothing synthesized!
In your case, it is not entirely clear what logic you want to describe as the result of your module will always have out equal to 31. If you want out to cycle through the values 0 to 31, you'll need to add some sequential logic to implement that. Search around the net for some tutorials on digital design so you have the fundamentals down (combinational logic, gates, registers, etc). Then, think about what you want the design to do and map it to those components. Then, write the Verilog that describes that design.
EDIT IN LIGHT OF COMMENTS:
The reason you are get no LUT/FF usage on the report is because the FPGA doesn't need to use any resources (or none of those resources) to implement your module. As out is tied to constant 31, it will always have the value of 1, so the FPGA only needs to tie out to Vdd (NOTE that out is not 31 because it is only a 1-bit reg). The other array values are never used nor accesses, so the FPGA synthesized them away (ie, not output needs to know the value of array[0][1] as out is a constant and no other ports exist in the design). In order to preserve the array, you need only use it to drive some output somehow. Heres a basic example to show you:
module top( input [6:0] i_in, // Used to index the array like i
input [4:0] j_in, // Used to index the array like j
output reg [5:0] out // Note, out is now big enough to store all the bits in array
);
integer i;
integer j;
reg [5:0] array[0:99][0:31];
always #(*) begin
// Set up the array, not necessarily optimal, but it works
for (i = 0; i < 100; i = i + 1) begin
for (j = 0; j < 32; j = j + 1) begin
array[i][j] = j;
end
end
// Assign the output to value in the array at position i_in, j_in
out = array[i_in][j_in];
end
endmodule
If you connect the inputs i_in and j_in to switches or something and out to 6 LEDs, you should be able to index the array with the switches and get the output on the LEDs to confirm your design.
I have a project, written in Verilog (importantly not SystemVerilog) which has gotten a little unmanageable due to the number of signals being passed along between different parts of the design. Since I have several modules which all need the same signals, I was thinking of trying to consolidate them into a smaller number of named objects. The questions is how to do it.
Let's say this is my contrived example:
module mymodule(sig_a_in, sig_b_in, sig_c_in, sig_d_in, sig_e_in,
sig_a_out, sig_b_out, sig_c_out, sig_d_out, sig_e_out);
input wire sig_a_in, sig_b_in, sig_c_in;
input wire [5 : 0] sig_d_in;
input wire [31 : 0] sig_e_in;
output reg sig_a_out, sig_b_out, sig_c_out;
output reg [5 : 0] sig_d_out;
output reg [31 : 0] sig_e_out;
endmodule
It is important, in my opinion, for readability that I can reference the signals by name. However, I don't want to have to pass them all individually to each module. Again, I am only using Verilog in this project so SystemVerilog constructs are not possible.
My first thought was that I would just combine them into one bus and then use defined names to reference the individual wires. This is kind of clunky, however, particularly when you add other buses into the mix. This is pretty trivial in my contrived example because the signals have an obvious implicit order, but in real life they don't.
`define SIGNAL_BUS_WIDTH 41
`define A 0
`define B 1
`define C 2
`define D 3
`define E 9
module mymodule(signal_bus_in, signal_bus_out);
input wire [`SIGNAL_BUS_WIDTH-1 : 0] signal_bus_in;
output reg [`SIGNAL_BUS_WIDTH-1 : 0] signal_bus_out;
// reference a
signal_bus_in[`A]
// reference d? Not good when names don't have an obvious order
signal_bus_in[`E-1 : `D]
endmodule
Finally, in addition to all of this, it is necessary for the tool chain to be able to distinguish which wires in the struct are being used by the module and to only synthesize those wires. Not all the modules use all the wires, so I want to avoid having extra unused paths. I think that the tools should be smart enough to do this, even in my bus example above, but I'm not completely sure.
Is there a good way to get what I want in Verilog?
You can always extend you idea a bit further by use macros to define the range of each signal rather than an endpoint:
`define WIDTH 41
`define sigA 0:0
`define sigB 1:1
`define sigC 2:2
`define sigD 8:3
`define sigE 40:9
module mymodule(signal_bus_in, signal_bus_out);
input wire [`WIDTH-1 : 0] signal_bus_in;
output reg [`WIDTH-1 : 0] signal_bus_out;
...
// signal a
signal_bus_in[`sigA];
// signal d
signal_bus_in[`sigD];
...
Of course, this isnt as easy as SystemVerilog packed structs (which is why they exist!), but it will work for what you want. Also, this added order to your lines as well, but I see no structure that wont do that; even structs will add an order to your signals. So long as you use the macros however, it doesnt really matter that there order except when you define the marcos.
Any good synthesis tool should be able to throw out any port or wire that does not drive anything or is not drive by anything, so unless you have to explicitly tell it which lines to ignore for some reason, you shouldnt worry about it synthesizing extra space for unused module pins.
Verilog does not have structs. IMO combining all signals in a long vector (or as you call it a bus) is your best bet. But, you can slightly improve upon your macros:
`define SIGNAL_BUS_WIDTH 41
`define A 0:0
`define B 1:1
`define C 2:2
`define D 8:3
`define E 40:9
// reference a
signal_bus_in[`A]
// reference d
signal_bus_in[`D]
// reference e
signal_bus_in[`E]
Most synthesis tools do not create extra logic for the wires that are not connected and treat them as dont cares.
To avoid relying on the preprocessor so much, you might try using localparam and function declarations to simulate structures. Below is a mock-up of a "mybus" structure with four fields, named A through D, of various sizes, to illustrate this idea.
You could put these supporting parameters and functions into a file that you include only in the various modules that need to construct and destructure this kind of bus. This could perhaps allow you to use shorter names without fear of clashes.
module test ;
// Boilerplate structure size definitions -- you could automatically generate these
// with a simple script and put them into an include file.
localparam mybus_a_size = 4;
localparam mybus_a_offset = 0;
localparam mybus_b_size = 8;
localparam mybus_b_offset = mybus_a_offset + mybus_a_size;
localparam mybus_c_size = 4;
localparam mybus_c_offset = mybus_b_offset + mybus_b_size;
localparam mybus_d_size = 6;
localparam mybus_d_offset = mybus_c_offset + mybus_c_size;
localparam mybus_size = mybus_a_size + mybus_b_size + mybus_c_size + mybus_d_size;
// accessor functions, i.e., instead of bus.a you write mybus_a(bus)
function [mybus_a_size-1:0] mybus_a (input [mybus_size-1:0] in);
mybus_a = in[mybus_a_size + mybus_a_offset - 1 : mybus_a_offset];
endfunction
function [mybus_b_size-1:0] mybus_b (input [mybus_size-1:0] in);
mybus_b = in[mybus_b_size + mybus_b_offset - 1 : mybus_b_offset];
endfunction
function [mybus_c_size-1:0] mybus_c (input [mybus_size-1:0] in);
mybus_c = in[mybus_c_size + mybus_c_offset - 1 : mybus_c_offset];
endfunction
function [mybus_d_size-1:0] mybus_d (input [mybus_size-1:0] in);
mybus_d = in[mybus_d_size + mybus_d_offset - 1 : mybus_d_offset];
endfunction
// constructor function -- build a mybus out of its components
function [mybus_size-1:0] make_mybus(input [mybus_a_size-1:0] a,
input [mybus_b_size-1:0] b,
input [mybus_c_size-1:0] c,
input [mybus_d_size-1:0] d);
make_mybus = {d,c,b,a};
endfunction
// example of using this stuff
reg [mybus_size - 1 : 0] bus;
initial begin
bus = make_mybus(1,2,3,4);
$display("Hello, my bus is { a=%b, b=%b, c=%b, d=%b }", mybus_a(bus), mybus_b(bus), mybus_c(bus), mybus_d(bus));
end
endmodule
This mock up might make a good starting place. Some obvious improvements would be to generate all of this boilerplate automatically from a simple script, and to add additional constructor functions like "setters" in C++, i.e.,
set_mybus_a(mybus, 5) // set mybus.a = 5
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 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.