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.
Related
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
Below is the always block code.
I need to have same code 11 times, with same functionality but on different variables. So how can I reuse the code?
always #(posedge tconClk or negedge tconRst_n)
begin
if(~tconRst_n)
begin
pulse_cnt <= 0;
pulse_start = 0;
start_written = 0;
pulse_width <= 'h271;
end
else if(~pulse_rst)
begin
pulse_cnt <= 0;
pulse_start = 0;
end
else
begin
if(start_signal)
begin
// start_written = 0;
pulse_width <= (pulse_start) ? pulse_width : START_PW;
pulse_start = 1;
end
pulse_cnt <= (pulse_start) ? (pulse_cnt + 1) : pulse_cnt;
end
end
Naming Pattern -
tconClk, tconRst_n is common,
pulse_cnt0, pulse_cnt1 upto 10,
pulse_width0, pulse_width1 upto 10,
pulse_start[0:10] (Array),
start_written[0:10] (Array),
pulse_rst[0:10] (Array),
start_signal[0:10] (Array),
START_PW (No pattern, different name for each 11 always blocks)
Note -
Defining macro won't work, as this code contains many verilog tokens.
I can't make module of the code, because the signals used in the always block, are also used in other part of the code. So if I make module, then I won't be able to ensure proper reg or wire connections to the module. (Like a module output port must be a wire, but that same signal has been used as a reg in other part of code)
You can use the emacs script verilog-mode using encapulate the RTL in a module and utilize AUTO_TEMPLATE. Something like the following (not tested) then execute verilog-batch-auto within (or batch of) emacs:
/* PulseModule AUTO_TEMPLATE "\([0-9]+\)$" (
.pulse_cnt(pulse_cnt#),
.pulse_width(pulse_width#),
.pulse_start(pulse_start[#]),
.start_written(start_written[#]),
.pulse_rst(pulse_rst[#]),
.start_signal(start_signal[#]),
.tconClk(tconClk),
.tconRst_n(tconRst_n)
);
*/
PulseModule pm_0 (/*AUTOINST*/ .start_pulse_width(START_PW) );
PulseModule pm_1 (/*AUTOINST*/ .start_pulse_width(OTHER_START_PW) );
...
PulseModule pm_10 (/*AUTOINST*/ .start_pulse_width(SOME_OTHER_START_PW) );
There are also various embedded code (such as Perl's EP3, Ruby's eRuby/ruby_it, Python's prepro, etc.) that can generate the desired code.
SystemVerilog enhanced the functionality of macros. For you the `` feature will make your task easier. See IEEE Std 1800-2012 ยง 22.5.1 `define.
Multi-line macros are a pain to debug. Although it is possible to put your RTL as one macro, I strongly recommend putting it in a module and have the macro instantiate the macro. Something lake the following (not tested):
`define PULSEMACRO(id,val) \
PulseModule pm_``id( \
.pulse_cnt(pulse_cnt``id), .pulse_width(pulse_width``id), \
.pulse_start(pulse_start[id]), .start_written(start_written[id]), \
.pulse_rst(pulse_rst[id]), .start_signal(start_signal[id]), \
.start_pulse_width(val) \
.tconClk(tconClk), .tconRst_n(tconRst_n) )
This instantiate as like follows. Note that a generate for-loop will not work. Macros are evaluated before generate blocks.
`PULSEMACRO(0,START_PW);
`PULSEMACRO(1,OTHER_START_PW);
...
`PULSEMACRO(10,SOME_OTHER_START_PW);
SystemVerilog can also pass multi-dimensional arrays through module ports. Therefore you can rename reg [PULSE_CNT_WIDTH-1:0] pulse_cnt0,...,pulse_cnt10 to logic [PULSE_CNT_WIDTH-1:0] pulse_cnt [11]. With this conversion you can use generate loops.
Alternatively, you can collapse the pulse_cnt into a big bus reg [PULSE_CNT_WIDTH*11-1:0] pulse_cnt, then use bit slicing for indexing pulse_cnt[PULSE_CNT_WIDTH*index +: PULSE_CNT_WIDTH]. Bit slicing is also compatable with Verilog. See What is `+:` and `-:`? and Indexing vectors and arrays with +:
Put the always inside a generate statement. You should find lots of examples on SO: here, for instance. You still need to modify your code, which may be no easier than modifying it for module instantiation.
Your code is broken at the moment, because pulse_rst is tested before the clock edge, and it's not in the sensitivity list. You should put it in the list, or recode the block. Note that there are issues in Verilog with having two async controls and a clock; look up "verilog flops with async set and reset", or ask again with a different question.
I think you still can use macro. Change those non-common variables into a macro, for example pulse_cnt into `pulse_cnt. Put them into a file and use it as include file.
For example your code,
always #(...)
begin
`pulse_cnt <= 0;
// ...
end
Put this template into a file called for example, my_always.v
Then reuse the code in your other file/module as follows:
`define pulse_cnt pulse_cnt0
`include "my_always.v"
`undef pulse_cnt
`define pulse_cnt pulse_cnt1
`include "my_always.v"
`undef pulse_cnt
//... and so on
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.
wire [9:0] data_reg;
reg [3:0] Reverse_Count = 8; //This register is derived in logic and I need to use it in following logic in order to reverse the bit position.
assign data_reg[9:0] = 10'h88; // Data Register
genvar i;
for (i=0; i< Reverse_Count; i=i+1)
assign IReg_swiz[i] = IReg[Reverse_Count - 1 -i];
This is generating syntax error. May I know how to do this in verilog
If you'd have Reverse_Count as constant, your task boils down to just wire mix-up, which is essentially free in HDL.
In your case, the task can be nicely reduced to first mirroring wide data and then shifting by Reverse_Count to get LBS bit on its position, which itself is done just by a row of N-to-1 multiplexers.
integer i;
reg [9:0] reversed;
wire [9:0] result;
// mirror bits in wide 10-bit value
always #*
for(i=0;i<10;i=i+1)
reversed[i] = data_reg[9-i];
// settle LSB on its place
assign result = reversed>>(10-Reverse_Count);
Reverse_Count is not a constant, ie it is not a parameter or localparam.
This means that the generate statement you would be creating and destroying hardware as required, this is not allowed in verilog as it would not be possible in hardware.
The Bus that your reversing should have a fixed width at compile time, it should be possible to declare Reverse_Count as a parameter.
Since the value of Reverse_Count dunamic, you cannot use a generate statement. You can use an always block with for-loop. To be synthesizable, the for-loop needs able to static unroll. To decide which bits reverse, use an if condition to compare the indexing value and Reverse_Count
Example:
parameter MAX = 10;
reg [MAX-1:0] IReg_swiz;
integer i;
always #* begin
for (i=0; i < MAX ; i=i+1) begin
if (i < Reverse_Count) begin
IReg_swiz[i] = IReg[Reverse_Count - 1 -i];
end
else begin
// All bits need to be assigned or complex latching logic will be inferred.
IReg_swiz[i] = IReg[i]; // Other values okay depending on your requirements.
end
end
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.