Sequential multiplier 應用實驗

 

 

這是一個乘法器的實驗,切動VGA模組的DIP SW,輸入乘數和被乘數,並將乘積顯示在VGA模組的LED

 

比較其他章節的幾個multiplier,了解一個algorithm的一些不同的做法

 

Source

 

1. 建立FPGA的Project : multi

 

VHDL : multi.vhd

Verilog : multi.v

 

LIBRARY ieee;

USE ieee.std_logic_1164.all;

USE ieee.std_logic_unsigned.all;

 

ENTITY multi IS

PORT

(

             mclk,en    : IN STD_LOGIC;

             px,py       : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

             po            : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);

             done : OUT STD_LOGIC

);

END multi;

 

ARCHITECTURE a1 OF multi IS

SIGNAL shf,ldclr : STD_LOGIC;

SIGNAL cs,ncs,ccnt : STD_LOGIC_VECTOR(1 DOWNTO 0);

SIGNAL yd             : STD_LOGIC_VECTOR(3 DOWNTO 0);

SIGNAL xd,acc       : STD_LOGIC_VECTOR(7 DOWNTO 0);

BEGIN

 

PROCESS(mclk)

BEGIN

IF(mclk'EVENT AND mclk='1') THEN

             IF(ldclr='1') THEN

                            ccnt <= "11";

             ELSIF(ccnt/="00") THEN

                            ccnt <= ccnt -1;

             END IF;

END IF;

END PROCESS;

 

PROCESS(mclk)

BEGIN

IF(mclk'EVENT AND mclk='1') THEN

             IF(ldclr='1') THEN

                            xd<="0000"&px;

             ELSIF(shf='1') THEN

                            xd<=xd(6 DOWNTO 0)&"0";

             END IF;

END IF;

END PROCESS;

 

PROCESS(mclk)

BEGIN

IF(mclk'EVENT AND mclk='1') THEN

             IF(ldclr='1') THEN

                            yd<=py;

             ELSIF(shf='1') THEN

                            yd<="0"&yd(3 DOWNTO 1);

             END IF;

END IF;

END PROCESS;

 

PROCESS(mclk)

BEGIN

IF(mclk'EVENT AND mclk='1') THEN

             IF(ldclr='1') THEN

                            acc<="00000000";

             ELSIF(yd(0)='1') THEN

                            acc<=acc+xd;

             END IF;

END IF;

END PROCESS;

 

PROCESS(mclk)

BEGIN

IF(mclk'EVENT AND mclk='1') THEN

             cs<=ncs;

END IF;

END PROCESS;

 

PROCESS(cs,en,ccnt)

BEGIN

CASE(cs) IS

WHEN "00" =>

             ldclr<='0'; shf<='0'; done<='0';

             IF(en='1') THEN

                            ncs<="01";

             ELSE

                            ncs<="00";

             END IF;

WHEN "01" =>

             ldclr<='1'; shf<='0'; done<='0';

             ncs<="10";

WHEN "10" =>

             ldclr<='0'; shf<='1'; done<='0';

             IF(ccnt="00") THEN

                            ncs<="11";

             ELSE

                            ncs<="10";

             END IF;

WHEN "11" =>

             ldclr<='0'; shf<='0'; done<='1';

             IF(en='0') THEN

                            ncs<="00";

             ELSE

                            ncs<="11";

             END IF;

WHEN OTHERS =>

             ldclr<='0'; shf<='0'; done<='0';

             ncs<="00";

END CASE;

END PROCESS;

 

po<=acc;

 

END a1;

 

 

module multi

(

mclk,en,

px,py,po,done

);

input mclk,en;

input[3:0] px,py;

output[7:0] po;

output done;

 

reg[7:0] acc,xd;

reg[3:0] yd;

reg[1:0] cs,ncs,ccnt;

reg ldclr,shf,done;

 

always @(posedge mclk)

begin

if(ldclr)

             ccnt<=2'b11;

else if(~(ccnt==2'b00))

             ccnt<=ccnt-1;

end

 

always @(posedge mclk)

begin

if(ldclr)

             xd<={4'b0000,px};

else

             xd<={xd[6:0],1'b0};

end

 

always @(posedge mclk)

begin

if(ldclr)

             yd<=py;

else if(shf)

             yd<={1'b0,yd[3:1]};

end

 

always @(posedge mclk)

begin

if(ldclr)

             acc<=8'h00;

else if(yd[0])

             acc<=acc+xd;

end

 

always @(posedge mclk)

begin

cs<=ncs;

end

 

always @(cs or en or ccnt)

begin

ncs=cs;

case(cs)

2'b00 : begin

             ldclr=1'b0; shf=1'b0; done=1'b0;

             if(en) ncs=2'b01;

             end

2'b01 : begin

             ldclr=1'b1; shf=1'b0; done=1'b0;

             ncs=2'b10;

             end

2'b10 : begin

             ldclr=1'b0; shf=1'b1; done=1'b0;

             if(ccnt==2'b00) ncs=2'b11;

             end

2'b11 : begin

             ldclr=1'b0; shf=1'b0; done=1'b1;

             if(~en) ncs=2'b00;

             end

endcase

end

 

assign po=acc;

 

endmodule

 

 

 

 

 

 

 

1. The state machine cs controls the operation of the data path.

 

2. When in 'idle' state S00, the state machine waits for en=1, which makes the state machine transit to the 'load' state S01, asserting ldclr=1.

 

3. In state S01, the shift registers xd[7:0] and yd[3:0] are loaded with the multiplicand px[3:0] and multiplier py[3:0] respectively and the accumulator is cleared.

 

4. Then, the state transits to the 'shift' state S10, asserting shf=1, shifting the xd and yd for four clocks, and accumulating the shifted xd[7:0] according to the value of yd[0].

 

After four shift cycles, the state transits to the 'done' state S11, asserting done=1, and waiting for en=0(the enable dip switch turned off), that gets the state back to the 'idle' state S00.

 

 

 

 

 

文章標籤
全站熱搜
創作者介紹
創作者 zeppe 的頭像
zeppe

ZEPPE

zeppe 發表在 痞客邦 留言(0) 人氣(77)