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.
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.
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.
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.
I wrote a 32-bit LFSR based on the taps from [1]. I want to ask if the following description is right for the 32-bit LFSR with the taps 32,22,2 and 1.
module lfsr (
input logic clk_i,
input logic rst_i,
output logic [31:0] rand_o
);
logic[31:0] lfsr_value;
assign rand_o = lfsr_value;
always_ff #(posedge clk_i, negedge rst_i) begin
if(~rst_i) begin
lfsr_value <= '0;
end else begin
lfsr_value[31:1] <= lfsr_value[30:0];
lfsr_value[0] <= ~(lfsr_value[31] ^ lfsr_value[21] ^ lfsr_value[1] ^ lfsr_value[0]);
end
end
endmodule
[1] http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf
Looks Ok. you could also use an XOR, instead of an XNOR, as long as you reset to something else (the XOR version locks up at all 0's, the XNOR at all 1's).
For many apps the pseudo-random output is the single bit you shift out (31 in your case), rather than the entire register. It's also (more?) common to shift right, and put the XOR data in the top bit, and use the bit 0 output as your PR data.
Your code is specifically SystemVerilog, and not Verilog, so I've removed the Verilog tag.
I'm trying to synthesize an Altera circuit using as few logic elements as possible. Also, embedded multipliers do not count against logic elements, so I should be using them. So far the circuit looks correct in terms of functionality. However, the following module uses a large amount of logic elements. It uses 24 logic elements and I'm not sure why since it should be using 8 + a couple of combinational gates for the case block.
I suspect the adder but I'm not 100% sure. If my suspicion is correct however, is it possible to use multipliers as a simple adder?
module alu #(parameter N = 8)
(
output logic [N-1:0] alu_res,
input [N-1:0] a,
input [N-1:0] b,
input [1:0] op,
input clk
);
wire [7:0] dataa, datab;
wire [15:0] result;
// instantiate embedded 8-bit signed multiplier
mult mult8bit (.*);
// assign multiplier operands
assign dataa = a;
assign datab = b;
always_comb
unique case (op)
// LW
2'b00: alu_res = 8'b0;
// ADD
2'b01: alu_res = a + b;
// MUL
2'b10: alu_res = result[2*N-2:N-1]; // a is a fraction
// MOV
2'b11: alu_res = a;
endcase
endmodule
Your case statement will generate a 4 input mux with op as the select which uses a minimum of 2 logic cells. However since your assigning an 8-bit variable in the case block you will require 2 logic elements for each bit of the output. Therefore total logic elements is 8*2 for the large mux and 8 for the adder giving you 24 as the total.
I'm doing this project too so I won't give too much away about how to optimise this. However what I will tell you is that both the mux's and the adder can be implemented using multipliers, 8 at most. With that said I don't think this architecture is optimal for a multiplier implementation.