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.
Related
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.
I am using this wire declaration in Verilog:
wire [23:15] myvar;
My code works and I have seen this coding style before, but I am not sure what is actually happening, I can only guess that a wire that is 9 bits wide is getting declared. Is that what is happening? I wanted to read more on this online, but i didn't know what this is called, so apologies for the simplistic question.
Verilog is a Hardware Descriptive Language(HDL). Whatever you write/declare, ultimately turns out to be a form of hardware.
Lets have a look at the image below:
Here, declaring wire [23:15] myvar; or wire [8:0] myvar; declares the same bunch of wires, nine bits wide. Its just the indexing part that differs. No matter you call it as a[0] (when a is wire [8:0] a) or a[15] (when a is wire [23:15] a). The coding part is different according to the ease for programmer, while synthesis part remains the same.
Also, note that in former case, myvar[15] is the least significant bit while latter has myvar[0] as the LSB. We can swap the declarations part, which shall swap the MSB-LSB too.
reg [7:0] reg1; // 8-bit vector with MSB=7 LSB=0
reg [0:7] reg2; // 8-bit vector with MSB=0 LSB=7
// ...
// ...
reg1 = 8'hF0; // reg1[7] = 1 and reg1[0] = 0 ultimately, reg1 = F0
reg2 = 8'hF0; // reg2[7] = 0 and reg2[0] = 1 ultimately, reg2 = F0
Lets take an example:
wire [23:15] myvar;
reg [23:15] reg2;
reg [31:0] reg3;
initial begin
$monitor("myvar = %0h myvar2 = %0h reg3 = %0h",myvar,myvar2,reg3);
reg3 = 32'h5ABC_FEDC;
// This will correctly assign values to reg2, since it is [23:15]
for(int i=16;i<20;i++)
begin
reg2[i] = myvar[i];
$display("1: reg2[%0d] = %0h myvar[%0d] = %0h",i,reg2[i],i,myvar[i]);
end
// While, this will not assign correctly,
// since reg2 does not have [5:0] indexes,neither does myvar
for(int i=0;i<5;i++)
begin
reg2[i] = myvar[i];
$display("2: reg2[%0d] = %0h myvar[%0d] = %0h",i,reg2[i],i,myvar[i]);
end
end
Another alternative is that your reg is [8:0] while wire is [23:0]. Here is all that matters, but just in the coding part. Note that in the first snippet below, values are assigned to reg1[4:0] and in the second snippet, it is in the range reg1[20:15].
reg [8:0] reg1;
wire [23:15] myvar;
// Correct, since LSB of myvar is at index position 15
for(int i=0;i<5;i++)
begin
reg1[i] = myvar[i+15];
$display("3 : reg1[%0d] = %0h myvar[%0d] = %0h",i,reg1[i],i,myvar[i+15]);
end
reg [31:0] reg1;
wire [23:15] myvar;
// reg1[19:15] is assigned here
for(int i=15;i<20;i++)
begin
reg1[i] = myvar[i];
$display("4 : reg1[%0d] = %0h myvar[%0d] = %0h",i,reg1[i],i,myvar[i]);
end
So, in the end, just some slicing differs while driving from the wire, no effect on the actual hardware. More information can be obtained from Verilog Syntax Details link.
You are correct that you are declaring a 9-bit wire. Many designs have different ideas about what the LSB and MSB values should be, which direction the index numbering should go in. It really doesn't matter what use for index values until you start referencing individual bit or slices.
In the following Verilog code snippet for implementing an input buffer for a router, in second line, what is the role of 1<<`BUF_WIDTH? I understand that << is the left shift operator, but what happens by left shifting 1 by `BUF_WIDTH? Or is there some other function of << operator?
`define BUF_WIDTH 3 // BUF_SIZE = 16 -> BUF_WIDTH = 4, no. of bits to be used in pointer
`define BUF_SIZE ( 1<<`BUF_WIDTH )
module fifo13( clk, rst, buf_in, buf_out, wr_en, rd_en, buf_empty, buf_full, fifo_counter );
input rst, clk, wr_en, rd_en;
input [7:0] buf_in; // data input to be pushed to buffer
output[7:0] buf_out;// port to output the data using pop.
output buf_empty, buf_full; // buffer empty and full indication
output[`BUF_WIDTH :0] fifo_counter; // number of data pushed in to buffer
reg[7:0] buf_out;
reg buf_empty, buf_full;
reg[`BUF_WIDTH :0] fifo_counter;
reg[`BUF_WIDTH -1:0] rd_ptr, wr_ptr; // pointer to read and write addresses
reg[7:0] buf_mem[`BUF_SIZE -1 : 0];
.
.
.
The entire code is available on http://electrosofts.com/verilog/fifo.html
You assume correctly that << is the left-shift operator, it has no other special meaning.
Shifting the binary representation of a number to the left is equivalent to multiplying the number by 2. So, by shifting 1 to the left N times, you get 2 to the power of N as a result.
The way this is used in the code sample ensures that the buffer has exactly as many entries (BUF_SIZE) as can be uniquely addressed by a pointer of size BUF_WIDTH.
It is the bit shift operator. Think what it does: it shifts bits left. You have a definition of BUF_WIDTH being 3. Then you take 1, shift it by that many places and you get 8 for BUF_SIZE. With three bits you can have 8 different values.
So this is a way to define these two constants so that you only have to change one value. If they would be two constants, someone might accidentally only change one and not the other and this would cause problems.
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.
i can't understand the two lines at the end of this code
input [15:0] offset ;
output [31:0] pc;
output [31:0] pc_plus_4;
reg [31:0] pc;
wire [31:0] pcinc ;
assign pcinc = pc +4 ;
assign pc_plus_4 = {pc[31],pcinc};
assign branch_aadr = {0,pcinc + {{13{offset[15]}},offset[15:0],2'b00}};
If you are unfamiliar with curly braces {}, they are concatenation operators. You can read about them in the IEEE Std for Verilog (for example, 1800-2009, Section 11.4.12).
assign pc_plus_4 = {pc[31],pcinc};
This concatenates the MSB of pc with all bits of pcinc to assemble the pc_plus_4 signal. However, in this case, since pcinc and pc_plus_4 are both 32 bits wide, pc[31] is ignored. A good linting tool will notify you that the RHS is 33 bits and the LHS is 32 bits, and that the most significant bit will be lost. The line can be more simply coded as:
assign pc_plus_4 = pcinc;
The last line is a compile error for one simulator I'm using. You did not explicitly declare the width of the branch_aadr signal, and the width of the 0 constant is unspecified.
The last line also contains a replication operator, which uses two sets of curly braces.
{13{offset[15]}}
This replicates the bit offset[15] thirteen times. It looks like the author is doing a sign extension on offset before adding it to pcinc. A better way might be to declare offset as signed.
//Three ways to replicate bits
wire [3:0] repeated;
wire value;
//These two assignments have the same effect
assign repeated = {4{value}}; //Replication operator
assign repeated = {value,value,value,value}; //Concatenation operator
//These four taken together have the same effect as the above two
assign repeated[3] = value; //Bit selects
assign repeated[2] = value;
assign repeated[1] = value;
assign repeated[0] = value;