SystemVerilog has unsized single-bit value literals such as '0 and '1.
According to the IEEE Std 1800, in 5.7.1 Integer literal constants,
I see "an unsized single-bit value ... shall be treated as unsigned."
However, Example 5 in the section, I also see:
logic [15:0] a, b, c, d;
a = '0; // sets all 16 bits to 0
b = '1; // sets all 16 bits to 1
...
Doesn't it mean '1 is treated as signed?
In fact, I get the following result with '1 and 1'b1 by Quartus Prime and ModelSim-Altera.
logic [3:0] a, b;
assign a = '1; // => yields 4'b1111
assign b = 1'b1; // => yields 4'b0001
I think both '1 and 1'b1 themselves are unsigned. Why do I see such difference?
I missed the description "All bits of the unsized value shall be set to the value of the specified bit." in the same section. In multiple-bit context, '1 is treated as a sequence of all 1, but still is treated as unsigned.
So, in 4-bit context, '1 is unsigned 4'b1111 and 1'b1 is unsigned 4'b0001.
Sorry for bothering.
Related
What are the +: and -: Verilog/SystemVerilog operators? When and how do you use them? For example:
logic [15:0] down_vect;
logic [0:15] up_vect;
down_vect[lsb_base_expr +: width_expr]
up_vect [msb_base_expr +: width_expr]
down_vect[msb_base_expr -: width_expr]
up_vect [lsb_base_expr -: width_expr]
That particular syntax is called an indexed part select. It's very useful when you need to select a fixed number of bits from a variable offset within a multi-bit register.
Here's an example of the syntax:
reg [31:0] dword;
reg [7:0] byte0;
reg [7:0] byte1;
reg [7:0] byte2;
reg [7:0] byte3;
assign byte0 = dword[0 +: 8]; // Same as dword[7:0]
assign byte1 = dword[8 +: 8]; // Same as dword[15:8]
assign byte2 = dword[16 +: 8]; // Same as dword[23:16]
assign byte3 = dword[24 +: 8]; // Same as dword[31:24]
The biggest advantage with this syntax is that you can use a variable for the index. Normal part selects in Verilog require constants. So attempting the above with something like dword[i+7:i] is not allowed.
So if you want to select a particular byte using a variable select, you can use the indexed part select.
Example using variable:
reg [31:0] dword;
reg [7:0] byte;
reg [1:0] i;
// This is illegal due to the variable i, even though the width is always 8 bits
assign byte = dword[(i*8)+7 : i*8]; // ** Not allowed!
// Use the indexed part select
assign byte = dword[i*8 +: 8];
The purpose of this operator is when you need to access a slice of a bus, both MSB position and LSB positions are variables, but the width of the slice is a constant value, as in the example below:
bit[7:0] bus_in = 8'hAA;
int lsb = 3;
int msb = lsb+3; // Setting msb=6, for out bus of 4 bits
bit[3:0] bus_out_bad = bus_in[msb:lsb]; // ILLEGAL - both boundaries are variables
bit[3:0] bus_out_ok = bus_in[lsb+:3]; // Good - only one variable
5.2.1 Vector bit-select and part-select addressing
Bit-selects extract a particular bit from a vector net, vector reg, integer, or time variable, or parameter. The bit can be addressed using an expression. If the bit-select is out of the address bounds or the bit-select is x or z , then the value returned by the reference shall be x . A bit-select or part-select of a scalar, or of a variable orparameter of type real or realtime, shall be illegal.
Several contiguous bits in a vector net, vector reg, integer, or time variable, or parameter can be addressed and are known as part-selects. There are two types of part-selects, a constant part-select and an indexed part-select. A constant part-select of a vector reg or net is given with the following syntax:
vect[msb_expr:lsb_expr]
Both msb_expr and lsb_expr shall be constant integer expressions. The first expression has to address a more significant bit than the second expression.
An indexed part-select of a vector net, vector reg, integer, or time variable, or parameter is given with the following syntax:
reg [15:0] big_vect;
reg [0:15] little_vect;
big_vect[lsb_base_expr +: width_expr]
little_vect[msb_base_expr +: width_expr]
big_vect[msb_base_expr -: width_expr]
little_vect[lsb_base_expr -: width_expr]
The msb_base_expr and lsb_base_expr shall be integer expressions, and the width_expr shall be a positive constant integer expression. The lsb_base_expr and msb_base_expr can vary at run time. The first two examples select bits starting at the base and ascending the bit range. The number of bits selected is equal to the width expression. The second two examples select bits starting at the base and descending the bit range.
A part-select of any type that addresses a range of bits that are completely out of the address bounds of the net, reg, integer, time variable, or parameter or a part-select that is x or z shall yield the value x when read and shall have no effect on the data stored when written. Part-selects that are partially out of range shall, when read, return x for the bits that are out of range and shall, when written, only affect the bits that are in range.
For example:
reg [31: 0] big_vect;
reg [0 :31] little_vect;
reg [63: 0] dword;
integer sel;
big_vect[ 0 +: 8] // == big_vect[ 7 : 0]
big_vect[15 -: 8] // == big_vect[15 : 8]
little_vect[ 0 +: 8] // == little_vect[0 : 7]
little_vect[15 -: 8] // == little_vect[8 :15]
dword[8sel +: 8] // variable part-select with fixed width*
Example 1—The following example specifies the single bit of acc vector that is addressed by the operand
index :
acc[index]
The actual bit that is accessed by an address is, in part, determined by the declaration of acc . For instance, each of the declarations of acc shown in the next example causes a particular value of index to access a different bit:
reg [15:0] acc;
reg [2:17] acc
Example 2—The next example and the bullet items that follow it illustrate the principles of bit addressing. The code declares an 8-bit reg called vect and initializes it to a value of 4. The list describes how the separate bits of that vector can be addressed.
reg [7:0] vect;
vect = 4; // fills vect with the pattern 00000100
// msb is bit 7, lsb is bit 0
— If the value of addr is 2, then vect[addr] returns 1.
— If the value of addr is out of bounds, then vect[addr] returns x.
— If addr is 0, 1, or 3 through 7, vect[addr] returns 0.
— vect[3:0] returns the bits 0100.
— vect[5:1] returns the bits 00010.
— vect[ expression that returns x ] returns x.
— vect[ expression that returns z ] returns x.
— If any bit of addr is x or z , then the value of addr is x.
NOTE 1—Part-select indices that evaluate to x or z may be flagged as a compile time error.
NOTE 2—Bit-select or part-select indices that are outside of the declared range may be flagged as a compile time error.
How "inside" sub-expressions bit lengths are supposed to be computed in System Verilog?
It appears that the type of an expression depends on whether an operand is a numeric literal or a variable.
The following System Verilog program:
`define M( x ) $display( `"x -- %b`", x )
module top ();
bit [3:0] a, b;
initial begin
// (a+b) could be evaluated either to 0 or 16, depending on the bit length of the expression.
a = 15;
b = 1;
`M(4'd1 inside { [(a+b):17] } ); // 0
`M(4'd1);
`M( b inside { [(a+b):17] } ); // 1
`M( b);
end
endmodule
outputs:
Chronologic VCS simulator copyright 1991-2019
Contains Synopsys proprietary information.
Compiler version P-2019.06-SP1-1_Full64; Runtime version P-2019.06-SP1-1_Full64; May 8 20:27 2020
4'd1 inside { [(a+b):17] } -- 0
4'd1 -- 0001
b inside { [(a+b):17] } -- 1
b -- 0001
V C S S i m u l a t i o n R e p o r t
Time: 0
CPU Time: 0.250 seconds; Data structure size: 0.0Mb
Fri May 8 20:27:08 2020
PS: Verific interprets the standard differently from Synopsys.
It's definitely a tool bug that it produces different results for two different operands of the same value and width.
However, the correct answer is slightly ambiguous because the inside operator was left out of Table 11-21—Bit lengths resulting from self-determined expressions in the IEEE 1800-2017 LRM. This is a reported issue for the LRM, and the consensus is that is should behave the same as the case inside statement in that all operands get sized to the largest size operand before doing any comparisons. In this example, the literal 17 is 32-bits wide and has the largest width. So the result of the inside operator should be 1'b0.
I have a specific question and a request for more general guidance.
My question is what is the cleanest way to multiply a signed number by an unsigned number in SystemVerilog?
Below is a little test code that illustrates the problem. 'a' is the unsigned number. 'b' is the signed number. In order to produce a correct signed result SystemVerilog seems to require that both operands of the multiplication be signed. To make that work here I had to add an extra '0' to the front of the unsigned number to make it a valid signed number. I'm thinking there must be a cleaner way.
More generally, I am just getting started doing fixed point math in SystemVerilog. In VHDL there is very concrete syntax and even a standard package to support signed and unsigned fixed point math, with rounding, etc. Is there something like that in the SystemVerilog world?
Thanks,
module testbench ();
localparam int Wa = 8;
localparam int Wb = 8;
logic [Wa-1:0] a; // unsigned
logic [Wa:0] a_signed; // signed word with extra bit to hold unsigned number.
logic [Wb-1:0] b; // signed
logic [Wa+Wb-1:0] c; // result
localparam clk_period = 10;
assign a_signed = {1'b0, a};
assign c = $signed(a_signed)*$signed(b);
initial begin
a = +5;
b = +10;
#(clk_period*1);
$display("Hex: a=%x,b=%x, c=%x; Dec: a=%d, b=%d, c=%d", a, b, c, a, $signed(b), $signed(c));
a = +5;
b = -10;
#(clk_period*1);
$display("Hex: a=%x,b=%x, c=%x; Dec: a=%d, b=%d, c=%d", a, b, c, a, $signed(b), $signed(c));
a = +255;
b = +10;
#(clk_period*1);
$display("Hex: a=%x,b=%x, c=%x; Dec: a=%d, b=%d, c=%d", a, b, c, a, $signed(b), $signed(c));
a = +255;
b = -10;
#(clk_period*1);
$display("Hex: a=%x,b=%x, c=%x; Dec: a=%d, b=%d, c=%d", a, b, c, a, $signed(b), $signed(c));
$stop;
end
endmodule
system verilog rules say
If any operand is unsigned, the result is unsigned, regardless of the operator
Propagate the type and size of the expression (or self-determined subexpression) back down to the context-determined operands of the expression
When propagation reaches a simple operand as defined in 11.5, then that operand shall be converted to the propagated type and size.
So, in other words, when you multily signed and unsigned numbers, the expression type will be determined as unsigned. This will be propagated back to operands and all signed will be treated as unsigned as well.
so, your result will be identical to the one of multiplying two unsigned numbers. So, the cleanest way, if you need signed result, is to convert all operands to signed number.
You will also need an extra bit in your operands to have a place for the sign bit. Otherwise 255 will be treated as -1 in 8-bit sign conversion.
I've looked thru the LRM, haven't found a clear answer... How is the following interpreted:
logic [7:0] data;
logic sig_out;
assign sig_out = (data == '1);
Will it be interpreted as:
assign sig_out = (data == 8'hFF);
Do sim & synthesis interpret this differently?
thx
PB&J
5.7.1 Integer literal constants of the 1800-2012 LRM explains that '1 has the width of the value based on the context where it is used. When using it in a self-determined context, it has a width of 1 bit. Table 11-21 explains that the operands of relational operators in a context sized to the largest operand
So '1 in your context is 8'hff.
It works as 8'hff.
Consider the below code, with it's output -
module top();
logic [7:0] data;
logic sig_out;
assign sig_out = (data == '1);
initial
begin
data = 'h01;
#1 $display("sig_out - %0h", sig_out);
data = 'h0f;
#1 $display("sig_out - %0h", sig_out);
data = 'hff;
#1 $display("sig_out - %0h", sig_out);
end
endmodule
Output -
sig_out - 0
sig_out - 0
sig_out - 1
'1 means all ones, so if data is 8 bit wide then data = 8'hff.
If you meant to write the value 8'h01 in a context determined length way, use 'b1 which will be interpreted in this case as 8'h01.
I found the following code snippet in verilog code for AES.
function [7:0] xtime;
input [7:0] b; xtime={b[6:0],1'b0}^(8'h1b&{8{b[7]}});
endfunction
Please explain what does this do. The more elaborate explanation, the better.
b is a 8 bit input.
b[6:0],1'b0 last 7 bits left shifted, and padded with 0
^ xor
8'h1b 8 bits hex 1b anded with the sign bit.
Explained in one line: If msb is set xor with 0x1b otherwise just *2
A quick search of xtime and AES leads me to this c implementation’s comment:
// xtime is a macro that finds the product of {02} and the argument to
// xtime modulo {1b}
#define xtime(x) ((x<<1) ^ (((x>>7) & 1) * 0x11b))
looks like it maybe is doing about the same.
Lets clean up the code and breakdown some of the assignments:
function [7:0] xtime;
input [7:0] b;
reg [7:0] temp1;
reg [7:0] temp2;
begin
temp1 = {b[6:0],1'b0};
temp2 = ( 8'h1b & {8{b[7]}} );
xtime = temp1 ^ temp2;
end
endfunction
Function called xtime outputs the variable xtime 8 bits wide. Has 8 bit wide input called b.
temp1 left shifts input b, padding LSB (Least Significant Bit) with 0 and throwing away MSB (Most Significant Bit).
temp2 bitwise ANDs 8'h1B (8'b0001_1011) with the MSB of input b.
b[7] selects bit 7 of b.
{8{value}} is the replication operator.
{8{1'b1}} => 8'b1111_1111
{4{2'b10}} => 8'b1010_1010
xtime performs the bitwise XOR of temp1 and temp2.