Created
April 7, 2014 14:19
-
-
Save tausen/10021169 to your computer and use it in GitHub Desktop.
shiftaddmult
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library ieee; | |
use ieee.std_logic_1164.all; | |
use ieee.std_logic_arith.all; | |
use ieee.std_logic_unsigned.all; | |
entity shiftaddmult is | |
generic (WIDTH: integer := 8); | |
port ( | |
clk: in std_logic; | |
reset: in std_logic; | |
x: in std_logic_vector(WIDTH-1 downto 0); | |
y: in std_logic_vector(WIDTH-1 downto 0) | |
); | |
end shiftaddmult; | |
architecture rtl of shiftaddmult is | |
signal acc: std_logic_vector(WIDTH*2-1 downto 0); | |
signal ylsb: std_logic_vector(WIDTH*2-1 downto 0); | |
signal xreg: std_logic_vector(WIDTH*2-1 downto 0); | |
signal yreg: std_logic_vector(WIDTH-1 downto 0); | |
signal andout: std_logic_vector(WIDTH*2-1 downto 0); | |
signal xsign: std_logic_vector(WIDTH-1 downto 0); | |
signal ysign: std_logic_vector(WIDTH-1 downto 0); | |
signal x_invsign: std_logic_vector(WIDTH-1 downto 0); | |
signal y_invsign: std_logic_vector(WIDTH-1 downto 0); | |
begin | |
-- if lsb of y is 0, andout is all zeros | |
-- if lsb of y is 1, andout is xreg | |
ylsb <= (others=>yreg(0)); | |
andout <= ylsb and xreg; | |
-- used for sign extension | |
xsign <= (others=>x(WIDTH-1)); | |
ysign <= (others=>y(WIDTH-1)); | |
-- 2's complement sign inversion | |
x_invsign <= (not x) + 1; | |
y_invsign <= (not y) + 1; | |
process (clk, reset, x, y) | |
begin | |
if (reset = '1') then | |
-- sign extend into double width registers (need room for shifting) | |
if (y(WIDTH-1) = '1') then | |
-- if multiplier is negative, invert multiplier and multiplicand | |
xreg <= (not xsign) & x_invsign; | |
yreg <= y_invsign; | |
else | |
xreg <= xsign & x; | |
yreg <= y; | |
end if; | |
-- reset accumulator | |
acc <= (others=>'0'); | |
elsif (clk = '1') then | |
-- shift xreg left | |
xreg <= xreg(WIDTH*2-2 downto 0) & '0'; | |
-- shift yreg right | |
yreg <= '0' & yreg(WIDTH-1 downto 1); | |
-- add xreg to acc if lsb of y is 1, otherwise do nothing (add zeros) | |
acc <= andout + acc; | |
end if; | |
end process; | |
end rtl; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- TEST BENCH -- | |
LIBRARY ieee; | |
USE ieee.std_logic_1164.all; | |
ENTITY shiftaddmult_vhd_tst IS | |
END shiftaddmult_vhd_tst; | |
ARCHITECTURE shiftaddmult_arch OF shiftaddmult_vhd_tst IS | |
-- constants | |
constant N : integer := 4; | |
-- signals | |
SIGNAL clk : STD_LOGIC; | |
SIGNAL reset : STD_LOGIC; | |
SIGNAL x : STD_LOGIC_VECTOR(N-1 DOWNTO 0); | |
SIGNAL y : STD_LOGIC_VECTOR(N-1 DOWNTO 0); | |
COMPONENT shiftaddmult | |
generic (WIDTH: integer := N); | |
PORT ( | |
clk : IN STD_LOGIC; | |
reset : IN STD_LOGIC; | |
x : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0); | |
y : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0) | |
); | |
END COMPONENT; | |
BEGIN | |
i1 : shiftaddmult | |
generic map(WIDTH => N) | |
PORT MAP ( | |
clk => clk, | |
reset => reset, | |
x => x, | |
y => y | |
); | |
init : PROCESS | |
BEGIN | |
-- code that executes only once | |
x <= "1111"; | |
y <= "0111"; | |
reset <= '1'; | |
wait for 15 ns; | |
reset <= '0'; | |
WAIT; | |
END PROCESS init; | |
always : PROCESS | |
BEGIN | |
clk <= '1'; | |
wait for 10 ns; | |
clk <= '0'; | |
wait for 10 ns; | |
clk <= '1'; | |
wait for 10 ns; | |
clk <= '0'; | |
wait for 10 ns; | |
clk <= '1'; | |
wait for 10 ns; | |
clk <= '0'; | |
wait for 10 ns; | |
clk <= '1'; | |
wait for 10 ns; | |
clk <= '0'; | |
wait for 10 ns; | |
clk <= '1'; | |
wait for 10 ns; | |
clk <= '0'; | |
wait for 10 ns; | |
clk <= '1'; | |
wait for 10 ns; | |
clk <= '0'; | |
wait for 10 ns; | |
clk <= '1'; | |
wait for 10 ns; | |
clk <= '0'; | |
wait for 10 ns; | |
clk <= '1'; | |
wait for 10 ns; | |
clk <= '0'; | |
wait for 10 ns; | |
clk <= '1'; | |
wait for 10 ns; | |
clk <= '0'; | |
wait for 10 ns; | |
clk <= '1'; | |
wait for 10 ns; | |
clk <= '0'; | |
wait for 10 ns; | |
WAIT; | |
END PROCESS always; | |
END shiftaddmult_arch; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Et par simuleringer:
http://tausen.org/s/a397cb0c66.png
http://tausen.org/s/55a05bc66b.png
http://tausen.org/s/c79d372329.png
Den første simulering:
inputs x,y har en sign bit og 3 fractional bits, så
x = 1,111 -> -0,001 -> -2**-3 -> -0.125
y = 0,111 -> 2**-1 + 2**-2 + 2**-3 -> 0.875
og resultatet skulle så gerne blive -0.109375
men resultatet (i acc_bin) har en extension sign bit, en sign bit og 6 fractional bits, så
acc = (1)1,111001 -> -(0)0,000111 -> -(2**-4 + 2**-5 + 2**-6) -> -0.109375