Forum Discussion
Altera_Forum
Honored Contributor
8 years agoHelp multiplier vhdl
Hi everyone!
I've some problems with a design, I have to Design an algorithmic state machine to implement a parallel series multiplier for eight-bit numbers encoded in SM (Sign-Magnitude). The multiplying is in a register with parallel output and the multiplier in a shift register of length m with serial output, the first bit to be the least significant. Each bit of multiplier, in his turn, multiplies by multiplying all, so that with operations multiplication is performed. I've the problem with the shift register with serial output, because I don´t know how to do it!! I'm learning VHDL right now, and I've never work with this hardware description language. Please if anyone can help me, I'd be very grateful. Thank you!!13 Replies
- Altera_Forum
Honored Contributor
--- Quote Start --- Hi everyone! I've some problems with a design, I have to Design an algorithmic state machine to implement a parallel series multiplier for eight-bit numbers encoded in SM (Sign-Magnitude). The multiplying is in a register with parallel output and the multiplier in a shift register of length m with serial output, the first bit to be the least significant. Each bit of multiplier, in his turn, multiplies by multiplying all, so that with operations multiplication is performed. I've the problem with the shift register with serial output, because I don´t know how to do it!! I'm learning VHDL right now, and I've never work with this hardware description language. Please if anyone can help me, I'd be very grateful. Thank you!! --- Quote End --- You need to show what have you done so far and where in design stage you want help. The 8 bit sign&magnitude can be any value from 0111 1111 to 1111 1111 when you multiply you do that per bit then add up as in primary school multiplication. You can ignore sign bit as you can conclude that at the end, for demo assume you have: 1) 111 1111 2) 111 1101 thus you multiply 1 by 111 1111 and you get 111 1111 then you multiply by zero which results in zero, shift one bit... xxxxxxx111 1111 xxxxxx000 0000 xxxxx111 1111 xxxx111 111 xx111 1111 x111 1111 111 1111 ------------------------ after 7 multiplications you add all to get result then decide sign bit - Altera_Forum
Honored Contributor
Thank you kaz, but how can I do that in VHDL??
I know how I have to do the operation, but I don't know how to create the register in VHDL. Right now, I have this: library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.std_logic_unsigned.all; use IEEE.numeric_std.all; entity reg_des is port ( multiplicador: in std_logic; multiplicando: in std_logic_vector (7 downto 0); registro7: out std_logic_vector (7 downto 0); registro6: out std_logic_vector (7 downto 0); Q7: out std_logic; resultado: out bit_vector (15 downto 0); clk: in std_logic; reset: in std_logic); end reg_des; architecture behavioral of reg_des is begin reg_des : process (multiplicador, clk, reset) variable Q : std_logic_vector (8 downto 0); begin if reset = '1' then Q:= "000000000"; else if clk'event and clk = '1' then for i in 0 to 7 loop Q(i) := Q(i+1); if i = 0 then registro7(7) <= Q(i) and multiplicando(7); end if; if i = 1 then registro7(6) <= Q(i) and multiplicando(7); registro6 (7) <= Q(i-1) and multiplicando(6); end if; if i = 2 then registro7(5) <= Q(i) and multiplicando(7); registro6 (6) <= Q(i-1) and multiplicando(6); end if; if i = 3 then registro7(4) <= Q(i) and multiplicando(7); registro6 (5) <= Q(i-1) and multiplicando(6); end if; if i = 4 then registro7(3) <= Q(i) and multiplicando(7); registro6 (4) <= Q(i-1) and multiplicando(6); end if; if i = 5 then registro7(2) <= Q(i) and multiplicando(7); registro6 (3) <= Q(i-1) and multiplicando(6); end if; if i = 6 then registro7(1) <= Q(i) and multiplicando(7); registro6 (2) <= Q(i-1) and multiplicando(6); end if; if i = 7 then registro7(0) <= Q(i) and multiplicando(7); registro6 (1) <= Q(i-1) and multiplicando(6); end if; if i = 8 then registro6 (0) <= Q(i-1) and multiplicando(6); end if; end loop; Q(8):=multiplicador; Q7 <= Q(7); end if; end if; end process; end behavioral; ------------------------------------------------------ Is this the correct way to do it?? Thank you! - Altera_Forum
Honored Contributor
--- Quote Start --- You need to show what have you done so far and where in design stage you want help. The 8 bit sign&magnitude can be any value from 0111 1111 to 1111 1111 when you multiply you do that per bit then add up as in primary school multiplication. You can ignore sign bit as you can conclude that at the end, for demo assume you have: 1) 111 1111 2) 111 1101 thus you multiply 1 by 111 1111 and you get 111 1111 then you multiply by zero which results in zero, shift one bit... xxxxxxx111 1111 xxxxxx000 0000 xxxxx111 1111 xxxx111 111 xx111 1111 x111 1111 111 1111 ------------------------ after 7 multiplications you add all to get result then decide sign bit --- Quote End --- Thank you kaz, but how can I do that in VHDL?? I know how I have to do the operation, but I don't know how to create the register in VHDL. Right now, I have this: library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.std_logic_unsigned.all; use IEEE.numeric_std.all; entity reg_des is port ( multiplicador: in std_logic; multiplicando: in std_logic_vector (7 downto 0); registro7: out std_logic_vector (7 downto 0); registro6: out std_logic_vector (7 downto 0); Q7: out std_logic; resultado: out bit_vector (15 downto 0); clk: in std_logic; reset: in std_logic); end reg_des; architecture behavioral of reg_des is begin reg_des : process (multiplicador, clk, reset) variable Q : std_logic_vector (8 downto 0); begin if reset = '1' then Q:= "000000000"; else if clk'event and clk = '1' then for i in 0 to 7 loop Q(i) := Q(i+1); if i = 0 then registro7(7) <= Q(i) and multiplicando(7); end if; if i = 1 then registro7(6) <= Q(i) and multiplicando(7); registro6 (7) <= Q(i-1) and multiplicando(6); end if; if i = 2 then registro7(5) <= Q(i) and multiplicando(7); registro6 (6) <= Q(i-1) and multiplicando(6); end if; if i = 3 then registro7(4) <= Q(i) and multiplicando(7); registro6 (5) <= Q(i-1) and multiplicando(6); end if; if i = 4 then registro7(3) <= Q(i) and multiplicando(7); registro6 (4) <= Q(i-1) and multiplicando(6); end if; if i = 5 then registro7(2) <= Q(i) and multiplicando(7); registro6 (3) <= Q(i-1) and multiplicando(6); end if; if i = 6 then registro7(1) <= Q(i) and multiplicando(7); registro6 (2) <= Q(i-1) and multiplicando(6); end if; if i = 7 then registro7(0) <= Q(i) and multiplicando(7); registro6 (1) <= Q(i-1) and multiplicando(6); end if; if i = 8 then registro6 (0) <= Q(i-1) and multiplicando(6); end if; end loop; Q(8):=multiplicador; Q7 <= Q(7); end if; end if; end process; end behavioral; ------------------------------------------------------ Is this the correct way to do it?? Thank you! - Altera_Forum
Honored Contributor
At least you got something...
if it was me I will run a 7 states machine (or just a counter 0 to 6). Assuming y = A*B then I might go as below
you will need to declare proper types and manage bitwidth for addition.case count is when 0 => if A(0) = '1' then temp <= B; else temp <= "0000000"; end if; y <= y + temp; -- first of 7 additions, initialise y to zero when 1 => if A(1) = '1' then temp <= B; else temp <= "0000000"; end if; y <= y + temp&'0'; --increase weight by one digit ...etc - Altera_Forum
Honored Contributor
--- Quote Start --- At least you got something... if it was me I will run a 7 states machine (or just a counter 0 to 6). Assuming y = A*B then I might go as below
you will need to declare proper types and manage bitwidth for addition. --- Quote End --- Sorry but I can´t understand what you want to do. Can you explain me?case count is when 0 => if A(0) = '1' then temp <= B; else temp <= "0000000"; end if; y <= y + temp; -- first of 7 additions, initialise y to zero when 1 => if A(1) = '1' then temp <= B; else temp <= "0000000"; end if; y <= y + temp&'0'; --increase weight by one digit ...etc - Altera_Forum
Honored Contributor
--- Quote Start --- Sorry but I can´t understand what you want to do. Can you explain me? --- Quote End --- take this example: A = 1111101 B = 1111111 y = 0 count = 0 , A(0) = '1' hence result of A(0) *B = B (1111111), I called it temp update sum: y = y+temp; count <= count + 1; count = 1 , A(1) = '0' hence result of A(1) *B = 0, I called it temp update sum: y = y+temp&'0'; --shift temp by one bit count <= count + 1; count = 2 , A(2) = '1' hence result of A(2) *B = B, I called it temp update sum: y = y+temp&'00'; --shift temp by two bits count <= count + 1; ... - Altera_Forum
Honored Contributor
--- Quote Start --- take this example: A = 1111101 B = 1111111 y = 0 count = 0 , A(0) = '1' hence result of A(0) *B = B (1111111), I called it temp update sum: y = y+temp; count <= count + 1; count = 1 , A(1) = '0' hence result of A(1) *B = 0, I called it temp update sum: y = y+temp&'0'; --shift temp by one bit count <= count + 1; count = 2 , A(2) = '1' hence result of A(2) *B = B, I called it temp update sum: y = y+temp&'00'; --shift temp by two bits count <= count + 1; ... --- Quote End --- I've been working in this project and I've get this: library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.std_logic_unsigned.all; use IEEE.numeric_std.all; entity prueba2 is port ( A : in std_logic_vector (7 downto 0); B : in std_logic_vector (7 downto 0); inicio : in std_logic; clk : in std_logic; reset: in std_logic; q : out std_logic_vector (2 downto 0); resultado : out std_logic_vector (15 downto 0) ); end prueba2; architecture behavioral of prueba2 is begin multi : process (A, clk, reset) variable y : std_logic_vector (15 downto 0); variable cuenta : std_logic_vector (2 downto 0); variable temp : std_logic_vector (7 downto 0); begin if reset = '1' then y:= "0000000000000000"; else if clk'event and clk = '1' and inicio = '1' then cuenta := cuenta + 1; end if; q <= cuenta; end if; case cuenta is when "000" => if A(0) = '1' then temp := B; else temp := "00000000"; end if; y := y + temp; when "001" => if A(1) = '1' then temp := B; else temp := "00000000"; end if; y := y + temp&"0"; when "010" => if A(2) = '1' then temp := B; else temp := "00000000"; end if; y := y + temp&"00"; when "011" => if A(3) = '1' then temp := B; else temp := "00000000"; end if; y := y + temp&"000"; when "100" => if A(4) = '1' then temp := B; else temp := "00000000"; end if; y := y + temp&"0000"; when "101" => if A(5) = '1' then temp := B; else temp := "00000000"; end if; y := y + temp&"00000"; when "110" => if A(6) = '1' then temp := B; else temp := "00000000"; end if; y := y + temp&"000000"; when "111" => if A(7) = '1' then temp := B; else temp := "00000000"; end if; y := y + temp&"0000000"; end case; resultado <= y; end process; end behavioral; ------------------------------------------- But there is an error when I do y := y + temp&"0"; because expression has 17 elements, but must have 16 elements. How can I correct this? - Altera_Forum
Honored Contributor
That is because + and & operators have equal precedence, so it is doing the add followed by concatenate, giving you a 17 bit result (ie. you code is actaully y := (Y+temp)& "0"; )
You need to put () in to fix the precedence: y := y + (temp&"0"); - Altera_Forum
Honored Contributor
here is my go without sim and without sign bit output.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.numeric_std.all; entity prueba2 is port ( A : in std_logic_vector (7 downto 0); B : in std_logic_vector (7 downto 0); inicio : in std_logic; clk : in std_logic; reset : in std_logic; q : out std_logic_vector (2 downto 0); resultado : out std_logic_vector (15 downto 0) ); end prueba2; architecture behavioral of prueba2 is signal y : unsigned(15 downto 0); begin multi : process (clk, reset) variable cuenta : unsigned(2 downto 0); variable temp : unsigned(15 downto 0); begin if reset = '1' then --reset all elsif clk'event and clk = '1' then if inicio = '1' then cuenta := cuenta + 1; end if; q <= std_logic_vector(cuenta); temp := (others => '0'); --default y <= y + temp; if cuenta = "000" then --update output resultado <= std_logic_vector(y); end if; case cuenta is when "000" => if A(0) = '1' then temp := "00000000"&unsigned(B); end if; when "001" => if A(1) = '1' then temp := "0000000"&unsigned(B)&'0'; end if; when "010" => if A(2) = '1' then temp := "000000"&unsigned(B)&"00"; end if; when "011" => if A(3) = '1' then temp := "00000"&unsigned(B)&"000"; end if; when "100" => if A(4) = '1' then temp := "0000"&unsigned(B)&"0000"; end if; when "101" => if A(5) = '1' then temp := "000"&unsigned(B)&"00000"; end if; when "110" => if A(6) = '1' then temp := "00"&unsigned(B)&"000000"; end if; when "111" => if A(7) = '1' then temp := "0"&unsigned(B)&"0000000"; end if; end case; end if; end process; end behavioral; - Altera_Forum
Honored Contributor
I suggest you change my code to all signals instead of variables as I fell into that trap since temp may not be set to zeros in the way I have written