DSD VHDL Ch4
DSD VHDL Ch4
Ci 0 1 1 1 0
Control Circuit
input: N, Clock output: Sh
Examples
Good!
Bad!
Multiplication
add and shift operation Product
Mcand Mplier
process begin wait until Clk = '1'; -- executes on rising edge of clock case State is when 0=> -- initial State if St='1' then ACC(8 downto 4) <= "00000"; -- Begin cycle ACC(3 downto 0) <= Mplier; -- load the multiplier State <= 1; end if;
11
when 1 | 3 | 5 | 7 => -- "add/shift" State if M = '1' then -- Add multiplicand ACC(8 downto 4) <=add4(ACC(7 downto 4),Mcand,'0'); State <= State + 1; else ACC <= '0' & ACC(8 downto 1); --Shift accumulator right State <= State + 2; end if; when 2 | 4 | 6 | 8 => -- "shift" State ACC <= '0' & ACC(8 downto 1); -- Right shift State <= State + 1; when 9 => -- End of cycle State <= 0; end case; end process; Done <= '1' when State = 9 else '0'; end behave1;
12
13
14
15
4 x 4 Array Multiplier
17
18
19
20
10
=1.g = -1 + 0.g
21
22
11
23
24
12
Faster Multiplier
25
26
13
2s complement
library BITLIB; use BITLIB.bit_pack.all; entity mult2C is port (CLK, St: in bit; Mplier,Mcand : in bit_vector(3 downto 0); Product: out bit_vector (6 downto 0); Done: out bit); end mult2C; architecture behave1 of mult2C is signal State : integer range 0 to 5; signal A, B: bit_vector(3 downto 0); alias M: bit is B(0); begin
27
process variable addout: bit_vector(4 downto 0); begin wait until CLK = '1'; case State is when 0=> -- initial State if St='1' then A <= "0000"; -- Begin cycle B <= Mplier; -- load the multiplier State <= 1; end if;
28
14
when 1 | 2 | 3 => -- "add/shift" State if M = '1' then addout := add4(A,Mcand,'0'); -- Add --multiplicand to A and shift A <= Mcand(3) & addout(3 downto 1); B <= addout(0) & B(3 downto 1); else A <= A(3) & A(3 downto 1); -- Arithmetic --right shift B <= A(0) & B(3 downto 1); end if; State <= State + 1;
29
when 4 => -- add complement if sign bit if M = '1' then -- of multiplier is 1 addout := add4(A, not Mcand,'1'); A <= not Mcand(3) & addout(3 downto 1); B <= addout(0) & B(3 downto 1); else A <= A(3) & A(3 downto 1); -- Arithmetic right shift B <= A(0) & B(3 downto 1); end if; State <= 5; wait for 0 ns; Done <= '1'; Product <= A(2 downto 0) & B; when 5 => -- output product State <= 0; Done <= '0'; end case; end process; end behave1;
30
15
31
16
begin CLK <= not CLK after 10 ns; process begin for i in 1 to N loop Mcand <= Mcandarr(i); Mplier <= Mplierarr(i); St <= '1'; wait until rising_edge(CLK); St <= '0'; wait until falling_edge(Done); end loop; end process; mult1: mult2c port map(Clk, St, Mplier, Mcand, Product, Done); end test1;
33
34
17
process (state, st, M) begin Load <= '0'; AdSh <= '0'; Sh <= '0'; Cm <= '0'; Done <= '0'; case State is when 0=> -- initial State if St='1' then Load <= '1'; Nextstate <= 1; end if; when 1 | 2 | 3 => -- "add/shift" State if M = '1' then AdSh <= '1'; else Sh <= '1'; end if; Nextstate <= State + 1; when 4 => -- add complement if sign if M = '1' then Cm <= '1'; AdSh <= '1';-- bit of multiplier is 1 else Sh <= '1'; end if; nextstate <= 5; when 5 => -- Output product done <= '1'; nextstate <= 0; 36 end case;
18
end process; addout <= add4(A, Mcand, '0') when Cm = '0' else add4(A, not Mcand, '1'); process begin wait until CLK = '1'; -- executes on rising edge if Load = '1' then -- Load the multiplier A <= "0000"; B <= Mplier; end if; if AdSh = '1' then -- Add multiplicand to A and Shift A <= (Mcand(3) xor Cm) & addout(3 downto 1); B <= addout(0) & B(3 downto 1); end if; if Sh = '1' then A <= A(3) & A(3 downto 1); B <= A(0) & B(3 downto 1); end if; State <= Nextstate; end process; Product <= A(2 downto 0) & B; end behave2;
37
38
19
Count1: C74163 port map (Ld1, CLR1, P1, One, CLK, Din, open, Q); P1 <= Q(2); CLR1 <= not Q(3); Done <= Q(3); Sh <= not M and Q(2); AdSh <= M and Q(2); Cm <= Q(1) and Q(0) and M; Load <= not Q(3) and not Q(2) and St; Ld1 <= not Load; Comp <= Mcand xor (Cm & Cm & Cm & Cm); -- complement Mcand if Cm='1' addout <= add4(A,Comp,Cm); -- add complementer output to A process begin wait until CLK = '1'; -- executes on rising edge if Load = '1' then -- load the multiplier A <= "0000"; B <= Mplier; end if;
40
20
if AdSh = '1' then -- Add multiplicand to A and shift A <= (Mcand(3) xor Cm) & addout(3 downto 1); B <= addout(0) & B(3 downto 1); end if; if Sh = '1' then -- Right shift with sign extend A <= A(3) & A(3 downto 1); B <= A(0) & B(3 downto 1); end if; if Done = '1' then Product <= A(2 downto 0) & B; end if; end process; end m2ceq;
41
Binary Division
-- Division 8bits / 4bits
42
21
43
44
22
Overflow
quotient of greater than 15 inspect dividend and divisor
Ex) 135/7=19.2857....
can subtract but, quotient bit of 1 will destroy LSB of dividend overflow!
Overflow condition
X8X7X6X5X4Y3Y2Y1Y0
45
Review
Fig. 4-19
Su=1: subtract signal, and set the quotient bit to 1 Su=0: can not subtract C=0: divisor is greater than the 4 leftmost dividend bits, thus, subtract can not occur
46
23
47
48
24
Cm2 Enable complementer (Cm2 equals the complement of the sign bit of the divisor, so that a positive divisor is complemented and a negative divisor is not) Sh Shift the dividend register left one place and increment the counter C Carry output from adder (If C = 1, the divisor can be subtracted from the upper dividend.) St Start V Overflow Qneg Quotient will be negative (Qneg = 1 when sign of dividend and divisor are different)
49
50
25
Signed Divider
51
Signed Divider
52
26
Control
53
27
begin -- concurrent statements compout <= divisor when divisor(15) = '1' -- 1's complementer else not divisor; Addvec(Acc,compout,not divisor(15),Sum,C,16); -- 16-bit adder Quotient <= Q; Rdy <= '1' when State=0 else '0'; process begin wait until Clk = '1'; -- wait for rising edge of clock case State is when 0=> if St = '1' then Acc <= Dbus; -- load upper dividend Sign <= Dbus(15); State <= 1; V <= '0'; Count <= 0; -- initialize overflow// initialize counter end if; 55
when 1=> Q <= Dbus; State <= 2; -- load lower dividend when 2=> Divisor <= Dbus; if Sign ='1'then -- two's complement Dividend if necessary addvec(not Dividend,zero_vector,'1',Dividend,NC,32); end if; State <= 3; when 3=> Dividend <= Dividend(30 downto 0) & '0'; -- left shift Count <= Count+1; State <= 4; when 4 => if C ='1' then -- C v <= '1'; State <= 0; else -- C' Dividend <= Dividend(30 downto 0) & '0'; -- left shift Count <= Count+1; State <= 5; 56 end if;
28
when 5 => if C = '1' then -- C ACC <= Sum; -- subtract Q(0)<= '1'; else Dividend <= Dividend(30 downto 0) & '0'; -- left shift if Count = 15 then -- KC' count<= 0; State <= 6; else Count <= Count+1; end if; end if; when 6=> if C = '1' then -- C Acc <= Sum; -- subtract Q(0) <= '1'; else if (Sign xor Divisor(15))='1' then -- C'Qneg addvec(not Dividend,zero_vector,'1',Dividend,NC,32); end if; -- 2's complement Dividend state <= 0; end if; end case; end process; end signdiv;
57
29
constant dividendarr: arr1 := (X"0000006F",X"07FF00BB",X"FFFFFE08", X"FF80030A",X"3FFF8000",X"3FFF7FFF",X"C00 08000",X"C0008000", X"C0008001",X"00000000",X"FFFFFFFF",X"FFFF FFFF"); constant divisorarr: arr2 := (X"0007", X"E005", X"001E", X"EFFA", X"7FFF", X"7FFF", X"7FFF", X"8000", X"7FFF", X"0001", X"7FFF", X"0000"); signal CLK, St, V, Rdy: bit; signal Dbus, Quotient, divisor: bit_vector(15 downto 0); signal Dividend: bit_vector(31 downto 0); signal count: integer range 0 to N;
59
begin CLK <= not CLK after 10 ns; process begin for i in 1 to N loop St <= '1'; Dbus <= dividendarr(i) (31 downto 16); wait until rising_edge(CLK); Dbus <= dividendarr(i) (15 downto 0); wait until rising_edge(CLK); Dbus <= divisorarr(i); St <= '0'; dividend <= dividendarr(i); -- save dividend for listing divisor <= divisorarr(i); -- save divisor for listing wait until (Rdy = '1'); count <= i; -- save index for triggering end loop; end process; sdiv1: sdiv port map(Clk, St, Dbus, Quotient, V, Rdy); end test1;
60
30
31