120 likes | 360 Views
5. VHDL/Verilog Operators, Arrays and Indexes. Verilog for synthesis: What operators can we use?. Operators can be used in both assign and always statements Logical bitwise operators: &, |, ~, ^, ~^ Operation applies to each bit of a signal
E N D
Verilog for synthesis: What operators can we use? • Operators can be used in both assign and always statements • Logical bitwise operators: • &, |, ~, ^, ~^ • Operation applies to each bit of a signal • Therefore, apply operators to signals with the SAME WIDTH only • Otherwise, the signal with lower width will be left aligned (some synthesizers might align it to right) • Logical operators: • !, &&, ||, ==, !=, ===, <, >, <=, >=, !== • Used in conditions only. Same as in C, a condition is written always in () • What is === and !== ? • Signals are compared including X and Z • Note: X = don’t care, not undefined! • Applies to simulation only!
Verilog for synthesis: What operators can we use? • Operators can be used in both assign and always statements • Arithmetic operators: • +, -, *, /, %, ** • /, % and ** can be synthesized only if the second operand is 2 or power of 2! • Shift: • <<, >>, <<<, >>> • Shifted in values are 0 • <<< and >>> : shift and maintain sign bit • Unary reduction operators • &, ~&, |, ~|, ~, ^, ~^, • Concatenate and replicate • { }, {{}}
Verilog for synthesis: What operators can we use? • Unary reduction operators • Example: We have a N-bit wide signal named A. The width of A is determined by a parameter called SIGNAL_WIDTH. We have to make a logic AND between all of the bits of A into a signal called A_and. How can we do this? • Solution 1: • … • wire [SIGNAL_WIDTH-1:0] A; • reg A_and; • integer I; • always@ (A) • for (i=0; i<SIGNAL_WIDTH; i = i+1) • A_and <= A_and & A[i]; • Solution 2: • … • wire A_and; • assign A_and = &A; • Note: To test whether any of the bits of A is 1, one can use (|A)
Verilog for synthesis: What operators can we use? • Concatenate and replicate • Concatenate Examples: • 1. {a, b, c} – Concatenate a, b, c into a bus • The width of the resulting bus = width of a + width of b + width of c • Concatenate assignment is also positional! The leftmost bit of the resulting bus is the leftmost bit of a • 2. Assume the following code snippet: • wire [7:0] a; • wire [2:0] b; • wire [4:0] c; • wire [18:0] q; • assign q = {a[5:0], c[3:0], b, a[7:6], 1’b0, 2’b10, b[2]}; • What will be connected to q[17], q[7] and q[2]?
Verilog for synthesis: What operators can we use? • Concatenate and replicate • Replicate Examples: • We have a N-bit wide signal called A and a 1-bit wide signal called EN. The value of N is determined by the parameter SIGNAL_WIDTH. • The EN signal acts as an enable for the N-bit wide output signal A_out such as A_out = A if EN = 1, otherwise all of the bits of A are 0. How can we do this? • Solution 1: • assignA_out = (EN)? A:0; • //works only if A is less than 32-bit wide! Otherwise: N’h00…. • Solution 2: • assignA_out = A & {SIGNAL_WIDTH{EN}}; • 2. wire [19:0] q = {{2{4’hA}}, {4{3’b101}}}. Write down in hexadecimal the value of Q!
Verilog for synthesis: About indexes • One-dimension signals i.e. BUSES: • How to access a part of a bus? Example: • wire | reg [N:n] A; • N and n are POSITIVE INTEGER numbers • A[Upper:Lower] always represents the CONTINUOUS part of the bus having the width of Upper-Lower+1 • Assume Upper >= Lower, then ALWAYS Upper <=N, Lower >=n! • Otherwise the Verilog parser generates an error. Careful when using parameters or variables for indexing! • The synthesizer is able to determine if the index is out of the range [N:n]. Example: • reg [15:0] A; • … • for (i=0; i<=16; i++) A[i] <= … //will generate an error • For selecting non-continuous parts of A, use concatenation operators • A[i] ALWAYS represents a 1-bit wide signal. Obviously, n<=i<=N • A ALWAYS represents the WHOLE range of A, equivalent to A[N:n] • Note: A[N:N] is valid if A was defined in this way! • Example: parameter SIGNAL_WIDTH = 0; • reg [SIGNAL_WIDTH-1:0] A; //A will be defined as A[0:0]
Verilog for synthesis: About indexes • One-dimension signals i.e. BUSES: • How to access a part of a bus? Example: • wire | reg [N:n] A; • What about accessing part of A as A[Lower:Upper]? • Syntactically it is accepted but the synthesizer will generate an error • Use the endianness of signals in the way they wer defined! • RECCOMENDATION: use only one endianness in your code! (usually little) • If cannot avoid both little and big endian signals, in your code, Example: • wire [Lower:Upper] B = A [Upper:Lower];//B[Lower] = A[Upper]… • Two-dimension signals i.e. ARRAYS • Example: • reg [N:n] A [m:M]; //It can be also [M:m] • Used mostly for MEMORY structures: RAM, ROM, FIFO and multi-dimensional shift registers • ALWAYS THE SECOND INDEX COMES FIRST! • A[ i ], m<= i <=M ALWAYS represents a N-n+1-width signal i.e the i-th location of the memory or shift register
Verilog for synthesis: About indexes • Two-dimension signals i.e. ARRAYS • Example: • reg [N:n] A [m:M]; //It can be also [M:m] • A[ i ], m<=i<=M ALWAYS represents a N-n+1-width signal i.e the i-th location of the memory or shift register, equivalent to A [ i ] [N:n] • A[ i ][ j ], m<= i <=M, n <= i <= N ALWAYS represents bit j of location i • A[ i ][Upper:Lower] ALWAYS represents a part selector of the bus from location i • A [L1:U1] [U2:L2] is syntactically valid, but the synthesizer will generate an error • For example: • reg [7:0] Mem [0:255]; • … • always @ .. begin • Mem <= 0; //NOT ALLOWED. Mem is an array of 256X8! Not 32 bits • //and not even 2048 bits! • Mem [0:3] <= {32{1’b0}};//Also not allowed • Mem [3] <= 8’hFF;//Allowed • Mem [255] [7:4] <= 4’h8;//Allowed
Verilog for synthesis: About indexes • Multi-Dimension signals? • Example: • reg [N:n] A [m:M] [p:P]; //It can be also [m:M], [P:p] and so on • It will be visible as a three-dimensional memory • ALWAYS, THE SECOND INDEX COMES FIRST! • XST solves the three-dimensional array as a two-dimensional array of • (P-p+1) * (N-n+1) X (M-m+1) • The third index i.e. [p:P] represents a multiplier for the first index i.e. [N:n] • Therefore A[ i ] [ j ], m<= i <=M, p <= j <= P represents a N-n+1-width signal i.e the i-th location, bits [ (( j+1 ) * N) + j : (( j+1 ) * N ) + j – (N-n) ] of the memory, or shift register, equivalent to A [ i ] [ j ] [N:n] • A[ i ][ j ][ k ], m<= i <=M, p <= i <= P, n <= k <=N represents bit j*k of location i • A[ i ][ j ][Upper:Lower] represents a part selector [ (j * Upper: j * Lower] of the bus from location i • A [L1:U1] [U2:L2] is not accepted by the synthesizer, it will generate an error • Example: reg [7:0] Mem [0:255][0:3]; //will generate an array of 256 X 32-bit wide registers
VHDL: About indexes • One-dimension signals i.e. BUSES: • Example: • signal A: std_logic_vector (7 downto 0); • signal B, C: std_logic_vector (0 to 3); • Index can be also negative! • Part selectors: • Valid: • A (5 downto 4); B(0 to 2); A (5 downto 5); C(0 to 3); • Invalid, even syntactically is not accepted to change the endianness or using indexes larger than the range: • A (3 to 7); B(3 downto 0); C(0 downto 0); A(8), A(6 downto -1); • A is equivalent to A(7 downto 0), B to B(0 to 3) and so on • 1-bit value: enclosed in ‘ ‘, multiple-bit values: enclosed in “ “ • Hexadecimal prefix: X • Concatenation operator: &. Examples: • A <= C & B; -- A(7) <= C(0), A(6) <= C(1) and so on • A <= ‘0’ & B &”000”; • A<= X”FF”; • B <= C(0 to 2) & ‘1’;
VHDL: About indexes • Multi-dimension signals i.e. ARRAYS: • First, the type of array has to be defined. Example: • type my_mem2type isarray (0 to 7) ofstd_logic_vector ( 15 downto 0); • type my_mem3type isarray (0 to 3) of my_mem2type; • signal A: my_mem2type; • signal B: my_mem3type; • The first defined index comes first! • Part selectors: similar to Verilog • A(7); A(5) (5 downto 4); B(3) (7) (15); • Invalid: • A (3 to 7); B(2 to 3) etc.