八位二进制乘法器VHDL

八位二进制乘法器VHDL

  • 工程文件
    • 一、 实验目的
    • 二、设计要求
    • 三、实验仪器与环境
    • 四、实现原理
    • 五、系统设计及仿真
    • 六、顶层设计:
    • 七、结果仿真:
    • 附录:

工程文件

点击下载八位二进制乘法器工程文件

一、 实验目的

  1. 熟习Quartus Ⅱ软件的使用。
  2. 掌握原理图输入法和硬件描述语言**(VHDL)**方法来设计逻辑电路。
  3. 对设计电路作硬件验证。展示;

二、设计要求

  1. 用移位相加的方法设计一个乘法器,实现八位二进制的乘法
  2. 考虑数据输入口的数量不足16位,实现分拍置数的功能

三、实验仪器与环境

  1. 芯片:EP4CE1022C8
  2. 编程与仿真环境:Quartus Ⅱ 13.1
  3. 输入输出验证平台:西安电子科技大学数电试验箱

四、实现原理

(一)二进制数的乘法
如下图(4.1.1)所示,这两种数制的乘法都是把被乘数和乘数的每一位分别相乘,然后将得到的乘积根据所乘的乘数的位数进行移位,比如,在十进制数乘法中,如果将被乘数与乘数的个位相乘,那就把得到的乘积向左移动0位;如果被乘数与乘数的十位相乘,那就把得到的乘积向左移动1位…移位操作完成后,最后将这些移位后的乘积相加,就是最开始这两个被乘数与乘数的结果。
我们都知道,在二进制数中,只有数字0和1。在二进制数乘法中,如果与被乘数相乘的乘数的某一位为1,那结果就是被乘数本身,如果乘数的某一位为0,那此次的结果就是0。因此,二进制数乘法过程中的数次相乘,其实使用与门实现的。
八位二进制乘法器VHDL_第1张图片图4.4.1
(二)分拍输入原理
两个8位二进制数相加需要16个输入引脚,但实验板空间有限,只好一次只输入一个8位二进制数,分两拍输入到上述的乘法器主体中。
通过设计置数端完成节拍的掌控,第一个数输入完毕后置数端置一,若置数成功,则第一个灯亮起。第二个数置数完毕后,再将置数端置一。若置数成功,则第二个灯亮起。此时输入模块同时输出两个乘数。

五、系统设计及仿真

(一)乘法器主体模块(mulity_8bit)
八位二进制乘法器VHDL_第2张图片

图(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×001010100000110×00000011
八位二进制乘法器VHDL_第3张图片
图(5.1.2)
(二)分拍输入模块(inp)
八位二进制乘法器VHDL_第4张图片
图(5.2.1)
该模块共有4个输入端,4个输出端,其中clk为1kHz时钟信号,num端为8位二进数输入端,set为置数端,clear为清零端。x,y为8位二进数输出端。ok_x,ok_y为置数成功显示端。
分拍输入有寄存器实现,通过检测set的次数给X,Y赋值。使用流程如下:

  1. num的引脚置高低电平
  2. set置1,Led_x亮起,set置0。
  3. num的引脚置第二个数
  4. set置1,Led_y亮起,set置0。置数完成。
  5. clear恢复初始状态。
  6. 重复1~5步骤进行第二组输入。
    仿真实现上述步骤,如图(5.2.2):
    八位二进制乘法器VHDL_第5张图片
    如图(5.2.2)

六、顶层设计:

八位二进制乘法器VHDL_第6张图片
图(6.1.1)

七、结果仿真:

软件仿真:八位二进制乘法器VHDL_第7张图片
图(7.1.1)
硬件测试:
【1】选择对应芯片:
八位二进制乘法器VHDL_第8张图片
图(7.2.1)
【2】无用管脚选三态:
八位二进制乘法器VHDL_第9张图片
图(7.2.2)
【3】分配管脚:
八位二进制乘法器VHDL_第10张图片

图(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记录为1IF(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;

你可能感兴趣的:(EDA,vhdl,fpga,芯片)