For the fixed point arithmatic I represented 0.166 with 0000 0010101010100110 and multiply it with same. for this I wrote the code in VHDL as below. Output is assigned in y which is signed 41bit. For signed Multiplication A(a1,b1)*A(a2,b2)=A(a1+a2+1,b1+b2). However during the simulation its give an error
Target Size 41 and source size 40 for array dimension 0 does not match.
code:
entity file1 is
Port ( y : out signed(40 downto 0));
end file1;
architecture Behavioral of file1 is
signal a : signed(19 downto 0) := "00000010101010100110";
signal b : signed(19 downto 0) := "00000010101010100110";
begin
y<= (a*b); ----error
end Behavioral;
The result of multiplying 19+1 bits to 19+1 bits is 39+1 bits, while your port is 40+1 bit long. For example let's multiply maximum possible values for 19-bits: 0x7FFFF * 0x7FFFF = 0x3FFFF00001 - so it's 39 bits (19 + 19 + carry) for unsigned result and +1 bit for sign.
So you should either "normalize" result by extending it to 1 more bit, which should be equal to the sign of result (bit#40 = bit#39) or just choose 40-bit port as output:
Port ( y : out signed(39 downto 0))
If you really need redundant 41st bit:
begin
y(39 downto 0) <= (a*b)
y(40) <= y(39)
end Behavioral;
Or just use resize function for signeds: How to convert 8 bits to 16 bits in VHDL?
Related
Please consider this very simple minimal reproducible code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity test is
generic ( LENGTH : integer range 1 to 16 := 5 );
Port ( x : in STD_LOGIC;
y : out STD_LOGIC_VECTOR(15 downto 0)
);
end test;
architecture Behavioral of test is
signal a : std_logic_vector (15 downto 0);
signal b : std_logic_vector (LENGTH - 1 downto 0);
signal i : integer range 0 to LENGTH-1 := 1;
begin
y <= a;
process
begin
if i = LENGTH then
i <= 1;
else
a <= a(15 downto i + 1) & b(i downto 0);
end if;
i <= i + 1;
end process;
end Behavioral;
My need is to join some elements of b into a, depending on i. By running the RTL on Vivado, it says:
[Synth 8-690] width mismatch in assignment; target has 16 bits, source has 20 bits
I don't really get why. Anyhow, the overall range will be 15 - (i + 1) + (i - 0) = 15 ... 0 and fits in the 16 bits of output -- what's the deal for 20 bits?
I should say the problem vanishes (obviously) if I use plain constants instead of i, but I still don't get what's going on.
For runtime variable I (as per the question)...
instead of a big CASE, you can use the value of I to generate masks, and evaluate (A and MASKA) or (B and MASKB). Which is equivalent to the multiplexer the synthesis tool would generate if it wasn't broken.
For generic I (it's not fair to move the goalposts in the comments!)
this approach generates unnecessary hardware, which will be optimised out by any competent synthesis tool.
(There are of course other problems with this code; I assume you deleted the clock, taking the MCVE notion a bit too far. You should leave it valid synthesisable code)
I am receiving an error that says my target is 17 bits but the source is 33 bits. I don't understand how this is the case when the two things being added together are each 16 bits. This should result in a 17-bit sum. I am unsure as to how it comes to 33 bits.
I have tried converting each addend into an sfixed value because that is what the target is. I have tried without this conversion. I have tried using the resize function on each addend in order to guarantee each is 16 bits. This method worked but created an incorrect circuit.
N and I are both generic integers of value 4.
This is the problem statement:
wx12 <= wx(1*(4*N)-1 downto 0*(4*N)) + wx(2*(4*N)-1 downto 1*(4*N));
This is wx and how it is defined/populated:
signal wx : sfixed (4*N*I-1 downto 0);
wx(1*(4*N)-1 downto 0*(4*N)) <= x(1*(2*N)-1 downto 0*(2*N)) * w(1*(2*N)-1 downto 0*(2*N));
wx(2*(4*N)-1 downto 1*(4*N)) <= x(2*(2*N)-1 downto 1*(2*N)) * w(2*(2*N)-1 downto 1*(2*N));
wx(3*(4*N)-1 downto 2*(4*N)) <= x(3*(2*N)-1 downto 2*(2*N)) * w(3*(2*N)-1 downto 2*(2*N));
wx(4*(4*N)-1 downto 3*(4*N)) <= x(4*(2*N)-1 downto 3*(2*N)) * w(4*(2*N)-1 downto 3*(2*N));
This is w and how it is defined:
constant w : sfixed ((2*N*I)-1 downto 0) := to_sfixed(1, N-1, -N)
& to_sfixed(1, N-1, -N)
& to_sfixed(1, N-1, -N)
& to_sfixed(1, N-1, -N);
This is x and how it is defined:
x : in sfixed ((2*N*I)-1 downto 0);
I expected a result of 17 bits but the error below shows the result is actually 33 bits.
[Synth 8-690] width mismatch in assignment; target has 17 bits, source has 33 bits ["C:/Users/devon/project_1/project_1.srcs/sources_1/new/neural_network.vhd":104]
If N and I are 4, then you have this:
wx12 <= wx(15 downto 0) + wx(31 downto 16);
The fixed_point libraries, by default, behave differently to numeric_std.
Both operands are re-shaped to be (max(a,b) downto (min(a,b))
The result has bit growth.
Because max(a,b) = 31, and min(a,b) = 0, both operands are bit extended to (31 downto 0) - 32 bit. It then has a single bit of growth, giving the result.
This is all because the fixed point libraries respects the index as the 2^n. to do what you want, you need to re-align the 2nd operand to (15 downto 0) yourself.
I want to divide a number by 512 meaning that I need to shift it by 9. For example in my code I want to take the number 26 in binary form to multiply by 100 and then divide it by 512. But instead of dividing by 512 all I need to do is to shift right 9 times the number 26*100. But when I do the shift_right command I get the following error:
Error (10511): VHDL Qualified Expression error at Multiplier_VHDL .vhd(34): SHIFT_RIGHT type specified in Qualified Expression must match std_logic_vector type that is implied for expression by context
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Multiplier_VHDL is
GENERIC (
display_resolution : INTEGER := 23; -- counter to get to the lowest frequency
display_counter: INTEGER := 8); -- counter to get to 97KHz frequency
port (
Nibble1 : in std_logic_vector(display_counter downto 0) := "000011010"; -- 26 in binary form
Nibble2 : in std_logic_vector(display_counter downto 0);
Result: out std_logic_vector(17 downto 0));
end entity Multiplier_VHDL;
architecture Behavioral of Multiplier_VHDL is
signal number : unsigned(display_counter downto 0) := "001100100"; -- 100 in binary form
begin
Result <= std_logic_vector(unsigned(Nibble1) * unsigned(number));
Result <= (shift_right(unsigned(number), display_counter + 1));
end architecture Behavioral;
shift_right returns either unsigned or signed, depending on what you give it. So you're trying to write an unsigned to a std_logic_vector (Result is of type std_logic_vector).
Also, number is already of type unsigned so there's no need to cast it to unsigned again.
But I give you +1 point for using numeric_std rather than std_logic_arith.
I'm using VHDL for describing a 32 bits multiplier, for a system to be implemented on a Xilinx FPGA, I found on web that the rule of thumb is that if you have inputs of N-bits size, the output must've (2*N)-bits of size. I'm using it for a feedback system, is it posible to has a multiplier with an output of the same size of it's inputs?.
I swear once I found a fpga application, which vhdl code has adders and multipliers blocks wired with signals of the same size. The person who wrote the code told me that you just have to put the result of the product on a 64 bits signal and then the output has to get the most significant 32 bits of the result (which was not necesarily on the most significant 32 bits of the 64 bits signal).
At the time I build a system (apparently works) using the next code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Multiplier32Bits is
port(
CLK: in std_logic;
A,B: in std_logic_vector(31 downto 0);
R: out std_logic_vector(31 downto 0)
);
end Multiplier32Bits;
architecture Behavioral of Multiplier32Bits is
signal next_state: std_logic_vector(63 downto 0);
signal state: std_logic_vector(31 downto 0);
begin
Sequential: process(CLK,state,next_state)
begin
if CLK'event and CLK = '1' then
state <= next_state(61 downto 30);
else
state <= state;
end if;
end process Sequential;
--Combinational part
next_state <= std_logic_vector(signed(A)*signed(B));
--Output assigment
R <= state;
end Behavioral;
I though it was working since at the time I had the block simulated with Active-HDL FPGA simulator, but know that I'm simulating the whole 32 bit system using iSim from Xilinx ISE Design Suite. I found that my output has a big difference from the real product of A and B inputs, which I don't know if it's just the accuracy loose from skipping 32 bits or my code is just bad.
Your code has some problems:
next_state and state don't belong into the sensitivity list
The writing CLK'event and CLK = '1' should be replaced by rising_edge(CLK)
state <= state; has no effect and causes some tools like ISE to misread the pattern. Remove it.
Putting spaces around operators doesn't hurt, but improves readability.
Why do you expect the result of a * b in bits 30 to 61 instead of 0 to 31?
state and next_state don't represent states of a state machine. It's just a register.
Improved code:
architecture Behavioral of Multiplier32Bits is
signal next_state: std_logic_vector(63 downto 0);
signal state: std_logic_vector(31 downto 0);
begin
Sequential: process(CLK)
begin
if rising_edge(CLK) then
state <= next_state(31 downto 0);
end if;
end process Sequential;
--Combinational part
next_state <= std_logic_vector(signed(A) * signed(B));
--Output assigment
R <= state;
end architecture Behavioral;
I totally agree with everything that Paebbels write. But I will explain to you this things about number of bits in the result.
So I will explain it by examples in base 10.
9 * 9 = 81 (two 1 digit numbers gives maximum of 2 digits)
99 * 99 = 9801 (two 2 digit numbers gives maximum of 4 digits)
999 * 999 = 998001 (two 3 digit numbers gives maximum of 6 digits)
9999 * 9999 = 99980001 (4 digits -> 8 digits)
And so on... It is totally the same for binary. That's why output is (2*N)-bits of size of input.
But if your numbers are smaller, then result will fit in same number of digits, as factors:
3 * 3 = 9
10 * 9 = 90
100 * 99 = 990
And so on. So if your numbers are small enough, then result will be 32 bit. Of course, as Paebbels already written, result will be in least significant part of signal.
And as J.H.Bonarius already pointed out, if your input consist not of integer, but fixed point numbers, then you would have to do post shifting. If this is your case, write it in the comment, and I will explain what to do.
I would like to add zero at the lsb (zero padding). my input is
m : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
and another vector (lets say a) that his length is changing all the time.
I didn't manage doing that by using bitwise "OR" because the length is always not the same.
Assuming you don't know the length of a, but want to zero pad the LSB of the resulting vector b it to length of b.
b(b'left downto b'left - a'left) <= a;
b(b'left - a'left - 1 downto 0) <= (others => '0');
I hope I didn't mix up the - 1.