我一直在尝试使用64位结果创建一个32位Booth编码乘法器。在我的调试中,我已经积极地测试了所有单个组件,并确认了它们的操作,但是当我将乘法器放在一起时,但是当我测试它时,我得到的只是0。移位寄存器我似乎根本没有加载。我想知道是否有人可以看看我的数据路径设计,看看你是否能发现任何缺陷,假设每个组件都能成功运行,因为我有理由相信它们会这样做。
我的算法如下:我有一个右移位寄存器(称为P寄存器),它在算术上移位,一个移位寄存器(称为A寄存器)在逻辑上移位。 P最初没有值,而A加载了一个要乘的数字。 P将最终保持产品的最重要的32位,而A将具有最低有效值32.另一个要乘的数字被加载到常规寄存器(称为B)。在乘法过程中,A逐位移出,进入触发器。进入触发器的A位和触发器的输出通过XOR门进行比较,XOR门的输出连接到类似多路复用器的器件。按照Booth编码算法,它的工作是确定是否添加B或-B(其中-B是使用32位NOT门的B的反转值)。选择取决于从A移出的位的值。
最后,P寄存器的并行输出被送入32位加法器,它将加到B,-B或0(如果不需要加B,P应保持不变),并且加法器的输出反馈到P.这个过程重复进行,直到乘法结束,并且应该进行64个加载和移位循环,由控制器中的计数器管理。寄存器有一个两位控制信号,用于确定它们是否应加载,移位或保持。控制器具有加载A和B的状态,然后在保持A的同时加载P,然后将它们都移位,并从加法器重新加载P并重复该过程,直到乘法完成。
如果所有这些都有意义,我的数据路径代码如下,接着是所提到的控制信号和计数到64个周期的计数器的组合。基本上,我已经找到了大部分实现(我相信),我只想帮助弄清楚为什么我的寄存器永远不会被加载。如果我的方法的任何部分/部分不清楚,请告诉我!任何帮助将不胜感激!
MULTIPLIER DATAPATH
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.all;
USE work.ALL;
ENTITY multiplier_32bit IS
PORT ( X, Y : IN STD_LOGIC_VECTOR(31 DOWNTO 0); --The inputs to the multiplier - X: Multiplicand Y: Multiplier
LOADP, LOADA : IN STD_LOGIC_VECTOR(1 DOWNTO 0); --LOAD SIGNALS
LOADB : IN STD_LOGIC; -- LOADB
CLK : IN STD_LOGIC;
CLRB : IN STD_LOGIC; --CLEAR SIGNAL (CLEAR BAR)
OUT64: OUT STD_LOGIC_VECTOR(63 DOWNTO 0)); --64 BIT OUTPUT
END multiplier_32bit;
ARCHITECTURE struct OF multiplier_32bit IS
COMPONENT dflipflop IS
PORT ( d, clk, clr : IN STD_LOGIC;
q, qbar : OUT STD_LOGIC);
END COMPONENT;
COMPONENT notgate_32 IS
PORT ( a : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
F : OUT STD_LOGIC_VECTOR (31 DOWNTO 0));
END COMPONENT;
COMPONENT xorgate IS
PORT ( a, b: IN STD_LOGIC;
F : OUT STD_LOGIC);
END COMPONENT;
COMPONENT multiplexer_2to1 IS
PORT(s0, en: IN STD_LOGIC;
a, b: IN STD_LOGIC_VECTOR(31 downto 0);
o: OUT STD_LOGIC_VECTOR(31 downto 0));
END COMPONENT;
COMPONENT register_32bit IS
PORT (clr, clk, loadb : IN STD_LOGIC;
D : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
Q : OUT STD_LOGIC_VECTOR (31 DOWNTO 0));
END COMPONENT;
COMPONENT right_shift_register_32bit IS --Logical shift register
PORT ( d : IN std_logic_vector(31 DOWNTO 0);
SI : IN std_logic;
clr : IN std_logic;
clk : IN std_logic;
CONTROL : IN std_logic_vector(1 DOWNTO 0);
POUT : OUT std_logic_vector(31 DOWNTO 0);
SO : OUT std_logic);
END COMPONENT;
COMPONENT fulladder_32bit IS
PORT ( a: IN STD_LOGIC_VECTOR (31 DOWNTO 0);
b: IN STD_LOGIC_VECTOR (31 DOWNTO 0);
cin : IN STD_LOGIC;
sum: OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
cout: OUT STD_LOGIC);
END COMPONENT;
FOR ALL : dflipflop USE ENTITY work.dflipflop(rtl);
FOR ALL : notgate_32 USE ENTITY work.notgate_32(dataflow);
FOR ALL : xorgate USE ENTITY work.xorgate(dataflow);
FOR ALL : multiplexer_2to1 USE ENTITY work.multiplexer_2to1(rtl);
FOR ALL : fulladder_32bit USE ENTITY work.fulladder_32bit(struct);
FOR ALL : register_32bit USE ENTITY work.reg32(rtl);
FOR ALL : right_shift_register_32bit USE ENTITY work.rsr(rtl);
SIGNAL P_IN : STD_LOGIC_VECTOR (31 DOWNTO 0); -- Full adder result back to P register
SIGNAL Ai : STD_LOGIC;
SIGNAL A0 : STD_LOGIC; --A0 = Ai-1
SIGNAL mux_en : STD_LOGIC; --Enable for B-selection mux
SIGNAL SO : STD_LOGIC; --Single bit shift out of P register
SIGNAL POUTP : STD_LOGIC_VECTOR (31 DOWNTO 0); -- Parallel output of P register
SIGNAL Im1 : STD_LOGIC_VECTOR (31 DOWNTO 0); -- Selected B or -B (Output of MUX)
SIGNAL Im2 : STD_LOGIC_VECTOR (31 DOWNTO 0); -- B (Y) from B register
SIGNAL Im3 : STD_LOGIC_VECTOR (31 DOWNTO 0); -- -B (-Y) from B register
SIGNAL AdrOUT : STD_LOGIC; --Carry out of the adder
SIGNAL Qbar : STD_LOGIC; --QBAR of DFF - UNUSED
SIGNAL POUTA : STD_LOGIC_VECTOR (31 DOWNTO 0); -- Parallel out of A
SIGNAL LB : STD_LOGIC; --LOADB
SIGNAL LP : STD_LOGIC_VECTOR (1 DOWNTO 0); --LOADP
SIGNAL LA : STD_LOGIC_VECTOR (1 DOWNTO 0) ; --LOADA
BEGIN
GO: right_shift_register_32bit PORT MAP (P_IN(31 DOWNTO 0), POUTP(31), CLRB, CLK, LP(1 DOWNTO 0), POUTP(31 DOWNTO 0), SO); --P1's RIGHT SHIFT REGISTER
G1: right_shift_register_32bit PORT MAP (X(31 DOWNTO 0), SO, CLRB, CLK, LA(1 DOWNTO 0), POUTA(31 DOWNTO 0), Ai); -- P2/A's RIGHT SHIFT REGISTER
G2: dflipflop PORT MAP (Ai, CLK, CLRB, A0, Qbar);
G3: xorgate PORT MAP (Ai, A0, mux_en);
G4: register_32bit PORT MAP (CLRB, CLK, LB, Y(31 DOWNTO 0), Im2(31 DOWNTO 0));
G5: notgate_32 PORT MAP (Im2(31 DOWNTO 0), Im3(31 DOWNTO 0));
G6: multiplexer_2to1 PORT MAP (Ai, mux_en, Im3(31 DOWNTO 0), Im2(31 DOWNTO 0), Im1(31 DOWNTO 0));
G7: fulladder_32bit PORT MAP (POUTP(31 DOWNTO 0), Im1(31 DOWNTO 0), Ai, P_IN(31 DOWNTO 0), AdrOUT);
OUT64(63 DOWNTO 32) <= POUTP(31 DOWNTO 0);--Most siginificant bits of result come from P register
OUT64(31 DOWNTO 0) <= POUTA(31 DOWNTO 0); --Least significant bits of result come from A register
END struct;
MULTIPLIER FULL ASSEMBLY
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
USE ieee.std_logic_arith.ALL;
USE work.ALL;
ENTITY fullproject IS
PORT( X, Y: IN STD_LOGIC_VECTOR (31 DOWNTO 0);
CLK, START, CLRB : IN STD_LOGIC;
OUT64 : OUT STD_LOGIC_VECTOR (63 DOWNTO 0);
FIN : OUT STD_LOGIC);
END fullproject;
ARCHITECTURE struct OF fullproject IS
COMPONENT multiplier_32bit IS
PORT ( X, Y : IN STD_LOGIC_VECTOR(31 DOWNTO 0); --The inputs to the multiplier - X: Multiplicand Y: Multiplier
LOADP, LOADA : IN STD_LOGIC_VECTOR(1 DOWNTO 0); --LOAD SIGNALS
LOADB : IN STD_LOGIC; -- LOADB
CLK : IN STD_LOGIC;
CLRB : IN STD_LOGIC; --CLEAR SIGNAL (CLEAR BAR)
OUT64: OUT STD_LOGIC_VECTOR(63 DOWNTO 0)); --64 BIT OUTPUT
END COMPONENT;
COMPONENT controller IS
PORT(START, clrb, clk : IN STD_LOGIC;
COUNT : IN STD_LOGIC_VECTOR (6 DOWNTO 0); --Clock cycle binary counter (to 64)
COUNT_EN : OUT STD_LOGIC; --Enable for the counter
LOADP : OUT STD_LOGIC_VECTOR (1 DOWNTO 0);
LOADA : OUT STD_LOGIC_VECTOR (1 DOWNTO 0);
LOADB : OUT STD_LOGIC; -- LOAD signal for B register
CLEAR : OUT STD_LOGIC; -- LOAD signal for B register
FIN : OUT STD_LOGIC); --"DONE"
END COMPONENT;
COMPONENT counter_64 IS
PORT ( COUNT_EN, clk, clr: IN STD_LOGIC;
COUNT: OUT STD_LOGIC_VECTOR(6 DOWNTO 0));
END COMPONENT;
FOR ALL : multiplier_32bit USE ENTITY work.multiplier_32bit(struct);
FOR ALL : controller USE ENTITY work.controller(ctrl);
FOR ALL : counter_64 USE ENTITY work.counter64(rtl);
SIGNAL LOADP : STD_LOGIC_VECTOR (1 DOWNTO 0); --LOADP SIGNAL
SIGNAL LOADB : STD_LOGIC; --LOADB
SIGNAL LOADA: STD_LOGIC_VECTOR (1 DOWNTO 0); --LOADA SIGNAL
SIGNAL COUNT : STD_LOGIC_VECTOR (6 DOWNTO 0); -- COUNT (7bit)
SIGNAL COUNT_EN : STD_LOGIC; --COUNT_EN
SIGNAL clear: STD_LOGIC;
BEGIN
G0 : multiplier_32bit PORT MAP (X(31 DOWNTO 0), Y(31 DOWNTO 0), LOADP, LOADA, LOADB, CLK, clear, OUT64(63 DOWNTO 0));
G1 : controller PORT MAP(START, clrb, CLK, COUNT(6 DOWNTO 0), COUNT_EN, LOADP, LOADA, LOADB, clear, FIN);
G2 : counter_64 PORT MAP(COUNT_EN, CLK, clear, COUNT(6 DOWNTO 0));
END struct;
编辑:下面是我的结果,显示P和A的寄存器从未加载,作为OUT64信号,其内容为P的前32位,底部为32位A的内容始终为0。
编辑2:下面是我正在使用整个项目中的数据路径及其测试平台和波形进行编译的控制器文件。
CONTROLLER
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
USE ieee.std_logic_arith.ALL;
USE work.ALL;
ENTITY controller IS
PORT(START, clrb, clk : IN STD_LOGIC;
COUNT : IN STD_LOGIC_VECTOR (6 DOWNTO 0); --Clock cycle binary counter (to 64)
COUNT_EN : OUT STD_LOGIC; --Enable for the counter
LOADP : OUT STD_LOGIC_VECTOR (1 DOWNTO 0);
LOADA : OUT STD_LOGIC_VECTOR (1 DOWNTO 0);
LOADB : OUT STD_LOGIC; -- LOAD signal for B register
CLEAR : OUT STD_LOGIC;
FIN : OUT STD_LOGIC); --"DONE" signal
END controller;
ARCHITECTURE ctrl OF controller IS
SIGNAL state : STD_LOGIC_VECTOR (4 DOWNTO 0) := "00000"; --Initialize to PRE state
SIGNAL next_state : STD_LOGIC_VECTOR (4 DOWNTO 0);
SIGNAL countDone : STD_LOGIC;
-- Define the (four) states in one-hot way
CONSTANT PRE : STD_LOGIC_VECTOR(4 DOWNTO 0) := "00000";
CONSTANT LOADIN : STD_LOGIC_VECTOR(4 DOWNTO 0) := "00010";
CONSTANT HOLDIN : STD_LOGIC_VECTOR(4 DOWNTO 0) := "00100";
CONSTANT SHIFTIN : STD_LOGIC_VECTOR(4 DOWNTO 0) := "01000" ;
CONSTANT DONE : STD_LOGIC_VECTOR(4 DOWNTO 0) := "10000";
BEGIN
countDone <= count(6);
-- to synthesize edge-triggered flip-flops
-- with asynchronous reset when clrb = 0
clock: PROCESS (clk, clrb)
BEGIN
IF (clrb = '0') THEN
state <= PRE;
ELSIF ( clk'EVENT AND clk = '1' ) THEN
state <= next_state; --On the rising edge, move to the next state
END IF;
END PROCESS clock;
decoding: PROCESS (start, countDone, state)
BEGIN
CASE state IS
--PRE STATE--
WHEN PRE =>
IF (START = '1') THEN
next_state <= LOADIN;
ELSE
next_state <= PRE;
END IF;
--LOADIN STATE--
WHEN LOADIN =>
next_state <= HOLDIN;
--HOLDIN STATE--
WHEN HOLDIN =>
next_state <= SHIFTIN;
WHEN SHIFTIN =>
IF ( countDone = '1' ) THEN
next_state <= DONE; --Go to Finish
ELSE
next_state <= HOLDIN; --If not done, repeat Load, then Shift
END IF;
-- DONE STATE
WHEN DONE =>
next_state <= PRE;
WHEN OTHERS =>
next_state <= PRE;
END CASE;
END PROCESS decoding;
ctrlOutput: PROCESS (state)
BEGIN
CASE state IS
--PRE STATE--
WHEN PRE =>
CLEAR <= '0';
FIN <= '0'; --Send FIN/DONE signal
--LOADIN STATE--
WHEN LOADIN =>
LOADA <= "00"; -- Set LOAD to send signal to load A register
LOADB <= '1'; -- Set LOADB to load B register
CLEAR <= '1';
FIN <= '0'; --Send FIN/DONE signal
--HOLDIN STATE--
WHEN HOLDIN =>
COUNT_EN <= '1'; --Enable the counter
LOADP <= "00"; -- Set LOADP to load P register
LOADA <= "01"; -- HOLD A
CLEAR <= '1';
FIN <= '0'; --Send FIN/DONE signal
WHEN SHIFTIN =>
LOADP <= "11"; -- SHIFT P
LOADA <= "11"; -- SHIFT A
CLEAR <= '1';
FIN <= '0'; --Send FIN/DONE signal
-- DONE STATE
WHEN DONE =>
CLEAR <= '1';
FIN <= '1';
WHEN OTHERS =>
CLEAR <= '1';
FIN <= '0'; --Send FIN/DONE signal
END CASE;
END PROCESS ctrlOutput;
END ctrl;
CONTROLLER Testbench
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
ENTITY controller_tb IS
END controller_tb;
ARCHITECTURE tb OF controller_tb IS
COMPONENT controller IS
PORT(START, clrb, clk : IN STD_LOGIC;
COUNT : IN STD_LOGIC_VECTOR (6 DOWNTO 0); --Clock cycle binary counter (to 64)
COUNT_EN : OUT STD_LOGIC; --Enable for the counter
LOADP : OUT STD_LOGIC_VECTOR (1 DOWNTO 0);
LOADA : OUT STD_LOGIC_VECTOR (1 DOWNTO 0);
LOADB : OUT STD_LOGIC; -- LOAD signal for B register
FIN : OUT STD_LOGIC); --"DONE" signal
END COMPONENT;
COMPONENT counter64 IS
PORT (COUNT_EN, clk, clr: IN STD_LOGIC;
COUNT: OUT STD_LOGIC_VECTOR(6 DOWNTO 0));
END COMPONENT;
FOR ALL: controller USE ENTITY work.controller(ctrl);
FOR ALL: counter64 USE ENTITY work.counter64(rtl);
SIGNAL COUNT : STD_LOGIC_VECTOR (6 DOWNTO 0);
SIGNAL clk, START : STD_LOGIC := '0';
SIGNAL CLRB, CLR: STD_LOGIC := '1';
SIGNAL FIN : STD_LOGIC;
SIGNAL LOADP : STD_LOGIC_VECTOR (1 DOWNTO 0);
SIGNAL LOADA : STD_LOGIC_VECTOR (1 DOWNTO 0);
SIGNAL LOADB : STD_LOGIC;
SIGNAL COUNT_EN : STD_LOGIC := '0';
BEGIN
G0: controller PORT MAP( START => START, CLRB => CLRB, CLK => CLK, COUNT => COUNT, COUNT_EN => COUNT_EN, LOADP => LOADP, LOADA => LOADA, LOADB => LOADB, FIN => FIN);
G1: counter64 PORT MAP (COUNT_EN => COUNT_EN, clk => clk, CLR=> CLR, COUNT=> COUNT);
CLOCK: PROCESS
BEGIN
WAIT FOR 10ns;
CLK <= NOT CLK;
IF Now > 1600 ns THEN
WAIT;
END IF;
END PROCESS;
TEST: PROCESS
BEGIN
--WAIT FOR 20ns;
COUNT_EN <= '1';
START <= '1'; --Begin the multiplication
WAIT;
END PROCESS;
END tb;