Is this code structure going in the right direction? - verilog

I am trying to utilize a 7 segment display. I have written a module which I want to take 4 inputs and change the hex output. There seems to be an issue with unpacked/packed arrays and I really don't know what on earth I'm doing. Any help much appreciated.
module hexDisplay(hex, c0, c1, c2, c3);
input c0;
input c1;
input c2;
input c3;
output hex[6:0];
reg out[6:0];
always#(*)
begin
case({c3, c2, c1, c0})
4'b0000:out [5:0] = 1;
// 0001-1111 go here
//...
default:out [6:0] = 0;
endcase
assign hex = out;
end
endmodule
Errors:
Error (10773): Verilog HDL error at lab2pre.v(55): declaring module ports or function arguments with unpacked array types requires SystemVerilog extensions
Error (10133): Verilog HDL Expression error at lab2pre.v(61): illegal part select of unpacked array "out"
Error (10133): Verilog HDL Expression error at lab2pre.v(62): illegal part select of unpacked array "out"
Error (10048): Verilog HDL error at lab2pre.v(64): values cannot be assigned directly to all or part of array "hex" - assignments must be made to individual elements only
Error (10137): Verilog HDL Procedural Assignment error at lab2pre.v(64): object "hex" on left-hand side of assignment must have a variable data type
Error (10044): Verilog HDL error at lab2pre.v(64): expression cannot reference entire array "out"
Error: Quartus II 64-Bit Analysis & Synthesis was unsuccessful. 6 errors, 1 warning
Error: Peak virtual memory: 959 megabytes
Error: Processing ended: Tue Feb 2 17:33:35 2016
Error: Elapsed time: 00:00:15
Error: Total CPU time (on all processors): 00:00:46
Error (293001): Quartus II Full Compilation was unsuccessful. 8 errors, 1 warning

2 Errors :
You need to have "packed" array rather than an "unpacked" array for
"out" & "hex" nets.
SystemVerilog supports both packed arrays and unpacked arrays of data.
The term packed array is used to refer to the dimensions declared
before the data identifier name. The term unpacked array is used to
refer to the dimensions declared after the data identifier name.
bit [7:0] c1; // packed array of scalar bit types
real u [7:0]; // unpacked array of real types
A packed array is a mechanism for subdividing a vector into subfields,
which can be conveniently accessed as array elements. Consequently, a
packed array is guaranteed to be represented as a contiguous set of
bits.
An unpacked array may or may not be so represented. A packed array
differs from an unpacked array in that, when a packed array appears as
a primary, it is treated as a single vector.
So in the code, you require, out & hex to be used as a continuous
bit vector, then it should be packed array, instead of unpacked
array.
Refer to topic 7.4 of the Systemverilog LRM.
assign statement to hex, cannot be with in always block. Because an
assign statement is used for modeling only combinational logic and it
is executed continuously. So the assign statement is called
'continuous assignment statement' as there is no sensitive list.
So it can't be within always block, which is executed as per
sensitivity list.
So your final working code is as below:
module hexDisplay(hex, c0, c1, c2, c3);
input c0;
input c1;
input c2;
input c3;
output [6:0] hex;
reg [6:0] out;
always#(*)
begin
case({c3, c2, c1, c0})
4'b0000:out [5:0] = 1;
// 0001-1111 go here
//...
default:out [6:0] = 0;
endcase
end
assign hex = out;
endmodule

Try something like this. Move the range specifiers ([6:0]) to the left of the signal names, and move the assign outside of the always block.
module hexDisplay(hex, c0, c1, c2, c3);
input c0;
input c1;
input c2;
input c3;
output [6:0] hex;
reg [6:0] out;
always#(*)
begin
case({c3, c2, c1, c0})
4'b0000:out [5:0] = 1;
// 0001-1111 go here
//...
default:out [6:0] = 0;
endcase
end
assign hex = out;
endmodule

whatever variable in always block must be reg , here you assign hex in always which is by default wire so if you assign hex at out side of always u will get compile free code.

Related

System Verilog Illegal assignment: Cannot assign an unpacked type to a packed type

In System Verilog I wrote:
module mult32x32_arith (
input logic clk, // Clock
input logic reset, // Reset
output logic [63:0] product // Miltiplication product
);
logic left_decoder, right_decoder, product_FF[63:0]={64{1'b0}};
always_ff #(posedge clk, posedge reset) begin
if (reset==1'b1)begin
product <= product_FF;
end
else begin
end
end
But, I'm getting errors on this line:
product <= product_FF;
It says:
Error: mult32x32_arith.sv(19): Illegal assignment to type 'reg[63:0]' from type 'reg $[63:0]': Cannot assign an unpacked type to
a packed type.
But, I don't understand what the problem is.
You declared product as packed and product_FF as unpacked. Refer to IEEE Std 1800-2017, section 7.4 Packed and unpacked arrays:
The term packed array is used to refer to the dimensions declared
before the data identifier name. The term unpacked array is used to
refer to the dimensions declared after the data identifier name
You need to declare them as the same data type. For example, to make them both packed, change:
logic left_decoder, right_decoder, product_FF[63:0]={64{1'b0}};
to:
logic left_decoder, right_decoder;
logic [63:0] product_FF = {64{1'b0}};

How do you manipulate input arrays in an always block (verilog)?

I'm very new to verilog and i'm just starting to understand how it works.
I want to manipulate an input to a module mant[22:0], in an always block but I am not sure how to go about it.
module normalize(mant,exp,mant_norm,exp_norm);
input [22:0]mant;
input [7:0]exp;
output [22:0]mant_norm;
output [7:0]exp_norm;
reg mantreg[22:0];
reg count=0;
always#(mant or exp)
begin
mantreg<=mant; //this gives an error
if(mant[22]==0)
begin
mant<={mant[21:0],1'b0};//this also gives an error
count<=count+1;
end
end
endmodule
so i have to shift the mant register if the bit22 is zero and count the number of shifts. I am so confused about when to use reg and when to use wire and how to do the manipulation. please help let me know how to go about it.
As you can see in your code you are assigning vector value (mant) to array of 23(mantreg). Instead you should declare mantreg as reg [22:0] mantreg (which is vector of 23 bit).
Wire type variable can not be assigned procedurally. They are used only in continues assignment. Other way around reg varible can only be procedural assigned.
For that try to read out LRM of Verilog .

verilog multi-dimensional reg error

This statement:
reg [7:0] register_file [3:0] = 0;
Produces this error:
Error (10673): SystemVerilog error at simpleprocessor.v(27): assignments to unpacked arrays must be aggregate expressions
First of all I am using Verilog, not SystemVerilog, so why is it giving me a SystemVerilog error?
Second of all, what is the cause of this error, and how can I fix it? I am using it in my desgin of a very rudementary processor to represent the internal working registers as a multidemmnsional array of memory.
It would be such that my registers are accessible directly from the instructions. For example this line:
register_file[instruction[5:4]] <= register_file[instruction[3:2]] + register_file[instruction[1:0]];
But it's not working. Any ideas?
From the SystemVerilog LRM:
The term packed array is used to refer to the dimensions declared before the data identifier name. The term unpacked array is used to refer to the dimensions declared after the data identifier name.
bit [7:0] c1; // packed array of scalar bit types
real u [7:0]; // unpacked array of real types
You have declared an unpacked array, therefore you cannot assign it to a value, hence the error message. With an unpacked array you have to use an aggregate expression to assign the entire array:
logic [7:0] register_file [3:0] = {8'b0, 8'b0, 8'b0, 8'b0};
If you declare a packed array you can then assign as though it was a flat vector:
logic [7:0][3:0] register_file = '0;
You have implied a memory but not specified the location to be set to 0.
You can use an aggregate expressions to define all the values in one line:
reg [7:0] register_file [3:0] = {8'b0, 8'b0, 8'b0, 8'b0};
If it is for an fpga you could also use initial:
reg [7:0] register_file [3:0];
initial begin
for(int i=0; i<4; i++) begin
register_file[i] = 8'b0
end
end
In this instant the loop can be statically unrolled, and therefore is synthesisable.
NB Verilog is depreciated. The Verilog standard has been merged with SystemVerilog in 2009, SystemVerilog 2012 being the latest version.

Verilog: Order of reg

Simple question
If I need to use 4 8-bit numbers, I would declare the following reg.
reg [7:0] numbers [3:0]
I'm quite confused about the difference between the first and second declaration ([7:0] and [3:0]). In what order should they come? Does first one stay for the size of a number while the second is for the number of numbers or vice versa? And is [7:0] or [0:7] give the right order?
Thanks in advance.
EDIT:
Ordinary arrays of numbers look like this, for example
0000
0110
0001
There are three 4-bit numbers (0000, 0110, 0001). We can access them by using array indices. So, accessing the first digit of the second number is done by something like this
a[0][1]
assuming that this array is stored in a variable a.
Returning to Verilog, how would accessing elements change if I would swap values in reg or declare them in reverse order ([0:7]), for example?
reg[7:0] is an 8-bit "register", or variable
reg[7:0] numbers[3:0] is a 1-D array with 4 elements, named
numbers, each of which is an 8-bit register
An element of numbers is accessed as numbers[index]
numbers[i][j] is a bit-select of numbers[i]. It accesses bit
j in the ith element of numbers
As toolic says, it's more conventional for array indices to be
numbered [lsb:msb], but there's no good reason for this.
When assigning two objects, bits are copied left-to-right, as for VHDL.
Verilog has (very) poor checking of bit and part selects and array indexes. See the code below.
module top;
initial
test;
task test;
reg[3:0] a[0:1];
reg[0:3] b[0:1];
reg[2:5] c[0:1];
begin
a[0] = 4'b1101;
a[1] = 4'b0110;
a[2] = 4'b0001; // error, but not caught by Verilog
$display("a[2] is %d", a[2]); // modelsim produces no warning, prints 'a[2] is x'
$display("a[0][4] is %b", a[0][4]); // modelsim warns, and prints 'a[0][4] is x'
$display( // produces '1.1.0.1'
"a[0][3:0] is %b.%b.%b.%b", a[0][3], a[0][2], a[0][1], a[0][0]);
b[0] = a[0];
$display("b[0] is %d", b[0]); // produces '13'
$display( // produces '1.1.0.1'
"b[0][0:3] is %b.%b.%b.%b", b[0][0], b[0][1], b[0][2], b[0][3]);
c[0] = a[0];
$display("c[0] is %d", c[0]); // produces '13'
$display( // produces '1.1.0.1'
"c[0][2:5] is %b.%b.%b.%b", c[0][2], c[0][3], c[0][4], c[0][5]);
end
endtask
endmodule
Yes, that syntax can be used to declare 4 8-bit numbers, however it is more conventional for 0 to be left of the colon for the number of words:
reg [7:0] numbers [0:3]

Converting a wire value in Verilog for further processing

I'm new to Verilog.
I have written code to convert a wire value to an integer:
wire [31:0] w1;
integer k;
always # (w1) k = w1;
Source: converting a wire value to an integer in verilog
Now, for the next part I get an ERROR!
wire [63:0] w2; // Suppose it contains some value
wire [63:0] w3;
assign w3[k-1:0] = w2[k-1:0]; // ERROR in this line
ERROR : k is not a constant.
How do I solve this issue?
Verilog requires that part selects (code like [msb:lsb] to select part of a vector) be constant. To access a variable-sized group of bits requires something more complicated. Here is one way to do it:
wire [63:0] src;
wire [6:0] k;
wire [127:0] mask = { { 64 { 1'b0 } }, { 64 { 1'b1 } } } << k;
wire [63:0] dest;
assign dest = mask[127:64] & src;
The technique here is to construct a vector of 64 zeros followed by 64 ones, shift that vector by a variable amount, and then use a portion of the vector as a qualifying mask to control which bits are transferred from src to dest.
A related concept which does not help in your example but which is worth being aware of: Verilog-2001 introduced the "indexed part-select". An indexed part select specifies a base index and a width. The width is required to be constant but the base index does not need to be constant. The syntax for an indexed part select is vec[base+:width] or vec[base-:width].
The part select operators in Verilog 2001 could be useful for what you want to achieve.
Basically verilog allows for the starting index to be variable but needs the width of the assignment to be constant. The "+:" operator indicates counting upwards from the index value and vice-versa for "-:".
You can do something like,
assign w3[k-1 -: 8 ] = w2[k-1 -: 8]; // Where 8 bits is copied downwards
Search for "+:" in the below document.
http://www.sutherland-hdl.com/papers/2001-Wescon-tutorial_using_Verilog-2001_part1.pdf
Word of caution, generally variable part selects is considered as bad verilog.

Resources