Signed multiplication result trim - vhdl

What I have
I've two signed signals, 10b length one of them and 2b the other one.
signal R_S_R : signed(9 downto 0);
signal prbs_sup_u : signed(1 downto 0);
Then I want to multiply them like:
R_S_E <= R_S_R * prbs_sup_u;
Storing the result into another 10b signal.
Why 10b again
Because prbs_sup_u is 2b, and it'll only have [-1, 1] values (only those two). So, although result of multiplication is 12b, I think (only if I'm not mistaken) I should be able to store the posible results of the operation in another 10b signal.
So your question is...
After doing the multiplication, I should be able to dispose of two of the bits from the 12b result.
However, which ones? Since it's a signed signal, I don't know which one are disposable. Of course not the first one, since it's the sign, but after that...

Simply use the resize operation to truncate unrequired MSBs (magnitude) like:
R_S_E <= resize(R_S_R * prbs_sup_u, R_S_E'length);
You can find the documentation in numeric_std.resize:
-- Id: R.1
function RESIZE (ARG: SIGNED; NEW_SIZE: NATURAL) return SIGNED;
-- Result subtype: SIGNED(NEW_SIZE-1 downto 0)
-- Result: Resizes the SIGNED vector ARG to the specified size.
-- To create a larger vector, the new [leftmost] bit positions
-- are filled with the sign bit (ARG'LEFT). When truncating,
-- the sign bit is retained along with the rightmost part.
If the prbs_sup_u can only have value 1 or -1, then you can also consider:
if prbs_sup_u = 1 then
R_S_E <= R_S_R;
else -- prbs_sup_u = -1
R_S_E <= - R_S_R;
end if;
The operation may then be more obvious, and the circuit will be smaller, since the implementation does not have to include handling of the unused 0 and -2 values.

Related

How to determine direction of a vector in VHDL (downto vs to)?

I need to write a function that will shift data into an input vector. The input could be of type signed or unsigned. In order to make the function robust, I need to know the direction of the input vector i.e range declared using downto vs to. This information will be used to determine what index has the least significant bit.
How do I find out how the range has been declared and choose the correct least significant and most significant bit based on that information?
Array types have the default attributes 'ascending and 'descending which are both functions that return true/false depending on whether the range is actually to (ascending) or downto (descending). Hence, you will likely need to have the following coding style if you explicitly need to investigate the direction:
if p'ascending then
-- do code for to direction
else
-- do code for downto direction
end if;
Alternatively, you can use an alias to "normalise" the direction inside the function, which means an if/else is not needed depending on direction, as you know the direction inside the function:
function do_something( p : bit_vector ) return bit_vector is
alias p_a : bit_vector(p'length-1 downto 0) is p; -- normalise p
variable r : p_a'subtype;
begin
-- use p_a as a downto vector
return r;
end function;

VHDL Fixed_pkg Getting bound check failure when adding 2 ufixed values

I am attempting to used the ufixed datatype and add 2 ufixed values together, I have calculated I should have enough bits to store the result and the output should be able to be stored in the signal, but when I attempt to perform it I get a bound check failure. Can someone tell me why I am getting this?
The important parts of the code are:
-- definition of parameters used in the failing calculation
input : in ufixed(0 downto -15); -- Q1.15
constant VectorLength : integer := 3;
type vector_ufixed is array(0 to VectorLength-1) of ufixed(1 downto -14);
constant InnerProductArray : vector_ufixed := (to_ufixed(1.2,1,-14), to_ufixed(1.0,1,-14), to_ufixed(0.2,1,-14));
signal InnerProductResult : ufixed(4 downto -29); -- Q5.29
signal counter : integer := 0;
write(l, real'image(to_real(InnerProductResult)));
write(l, string'(", "));
write(l, real'image(to_real(InnerProductResult + input*InnerProductArray(counter))));
writeline(output, l);
InnerProductResult <= InnerProductResult +
input*InnerProductArray(counter);
When I simulate this with ghdl I get the following result:
0.0, 6.00006103515625e-1
ghdl:error: bound check failure at InnerProduct.vhd:55
from: process work.innerproduct(innerproductarchitecture).P0 at InnerProduct.vhd:55
ghdl:error: simulation failed
line 55 in this case is the line
InnerProductResult <= InnerProductResult + input*InnerProductArray(counter);
input takes the value 0.5, as can be observed from the resulting value of 6.00006103515625e-1 when input is multiplied by 1.2.
The value 6.00006103515625e^-1*2^29 is 322125824 as well which is an integer less than 2^34 so it should fit fine, I don't understand why this might be?
When performing a arithmetic operations such as this, addition and multiplication in this case, it is necessary to resize the result of the operation to fit into the location it is being stored. In this case we add a 34 bit number to 2 16 bit numbers and so we need to resize the result to be 34 bits wide in order to fit precisely into the storage location i.e. InnerProductResult.
The syntax for resize in fixed_pkg appears to differ from that used in numeric_std for signed and unsigned numbers. The following syntax is nessesary to use for operations done with fixed_pkg, this was found in http://www.klabs.org/mapld05/presento/189_lewis_p.pdf:
InnerProductResult <= resize(
arg => InnerProductResult + input*InnerProductArray(counter),
size_res => InnerProductResult
);

Unsigned multiplication creates a x2 sized array

I'm trying to create a Shift Register, by using multiplication (*2) to shift bits one position.
However, when I do it, ISE (Xilinx IDE) says me that this expression has x2 the number of elements the original signal has.
To be specific, I've:
if rising_edge(clk) then
registro <= unsigned(sequence);
registro <= registro * 2;
-- Just adds into the last position the new bit, Sin (signal input)
registro <= registro or (Sin, others => '0');
sequence <= std_logic_vector(registro);
end if;
And before, I've declared:
signal Sin : std_logic;
signal sequence : std_logic_vector(0 to 14) := "100101010000000";
signal registro : unsigned (0 to 14);
So I'm getting the error (at multiplication line):
Expression has 30 elements ; expected 15
So, why does it creates a x2 sized vector, if I've only multiplied *2?
What am I missing? How can I accomplish it?
Thank you in advance
Word width grows because you have used multiplication.
Multiplying 2 16-bit unsigned numbers gives you a 32 bit unsigned, in general.
Now it would be possible to optimise your specific case of multiplication by a constant, 2, and have synthesis do the correct thing. In which case the error message would change to
Expression has 16 elements ; expected 15
but why should the synthesis tool bother?
Use a left shift instead, either using a left (right?) shift operator, or explicit slicing and concatenation, for example:
registro <= registro(1 to registro'length-1) & '0';
Incidentally:
Using ascending bit order range is quite unconventional for arithmetic : all I can say is good luck with that...
you have three assignments to the same signal within the same process; only the last one will take effect. (See Is process in VHDL reentrant? for some information on the semantics of signal assignment)
If you declared "sequence" as unsigned in the first place you'd save a lot of unnecessary conversions and the code inside the process would reduce to a single statement, something like
sequence <= ('0' & sequence(0 to sequence'length-2)) or
(0 => Sin, others => '0') when rising_edge(clk);
I am utterly unfamiliar with "wrong way round" arithmetic so I cannot vouch that the shifts actually do what you want.

LSFR counter for random number

module LSFR_counter
#(parameter BITS = 5)
(
input clk,
input rst_n,
output reg [4:0] data
);
reg [4:0] data_next;
always #* begin
data_next[4] = data[4]^data[1];
data_next[3] = data[3]^data[0];
data_next[2] = data[2]^data_next[4];
data_next[1] = data[1]^data_next[3];
data_next[0] = data[0]^data_next[2];
end
always_ff #(posedge clk or negedge rst_n) begin
if(!rst_n)
data <= 5'h1f;
else
data <= data_next;
end
endmodule
This is code for LSFR for 4 bit number. I want to implement N bit Random number generator for an FPGA board.
N is normally reserved for the state of the LFSR, M would be good to use for the number of random bits we wish to generate.
A standard LFSR generates 1 bit of random data, if consecutive bits of the LFSR are used they can be highly correlated, especially if taking a multi-bit value every clock cycle. To remove this correlation we can overclock the lfsr, say 4 times to generate 4 bits. The alternative to the this is to calculate the equations (feedback polynomials) that you would get for each bit. For every clock its internal state (as represented by the N-bits of the LFSR) would move forward 4 steps. Both techniques for over clocking or creating the feedback taps to move the state forward more than 1 step are known as leap-forward.
The code example in the question has been taken from a previous question and answer, this is an example of manually creating the extra feedback for a leap-forward lfsr.
The maths to do this can be done by generating the transition matrix and raising to the power of the number of steps we wish to move forward.
Quick 4-bit LFRS example: with transition matrix a:
a =
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 1
Feedback is XOR of the first and last bit, seen on last row of the matrix. All other rows are just a single shift. The output of this LFSR is good for one bit. Two bits would suffer from a high correlation, unless it was overclocked.
>> a^2
ans =
0 0 1 0
0 0 0 1
1 0 0 1
1 1 0 1
If we want two bits we need to square the transition matrix. It can be seen that the first two rows are a shift of two places and we require feedback for two places, ie we are moving the LFSR forward two states for every clock.
Just for confirmation if we wanted three bits:
a^3
ans =
0 0 0 1
1 0 0 1
1 1 0 1
1 1 1 1
The second code example in the previous question went on to parameterise the code so the leap forward calculations did not have to be manually created, skipping all of that lovely maths! However the approach used meant it could not be fully parameterised. Therefore I would like to revisit the example I gave for that question:
module fibonacci_lfsr(
input clk,
input rst_n,
output [4:0] data
);
wire feedback = data[4] ^ data[1] ;
always #(posedge clk or negedge rst_n)
if (~rst_n)
data <= 4'hf;
else
data <= {data[3:0], feedback} ;
endmodule
Now we want to parameterise it:
module fibonacci_lfsr#(
parameter POLYNOMIAL = 4'h9
)(
input clk,
input rst_n,
output [4:0] data
);
//AND data with POLYNOMIAL this
// selects only the taps in the polynomial to be used.
// ^( ) performs a XOR reduction to 1 bit
always #* begin
feedback = ^( POLYNOMIAL & data);
end
//Reseting to 0 is easier
// Invert feedback, all 1's state is banned instead of all 0's
always #(posedge clk or negedge rst_n)
if (~rst_n)
data <= 'b0;
else
data <= {data[3:0], ~feedback};
endmodule
A small step now, Just bring the shift outside of the synchronous loop to help with the step after.
always #* begin
data_next = data;
feedback = ^( POLYNOMIAL & data);
data_next = {data_next[3:0], ~feedback} ; //<- Shift and feedback
end
always #(posedge clk or negedge rst_n)
if (~rst_n)
data <= 'b0;
else
data <= data_next;
TL;DR
Now to control the leap-forward iterations, let the tools do the heavy lifting of multiplying the transition matrix.
module fibonacci_lfsr#(
parameter POLYNOMIAL = 4'h9,
parameter N = 4,
parameter BITS = 2
)(
input clk,
input rst_n,
output [BITS-1:0] random
);
reg [N-1:0] data;
reg [N-1:0] data_next;
reg feedback;
assign random = data[N-1:N-BITS];
always #* begin
data_next = data;
// Compiler unrolls the loop, calculating the transition matrix
for (int i=0; i<BITS; i++) begin
feedback = ^( POLYNOMIAL & data_next);
data_next = {data_next[N-2:0], ~feedback} ;
end
end
always #(posedge clk or negedge rst_n)
if (~rst_n)
data <= 'b0;
else
data <= data_next;
endmodule
Example on EDA Playground.
i++ is part of SystemVerilog. If you can only synthesis plain (pre-2009) Verilog then you will need to declare i as an integer and use i =i+1 in the for loop.
If you want to implement an N-bit LFSR, then because each length of LFSR has a different polynomial, and hence a difference set of taps to XOR to produce the next LFSR value, you will need to have constants or a lookup table describing the different tap points, which the design could then could use, based on 'BITS'.
A simpler way to do it might be to implement say a 32-bit LFSR, then use the least significant N bits of this as your output. This has the added benefit of increasing the repetition period for anything but the maximum length LFSR, giving better randomness in these cases.
If you're going for the first option, look at whether using the Fibonacci form instead of the Galois form will make the design more conducive to parametrization in this way. I can't quite work out which form you are using in your 5-bit example.
I'm a VHDL guy*, so I can't give Verilog code, but VHDL-like-pseudocode (untested) might look like this:
constant TAPS_TABLE : TAPS_TABLE_type := (
"00000011",
"00000110",
...
);
for i in 0 to BITS-2 loop
if (TAPS_TABLE(BITS-2)(i) = '1') then
data_next(i) <= data(0) xor data(i+1)
else
data_next(i) <= data(i+1)
end if;
end for;
This would support BITS being between 2 and 8 inclusive, assuming the table was completed. The constant TAPS_TABLE would be optimised away during synthesis, leaving you with something no less resource-hungry than a manually coded LFSR.
* This question originally had a 'VHDL' tag.
In Addition to the previous answers:
Years ago, Xilinx wrote a good AppNote on how to implement 'pseudo random number generators' (PRNGs). The AppNote has a TAP table for n = 3..168. The TAP table is optimized to allow the usage of shift registers. So a PRNG with n=32 does not use 32 single FFs.
Efficient Shift Registers, LFSR Counters, and Long PseudoRandom Sequence GeneratorsXilinx [XAPP 052][1996.07.07]

Unsigned logic, vector and addition - How?

I'm creating a program counter that is supposed to use only unsigned numbers.
I have 2 STD_LOGIC_VECTOR and a couple of STD_LOGIC. Is there anything I need to do so that they only use unsigned? At the moment I only have library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
I also need to increase one of the binary vectors by 1 under certain conditions (as you probably have guessed by now). Would you be so kind to explain how to perform such actions (using unsigned and adding up one) considering one of the vectors is output with 32 bits.
I'm guessing (I tried) Output <= Output + 1; won't do. Oh and I'm using a process.
In brief, you can add the ieee.numeric_std package to your architecture (library ieee; use ieee.numeric_std.all;) and then do the addition using:
Output <= std_logic_vector(unsigned(Output) + 1);
to convert your std_logic_vector to an unsigned vector, increment it, and finally convert the result back to an std_logic_vector.
Note that if Output is an output port, this won't work because you can't access the value of an output port within the same block. If that is the case, you need to add a new signal and then assign Output from that signal, outside your process.
If you do need to add a signal, it might be simpler to make that signal a different type than std_logic_vector. For example, you could use an integer or the unsigned type above. For example:
architecture foo of bar is
signal Output_int : integer range 0 to (2**Output'length)-1;
begin
PR: process(clk, resetn)
begin
if resetn='0' then
Output_int <= 0;
elsif clk'event and clk='1' then
Output_int <= Output_int + 1;
end if;
end process;
Output <= std_logic_vector(to_unsigned(Output_int, Output'length));
end foo;
Output_int is declared with a range of valid values so that tools will be able to determine both the size of the integer as well as the range of valid values for simulation.
In the declaration of Output_int, Output'length is the width of the Output vector (as an integer), and the "**" operator is used for exponentiation, so the expression means "all unsigned integers that can be expressed with as many bits as Output has".
For example, for an Output defined as std_logic_vector(31 downto 0), Output'length is 32. 232-1 is the highest value that can be expressed with an unsigned 32-bit integer. Thus, in the example case, the range 0 to (2**Output'length)-1 resolves to the range 0...4294967295 (232=4294967296), i.e. the full unsigned range that can be expressed with 32 bits.
Note that you'll need to add any wrapping logic manually: VHDL simulators will produce an error when you've reached the maximum value and try to increment by one, even if the synthesized logic will cleanly wrap around to 0.

Resources