In verilog Part-select of vector reg array is illegal - arrays

reg [data_width-1:0]coeff[0:order-1];
wire[3:0]lsbcoeff;
wire [7:4]msbcoeff;
lsbcoeff = coeff[3:0];
msbcoeff = coeff[7:4];
In the above line of code, im getting error
Part-select of vector reg array 'coeff' is illegal
Illegal right hand side of blocking assignment
Please guide me , how to overcome this ?
Xilinx v14.2
Verilog coding

You have coeff defined as a vector of coefficients, I am not sure what you expect coeff[3:0] to return? a vector of the LSBS? I think what you intended was something like coeff[0][3:0] Selecting the LSBs of the first vector. Code below shows a possible way of doing this:
module tb;
localparam data_width = 8;
localparam order = 2;
reg [data_width-1:0]coeff[0:order-1];
reg [3:0] lsbcoeff;
reg [7:4] msbcoeff;
reg [7:0] this_coeff;
always #* begin
lsbcoeff = coeff[0][3:0];
msbcoeff = coeff[0][7:4];
end
endmodule
and now I have read the comments I see this is what #Greg has already suggested.

In addition to #Morgan code, the wire should be assigned value using assign statement in verilog.
always #(*) begin
assign lsbcoeff = coeff[0][3:0];
assign msbcoeff = coeff[0][7:4];
end

Related

syntax error in accessing 2d register array in verilog code to synthesize in leonardo tool

I made a simple cache with verilog code in ISE tool, and used a 2d array of registers as my cache memory, simulating testbench on it in Modelsim done well and no syntax errors and no mistake in desires output signals, but in Leonardo tool when I tell Leonardo read it in library ams600nm it return syntax error near first line that I accessed my 2d array (cache), do you have any idea?
code:
module Cache(clk , wr
,din,adr,dout
);
input clk;
input wr;
input [3:0] din;
input [3:0] adr;
output [3:0] dout;
output hit;
reg [8:0] cache [3:0];
reg h;
reg [3:0] out;
initial
begin
***cache[0][8] = 1'b0; -----here-----
cache[1][8] = 1'b0; -----also here for sure-----
cache[2][8] = 1'b0;
cache[3][8] = 1'b0;***
end
You don't have output hit in module port list.
You don't have endmodule keyword.
Some software allow to access only all bits in array's row. I don't have access to your software, so I can't test it, but you should try something like that:
temp = cache[0];
cache[0] = {1'b 0, temp[7:0]};
This is equivalent to:
cache[0][8] = 1'b0;
temp should be declared as reg [8:0] temp; (same width as cache).

how to declare output array in verilog?

I am trying to ADD two array and want output in array in verilog code. But error is occured. which is ERROR:HDLCompiler:1335: Port sum must not be declared to be an array in verilog code . can anyone tell me how to declare output array in verilog code. Thanks.
module array(clk,sum,reset);
input clk,reset;
//input [7:0] din;
//input [7:0] A[3:0];
//input [7:0] B[3:0];
output sum[3:0];
wire [7:0] sum[3:0];
reg [7:0] A[3:0];
reg [7:0] B[3:0];
integer i;
always#(posedge clk)
begin
if(reset==1'b1)
begin
A[0]<=1;
A[1]<=2;
A[2]<=3;
A[3]<=4;
B[0]<=5;
B[1]<=5;
B[2]<=5;
B[3]<=5;
sum[0]<=0;
sum[1]<=0;
sum[2]<=0;
sum[3]<=0;
end
else
begin
for(i=0;i<4;i=i+1)
begin
sum[i]=(A[i] + B[i]);
end
end
end
endmodule
Array style ports are only supported in SystemVerilog, if you can use that you should probably stop using the Verilog-95 style port declaration.
Verilog 2001 and above port declaration, with SystemVerilog multi dimension ports
module array(
input clk,
input reset,
input [7:0] A [3:0],
input [7:0] B [3:0],
output reg [7:0] sum[3:0]
);
Verilog vs SystemVerilog files are often identified by file extension so saving as a .sv file will normally switch the compiler over to SystemVerilog.
A combinatorial version on EDA Playground using the free modelsim 10.1d simulator.
Also note that if you are assigning a value to sum in an always block it needs to be a reg not a wire. Since your using SystemVerilog now everything can be declared as logic instead, for more info Checkout this answer.

Defining an array in verilog down to a nonzero constant

I have the following sub-module:
module test
(
input [LENGTH : 1] array;
);
...
endmodule
And I'm calling it from a top module as follows:
...
wire [LENGTH-1 : 0] array_top;
test test_i
(
.array (array_top);
);
...
Assume LENGTH is the same in both modules.
How will array_top map to array, given array_top goes down to zero but array goes to down 1?
Why would anyone define an array down to 1 and not down to 0?
What will happen to array[0]?
Thanks,
Your questions can be answered with a small testbench:
module tb;
reg [3:0] atop;
initial begin
$monitor("array_top=%b, array=%b", array_top, test_i.array);
#1 atop = 4'b0000;
#1 atop = 4'b0001;
#1 atop = 4'b0010;
#1 atop = 4'b0100;
end
wire [3:0] array_top = atop;
test test_i (.array (array_top));
endmodule
module test (input [4:1] array);
endmodule
Output:
array_top=xxxx, array=xxxx
array_top=0000, array=0000
array_top=0001, array=0001
array_top=0010, array=0010
array_top=0100, array=0100
From your connection: array[1] = array_top[0], etc.
Sometimes people want to omit connecting a signal's LSB, like an address for a memory, because the LSB has no effect.
There is no array[0] signal.
When connecting ports, Verilog only cares that arrays have the same size (called an equivalent type in SystemVerilog) It does not care about the starting index value, or whether it increases or decreases. It will start by connecting the right range (LSB) of each signal. In your case array_top[0] connects to array[1]. If the sizes do not match you may get an error or warning, depending on the tool and its settings. Then the connection will either be padded or truncated after hitting the left range (MSB).

Implementing a closed loop in verilog

I'm trying to implement a loop without using loop instructions in verilog so i made a counter module and the simulation went perfectly but when i tried to implement it on the FPGA i got a lot of errors in the mapping , like this one
ERROR:MapLib:979 - LUT4 symbol
"Inst_Count/Mcompar_GND_1105_o_xcount[7]_LessThan_25_o_lut<0>" (output
signal=Inst_Count/Mcompar_GND_1105_o_xcount[7]_LessThan_25_o_lut<0>) has
input signal "Inst_Count/Madd_x[9]_GND_1105_o_add_0_OUT_cy<0>" which will be
trimmed. See Section 5 of the Map Report File for details about why the input
signal will become undriven.
These errors only occurred when i replaced this module with the loop instruction module so does anyone no what's the problem with this one ?
Thanks for giving this your time :)
module average( input rst , output reg [7:0]
reg [7:0] count;
reg [7:0] prv_count;
reg clk;
initial
begin
count = 8'd0;
end
always # (posedge rst)
begin
clk = 1'b0;
end
always # (clk)
begin
prv_count = count ;
count = prv_count + 1'b1;
end
always # (count)
begin
if (count == 8'd255)
G_count= count;
else
begin
clk = ~clk;
G_count= count;
end
end
endmodule
Oh, this is just plain wrong. I don't really think anybody can help here without giving you a lecture on Verilog, but... some things that are noticeable right away are:
You have an obvious syntax error in your module parameter list where you do not close it (i.e. ) went missing).
Clock should be an input to your module. Even if you depend on reset input only and use a register as a "clock", it won't work (logically and you have combinatorial loop that must be broken or else...).
Do not use initial block in the code that should be synthesizable.
prv_count is useless.
No need to manually take care of the overflow (check for 255? 8'd255 is exactly 8'b11111111 and it resets to 0 if you add 1'b1, etc).
And tons of other things, which raise the obvious question — have you tried reading some books on Verilog, preferably those covering synthesizable part of the language? :) Anyhow, what you are trying to do (as far as I can understand) would probably look something like this:
module average(input clk, input rst, output reg [7:0] overflow_count);
reg [7:0] count;
always #(posedge clk or negedge rst) begin
if (~rst) begin
count <= 8'b0;
overflow_count <= 8'b0;
end else begin
count <= (count + 1'b1);
if (count == 8'b0)
overflow_count <= (overflow_count + 1'b1);
end
end
endmodule
Hope it helps and really suggest you take a look at some good books on HDL.

Way to initialize synthesizable 2D array with constant values in Verilog

in VHDL, I can easily do this:
constant cmdbytes : bytearray(0 to Total) := (x"05", x"00", x...};
I want synthesizable constants so that when the FPGA starts, this array has the data I supplied. These registers are wired to VCC or ground to represent 1 or 0. I can then use them to generate a waveform. Also I would like to have 2D byte array which is 3D in verilog world.
If you're just using the array to pull out one value at a time, how about using a case statement? Granted, it's a long-winded way of doing it, but you could always write a script to write the RTL for you.
reg [7:0] value;
reg [7:0] i;
always #(posedge clk or negedge rst_n) begin
if(!rst_n)
i <= 8'd0;
else
i <= i + 1;
end
always #(*) begin
case(i)
8'h00: value = 8'd0;
8'h01: value = 8'd34;
...
endcase
endcase
Another way is to use an initial statement. As far as I'm aware, FPGA synthesis tools will allow you to set initial values for arrays in the following manner. Again, a script to write this may be the way to go.
reg [0:35][7:0] my_array;
initial begin
my_array[0] = 8'd45;
my_array[1] = 8'd26;
...
end
And if your FGPA synthesis tools support some SystemVerilog, you'll be able to initialise the array like so:
reg [0:34][7:0] my_array = '{ 8'd90, 8'd34, ... }; // note the '{
module test (
input [7:0] p1_sa, // i
input [7:0] p1_sb, // i
output [7:0] p3, // o
output [7:0] p3b // o
);
logic [7:0] array2d [7:0] = {99,124,119,123,242,107,111,197};
assign p3 = array2d[p1_sa];
assign p3b = array2d[p1_sb];
endmodule
I tried the above system verilog code and it is working fine in modelsim and Vivado.
An alternative to the case statement approach is to use a function to access values.
Example for an "array" of size 4 containing 8 bit constants:
function [7:0] cmdbytes;
input [1:0] index;
reg [7:0] t[0:3];
begin
{
t[0],t[1],t[2],t[3]
} = {
8'h05, 8'h00, 8'h5b, 8'h45
};
cmdbytes = t[index];
end
endfunction
One can access the constants like so:
wire [7:0] value0;
wire [7:0] value1;
wire [7:0] value2;
wire [7:0] value3;
assign value0 = cmdbytes(2'd0);
assign value1 = cmdbytes(2'd1);
assign value2 = cmdbytes(2'd2);
assign value3 = cmdbytes(2'd3);
Verilog 2005 doesn't allow array initialization. Though your FPGA vendor should have a means to generate a ROM.

Resources