Sequential multiplier 應用實驗
這是一個乘法器的實驗,切動VGA模組的DIP SW,輸入乘數和被乘數,並將乘積顯示在VGA模組的LED
比較其他章節的幾個multiplier,了解一個algorithm的一些不同的做法
Source
|
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
|
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.
