工程文件
一、 实验目的
- 熟习Quartus Ⅱ软件的使用。
- 掌握原理图输入法和硬件描述语言**(VHDL)**方法来设计逻辑电路。
- 对设计电路作硬件验证。展示;
二、设计要求
- 用移位相加的方法设计一个乘法器,实现八位二进制的乘法
- 考虑数据输入口的数量不足16位,实现分拍置数的功能
三、实验仪器与环境
- 芯片:EP4CE1022C8
- 编程与仿真环境:Quartus Ⅱ 13.1
- 输入输出验证平台:西安电子科技大学数电试验箱
四、实现原理
(一)二进制数的乘法
如下图(4.1.1)所示,这两种数制的乘法都是把被乘数和乘数的每一位分别相乘,然后将得到的乘积根据所乘的乘数的位数进行移位,比如,在十进制数乘法中,如果将被乘数与乘数的个位相乘,那就把得到的乘积向左移动0位;如果被乘数与乘数的十位相乘,那就把得到的乘积向左移动1位…移位操作完成后,最后将这些移位后的乘积相加,就是最开始这两个被乘数与乘数的结果。
我们都知道,在二进制数中,只有数字0和1。在二进制数乘法中,如果与被乘数相乘的乘数的某一位为1,那结果就是被乘数本身,如果乘数的某一位为0,那此次的结果就是0。因此,二进制数乘法过程中的数次相乘,其实使用与门实现的。
图4.4.1
(二)分拍输入原理
两个8位二进制数相加需要16个输入引脚,但实验板空间有限,只好一次只输入一个8位二进制数,分两拍输入到上述的乘法器主体中。
通过设计置数端完成节拍的掌控,第一个数输入完毕后置数端置一,若置数成功,则第一个灯亮起。第二个数置数完毕后,再将置数端置一。若置数成功,则第二个灯亮起。此时输入模块同时输出两个乘数。
五、系统设计及仿真
(一)乘法器主体模块(mulity_8bit)
图(5.1.1)
该模块共有4个输入端,一个输出端,其中clk为1kHz时钟信号,x和y为两个8位二进制乘数。Start端为1时开始计数,8个时钟周期后result端输出结果。Start端为0时输出为零。
该模块用一个模10计数器实现,亦可以认为是一个三状态的有限状态机。
S0:在计数为0时为第一状态,初始化乘法器,所有变量赋初值。
S1:在计数为1~8时,每次计数时完成以下三步
(1) 乘数右移一位。
(2) 根据乘数最后一位是否为1判断是否需要做移位后的加法。
(3) 乘积向左移动1位
S2:在计数为9时,输出结果。
具体实现代码见附录
仿真波形如图(5.1.2),仿真时实现了
00100101×0010101
和00000110×00000011
图(5.1.2)
(二)分拍输入模块(inp)
图(5.2.1)
该模块共有4个输入端,4个输出端,其中clk为1kHz时钟信号,num端为8位二进数输入端,set为置数端,clear为清零端。x,y为8位二进数输出端。ok_x,ok_y为置数成功显示端。
分拍输入有寄存器实现,通过检测set的次数给X,Y赋值。使用流程如下:
- num的引脚置高低电平
- set置1,Led_x亮起,set置0。
- num的引脚置第二个数
- set置1,Led_y亮起,set置0。置数完成。
- clear恢复初始状态。
- 重复1~5步骤进行第二组输入。
仿真实现上述步骤,如图(5.2.2):
如图(5.2.2)
六、顶层设计:
图(6.1.1)
七、结果仿真:
软件仿真:
图(7.1.1)
硬件测试:
【1】选择对应芯片:
图(7.2.1)
【2】无用管脚选三态:
图(7.2.2)
【3】分配管脚:
图(7.2.3)
【4】下载测试
附录:
(1)Inp.vhd:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
------------------------------------------------------
------------实体inp实现分拍输入数据---------------------
------------------------------------------------------
ENTITY inp IS
PORT(
clk : IN STD_LOGIC; --系统时钟
num : IN STD_LOGIC_VECTOR(7 downto 0); --输入两次8位操作数
set : IN STD_LOGIC; --置数端,高电平有效. num的信号赋值结束后,产生一个高脉冲可输入一个数
clear : IN STD_LOGIC; --清零端,高电平有效. 恢复初始状态. set为1时不可用
OK_x : OUT STD_LOGIC; --第一个数置数成功显示端
OK_Y : OUT STD_LOGIC; --第二个数置数成功显示端
x : OUT STD_LOGIC_VECTOR(7 downto 0); --输出8位乘数x
y : OUT STD_LOGIC_VECTOR(7 downto 0) --输出8位乘数y
);
END ENTITY inp;
------------------------------------------------------
----------------分拍输入使用流程------------------------
------------------------------------------------------
----1. num的引脚置高低电平------------------------------
----2. set置1,Led_x亮起,set置0。---------------------
----3. num的引脚置第二个数-----------------------------
----4. set置1,Led_y亮起,set置0。---------------------
------------------------------------------------------
ARCHITECTURE BEHAVIOR OF inp IS
SIGNAL tem_x : STD_LOGIC_VECTOR(7 downto 0); --result的中间结果
SIGNAL tem_y : STD_LOGIC_VECTOR(7 downto 0); --result的中间结果
BEGIN
process(clk)
VARIABLE count : INTEGER:=0;
VARIABLE Flag : INTEGER:=0; --Flag为set信号标志位,放置在第二个时钟信号到来时(count已经等于1)进入y的赋值阶段。
begin
IF(clk'EVENT AND clk = '1')THEN
IF(set = '1')THEN
IF(count=0)THEN
tem_x<=num; --若count为0,则将操作数赋值给x。
OK_x<='1'; --将第一个led灯点亮。
count := count + 1;
Flag := 0;
ELSIF(count=1 and Flag = 1)THEN
tem_y<=num; --若count为1,则将操作数赋值给y。
OK_y<='1'; --将第二个led灯点亮。
count:= count+1;
Flag := 0;
END IF;
ELSE
Flag := 1; --set为零时,Flag记录为1。
IF(clear = '1')THEN --clear为1时,清空状态信息。
tem_x<="00000000";
tem_y<="00000000";
OK_x<='0';
OK_Y<='0';
count := 0;
Flag := 0;
END IF;
END IF;
x<=tem_x;
y<=tem_y;
END IF;
end process;
END BEHAVIOR;
(2) mulity_8bit.vhd:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
------------------------------------------------------
----实体mulity_8bit通过串行乘法实现8位二进制乘法---------
------------------------------------------------------
ENTITY mulity_8bit IS
PORT(
clk : IN STD_LOGIC; --系统时钟
x : IN STD_LOGIC_VECTOR(7 downto 0); --8位乘数x
y : IN STD_LOGIC_VECTOR(7 downto 0); --8位乘数y
start : IN STD_LOGIC; --START为1时置数,为0时不工作
result : OUT STD_LOGIC_VECTOR(15 downto 0) --16位结果
);
END ENTITY mulity_8bit;
------------------------------------------------------
--------------------串行乘法---------------------------
------------------------------------------------------
ARCHITECTURE BEHAVIOR OF mulity_8bit IS
SIGNAL p : STD_LOGIC_VECTOR(15 downto 0); --p,t为中间变量,记录每次一位相乘的结果
SIGNAL t : STD_LOGIC_VECTOR(15 downto 0);
SIGNAL tem : STD_LOGIC_VECTOR(15 downto 0); --result的中间结果
SIGNAL y_reg : STD_LOGIC_VECTOR(7 downto 0); --y变量寄存器
BEGIN
PROCESS(clk,start)
VARIABLE count : INTEGER:=0;
VARIABLE Flag : INTEGER:=0; --计算完成标志,等于1时计算完成,终止计算进程,将结果持续输出
BEGIN
IF(clk'EVENT and clk = '1')THEN
IF(start = '1')THEN
IF(Flag = 0)THEN
IF(count = 9) THEN --count= 9时,完成8次累加后将结果寄存于tem,ok置1
count := 0;
tem <= p;
Flag := 1;
ELSIF(count = 0) THEN --count = 0时,赋初值
p(15 downto 0) <= "0000000000000000";
y_reg <= y;
t(7 downto 0)<= x(7 downto 0);
t(15 downto 8)<="00000000";
count := 1;
ELSE --count在1~8时,移位累加
IF (y_reg(0) = '1') THEN
p <= p + t;
ELSE p <= p;
END IF;
y_reg(6 downto 0)<=y_reg(7 downto 1); --y_reg右移一位
y_reg(7) <= '0';
t(15 downto 1) <= t(14 downto 0); --t左移一位
t(0) <= '0';
count := count + 1;
END IF;
ELSIF (Flag = 1) THEN
result <= tem;
END IF;
ELSIF(start = '0')THEN
result <= "0000000000000000";
Flag:= 0;
END IF;
END IF;
END PROCESS;
END BEHAVIOR;