基于Active-HDL的HDL设计录入与仿真

在这里插入图片描述
作者:毛茏玮 / Saint
掘金:https://juejin.im/user/5aa1f89b6fb9a028bb18966a
微博:https://weibo.com/5458277467/profile?topnav=1&wvr=6&is_all=1
GitHub:github.com/saint-000
CSDN: https://me.csdn.net/qq_40531974

基于Active-HDL的HDL设计录入与仿真

一、前言:
Active-HDL是围绕共同核心的HDL模拟器所构建的FPGA开发环境。支持基于文本和图形设计输入和调试工具,允许混合语言仿真(VHDL/ Verilog/ EDIF/ SystemC/ SystemVerilog),并提供统一的接口以及各种合成和实施工具。我们通过对选择器,加法器,三八译码器,优先编码器,计数器,分频器上述六种设计录入和调试得到输出波形图。

二、目的:
通过在Active-HDL上编写代码,熟悉Active-HDL的代码录入方式,温习并掌握VHDL源程序的语法结构,在通过对不同功能模块的设计过程中,了解每种设计它所需要的输入激励,输入波形需要加的恰当适宜,这样可以方便我们在示波器上观察输出波形是否正确。

三、内容:
选择器,加法器,三八译码器,优先编码器,计数器,分频器的VHDL代码录入及波形仿真。

四、平台(设备、元器件):
①软件Active-HDL9.2 ②Windows操作系统

五、(1)选择器
步骤:
1.打开Active-HDL9.2,页面会跳出提示框,可以选择之前建立好的文件打开,也可以创建新的设计文件,这里我们对选择器进行创建新的设计,故点击Create new workspace,然后设置Workspace name为 mux4。
在这里插入图片描述
在这里插入图片描述
2. 创建一个空的设计,添加一些基本信息,输入设计文件名,此处输入study3。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.在软件中点击File,选择New然后点击创建VHDL Source,对设计模型的实体,构造体进行命名,命名为 mux4,此处四选一数据选择器的构造体填RTL,我们采用寄存器传输级描述。
在这里插入图片描述

在这里插入图片描述

4.在描述端口的时候输入输出应用不同的端口方向,比如四选一数据选择器中,6个端口是输入,1个端口是输出,同时我们此处的端口也d0-3可用数组表示:d[3:0]。
在这里插入图片描述

在这里插入图片描述
5.完成了端口设定软件会自动生成好基本的代码框架,我们在此基础上进行程序的编写。

library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity mux4 is
	port(
		d0 : in STD_LOGIC;
		d1 : in STD_LOGIC;
		d2 : in STD_LOGIC;
		d3 : in STD_LOGIC;
		s0 : in STD_LOGIC;
		s1 : in STD_LOGIC;
		y : out STD_LOGIC
		);
end mux4;
--}} End of automatically maintained section
architecture rtl of mux4 is
begin
process(d0,d1,d2,d3,s0,s1)
begin
if s1='0' and s0='0'THEN
y<=d0;
elsif s1='0' and s0='1'THEN
y<=d1;
elsif s1='1' and s0='0'THEN
y<=d2;
elsif s1='1' and s0='1'THEN
y<=d3;
else
y<='Z';
end if;
end process;
end rtl;

6.把完成的代码进行编译,编译好的文件出现子项,其对应于文件中的实体和构造体,我们将出现的子项设为顶层,其目的是优先进行仿真,有时候多项目在同一个工作环境中,我们需选定优先仿真对象,然后进行仿真。
在这里插入图片描述
在这里插入图片描述
7.将待测信号加载到波形窗口,然后对各项输入信号设定波形信号,加仿真激励的方式只要有三种:图形化界面手动加激励;编写宏文件加激励;编写测平台加激励。在本次实验中主要是用图形化界面手动加激励的方式,在设定波形窗口发现,一共有7种图形化加激励方式,常用的是时钟类型,公式类型,数值类型。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
8.对于四选一数据选择器,我们将d0的激励设恒为1,将d1的激励设恒为0,d2和d3的波形任意给出,设定s0和s1的波形使形成的波形可以实现00-11,具体波形及结果如下:
在这里插入图片描述

9.在状态栏点击仿真按键对待测信号进行仿真测试。
在这里插入图片描述

六、(1)选择器:四选一数据选择器
数据及结果分析:
对于四选一数据选择器而言,我们的目标在于改变s0,s1的值可以有四种不同的变化即对应四路数据,我们在波形图上可以发现s1,s0为00,01,10,11分别输出的是不同的波形,我们将每一段输出y的值与d0-3相对比可验证实现了四路数选功能。
在这里插入图片描述
六、(2)加法器
实验步骤:
1.打开Active-HDL9.2,页面会跳出提示框,可以选择之前建立好的文件打开,也可以创建新的设计文件,这里我们对选择器进行创建新的设计,故点击Create new workspace,然后设置Workspace name为half_adder。(加法器我们这里以半加器为例)
2.创建一个空的设计,添加一些基本信息,输入设计文件名。
3.在描述端口处设置a,b为输入,co,s为输出。
在这里插入图片描述
在这里插入图片描述
4.在软件中点击File,选择New然后点击创建VHDL Source,对设计模型的实体,构造体进行命名,命名为half_adder,此处半加器的构造体填RTL,我们采用寄存器传输级描述。
5.完成了端口设定软件会自动生成好基本的代码框架,我们在此基础上进行程序的编写。
代码如下:

library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity half_adder is
	port(
		a : in STD_LOGIC;
		b : in STD_LOGIC;
		s : out STD_LOGIC;
		co : out STD_LOGIC
		);
end half_adder;
architecture rtl of half_adder is
SIGNAL c,d:STD_LOGIC; 
begin	
	c<=a or b;
	d<=a nand b;
	co<=not d;
	s<=c and d;
		
end rtl;

在这里插入图片描述
6.把完成的代码进行编译,然后进行仿真,仿真前加入如下激励方便观察波形。

七、(2)加法器:半加器
数据及结果分析:
对于半加器而言,我们的目标在于将ab相加,用s来表示两数之和,用co来表示二进制的加法是否进位,若进位则co为1,无进位co为0;我们将每一段输出的s,co的值与a+b相对比可验证实现了半加器加法功能。
在这里插入图片描述

六、(3)三八译码器
步骤:
1.前期的创建新的工作区不在重述,我们设置Workspace name为decoder。(三八译码器器为例)
2.创建一个空的设计,添加一些基本信息,输入设计文件名,在描述端口处设置a,b,c,g1,g2a,g2b为输入,y0-y7为输出。(可以设置数组形式表示输出)
在这里插入图片描述
3.在软件中点击File,选择New然后点击创建VHDL Source,对设计模型的实体,构造体进行命名,命名为decoder_3_to_8,此处三八译码器的构造体填RTL,我们采用寄存器传输级描述。
4.完成了端口设定软件会自动生成好基本的代码框架,我们在此基础上进行程序的编写。
代码如下:

library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity decoder_3_to_8 is
	 port(
		 a : in STD_LOGIC;
		 b : in STD_LOGIC;
		 c : in STD_LOGIC;
		 g1 : in STD_LOGIC;
		 g2a : in STD_LOGIC;
		 g2b : in STD_LOGIC;
		 Y : out STD_LOGIC_VECTOR(7 downto 0)
	     );
end decoder_3_to_8;
architecture rtl of decoder_3_to_8 is 
signal indata: STD_LOGIC_VECTOR(2 downto 0);
begin 
	indata<=c&b&a;
	process(indata,g1,g2a,g2b) 
	begin
IF(g1='1'AND g2a='0' AND g2b='0') THEN
		case indata is
		when "000"=>y<="11111110" ;	   
		when "001"=>y<="11111101" ;
		when "010"=>y<="11111011" ;
		when "011"=>y<="11110111" ;
		when "100"=>y<="11101111" ;
		when "101"=>y<="11011111" ;
		when "110"=>y<="10111111" ;
		when "111"=>y<="01111111" ;	 
		when others=>y<="11111111" ; 		
	end case ;
else
	y<="11111111";
end if;
end process;
end rtl;

5.把完成的代码进行编译,然后进行仿真。

七、(3)三八译码器
数据及结果分析:
对于三八译码器而言,我们要实现将3位2进制数通过电路转换成八路不同状态的输出,我们在波形图上可以将数值与下表数据相对比可验证实现了三八译码器译码输出功能。
在这里插入图片描述
在这里插入图片描述

此处仅列出前几个输入对应的输出波形,其余的情况我们可以根据规律同理得出。

六、(4)优先编码器
步骤:
1.创建新的工作区,我们设置Workspace name为 encoder_priority。(优先编码器为例)
2.创建一个空的设计,添加一些基本信息,输入设计文件名,在描述端口处设置input0-7为输入,y0-y2为输出。(可以设置数组形式表示输入和输出)
在这里插入图片描述
3.在软件中点击File,选择New然后点击创建VHDL Source,对设计模型的实体,构造体进行命名,命名为 encoder_priority,此处优先编码器的构造体填RTL,我们采用寄存器传输级描述。
4.完成了端口设定软件会自动生成好基本的代码框架,我们在此基础上进行程序的编写。
代码如下:

library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity encoder_priority is
	port(	
		input : in STD_LOGIC_VECTOR(7 downto 0);	
		y : out STD_LOGIC_VECTOR(2 downto 0)
		);
end encoder_priority;
architecture rtl of encoder_priority is
begin
	process(input)
	begin
	
if(input(0)='0')THEN
	y<="111";	
ELSIF(input(1)='0')THEN
	y<="110";	
ELSIF(input(2)='0')THEN
	y<="101";
ELSIF(input(3)='0')THEN
	y<="100";
ELSIF(input(4)='0')THEN
	y<="011";
ELSIF(input(5)='0')THEN
	y<="010";
ELSIF(input(6)='0')THEN
	y<="001";
else
	y<="000";	
	end if;
END PROCESS;
end rtl;

5.把完成的代码进行编译,然后进行仿真。

七、(4)优先编码器
数据及结果分析:
对于优先编码器而言,我们要实现同时在几个输入端有输入信号,编码器按输入信号排定的优先顺序,只对同时输入的几个信号中优先权最高的一个进行编码,我们在波形图上可以将数值与下表数据相对比可验证实现了三八译码器译码输出功能。

在这里插入图片描述
在这里插入图片描述
此处仅列出前几个输入对应的输出波形,其余的情况我们可以根据规律同理得出。我们容易发现input(7)为任意波形对输出结果不影响。

六、(5)计数器
步骤:
1.创建新的工作区,我们设置Workspace name为count10en。(四位二进制加‘1’同步计数器为例)
2.创建一个空的设计,添加一些基本信息,输入设计文件名,在描述端口处设置clr,clk,en为输入,q3-q1,full为输出。(可以设置数组形式表示输出)
在这里插入图片描述
3.在软件中点击File,选择New然后点击创建VHDL Source,对设计模型的实体,构造体进行命名,命名为 count10en,此处优先编码器的构造体填RTL,我们采用寄存器传输级描述。
4.完成了端口设定软件会自动生成好基本的代码框架,我们在此基础上进行程序的编写。
代码如下:

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE	IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY count10en IS
	 PORT(
		 clk : IN STD_LOGIC;
		 clr : IN STD_LOGIC;
		 en : IN STD_LOGIC;
		 full : OUT STD_LOGIC;
		 q : OUT STD_LOGIC_VECTOR(3 downto 0)
	     );
END count10en ; 
ARCHITECTURE rtl OF count10en IS
SIGNAL count_4:	STD_LOGIC_VECTOR(3 downto 0) ;
BEGIN
PROCESS(clk,clr)
BEGIN
	IF(clr='1')THEN
		count_4<="0000";
		full<='0';
ELSIF(clk'EVENT AND clk='1')THEN
	IF(en='1')THEN
		IF(count_4="1001")THEN
			count_4<="0000";
			full<='1';
		ELSE
			count_4<=count_4+'1';
			full<='0';
		END IF;
	END IF;
END IF;
END PROCESS;
q<=count_4 ;
END rtl ;

5.把完成的代码进行编译,然后进行仿真。

七、(5)计数器
数据及结果分析:
对于计数器而言,我们要实现在指定范围内等间隔计数,full是进位我们在波形图上可以直观的验证计数器从0计到8.
在这里插入图片描述
注意调节clk激励信号和总截止时间来更好的验证输出波形。
在这里插入图片描述

六、(6)分频器
步骤:
1.创建新的工作区,我们设置Workspace name为clk_div10 。(十分频器为例)
2.创建一个空的设计,添加一些基本信息,输入设计文件名,在描述端口处设置clk为输入,clk_div10为输出。
3.在软件中点击File,选择New然后点击创建VHDL Source,对设计模型的实体,构造体进行命名,命名为clk_div10,此处优先编码器的构造体填RTL,我们采用寄存器传输级描述。
4.完成了端口设定软件会自动生成好基本的代码框架,我们在此基础上进行程序的编写。
代码如下:

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity clk_div10 is
	 port(
		 clk : in STD_LOGIC;
		 clk_div10 : out STD_LOGIC
	     );
end clk_div10;
--}} End of automatically maintained section
architecture rtl of clk_div10 is
SIGNAL counter:STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL clk_temp:STD_LOGIC;
begin
	PROCESS(clk)
	begin
		if(clk'EVENT AND clk='1')THEN
			IF(counter="100")THEN
				counter<="000";
				clk_temp<=NOT clk_temp;
			ELSE
				counter<=counter+1;
			END IF;
		END IF;
	END PROCESS;
	clk_div10<=clk_temp;
end architecture rtl;

5.把完成的代码进行编译,然后进行仿真。

七、(6)分频器
数据及结果分析:
对于分频器而言,我们验证分频后信号输出一个周期时钟经历10个周期即达到十分频器的功能。
在这里插入图片描述

八、结论:
通过VHDL来描述硬件功能,我们需要在特定的框架下编程,对于不同功能的硬件,我们编写的方式也会有不同,编译成功后用示波器并加入激励信号进行软件虚拟波形仿真来验证模块的功能。

九、总结及心得体会:
(1)我们可以通过对一个模型的功能列出真值表,知道所需要的端口,主要是给出输出和输入,然后编写实体和结构体程序,在软件中编写程序相比其他编程环境更为人性化的是active具有编程语言助手功能,可以根据用户的自定义生成实体和构造体框架,大大减少人工录入代码的工作量。

(2)实验中我们主要定义的端口只是in和out,但事实上VHDL共定义了5种类型的端口,分别是In, Out,Inout, Buffer;

与Out端口比,Buffer端口具有回读功能,也即内部反馈,但在设计时最好不要使用buffer,因为buffer类型的端口不能连接到其他类型的端口上,无法把包含该类型端口的设计作为子模块元件例化,不利于大型设计和程序的可读性。若设计时需要实现某个输出的回读功能,可以通过增加中间信号作为缓冲,由该信号完成回读功能。

双向端口Inout比较特殊,即一个端口可以做输出,也可以做输入,在某些程序中同一个端口在不同的情况下作用会有不同,此时就会用到这种特定的端口。
在这里插入图片描述

(3)编写代码时,我们主要注意的是构造体核心部分代码,VHDL的编码支持大小写字母,然后布局软件有个缩进布局按键可以将代码以缩进式对齐,在布局的同时,对用户来说也有检查代码的好处,另外就是PROCESS,我们在编写代码时常用到的就是进程,我们知道进程内部是顺序执行的,进程之间是并行运行的;
VHDL中的所有并行语句都可以理解为特殊的进程,只是不以Process结构出现,其输入信号和判断信号就是隐含的敏感表。

(4)在仿真时,我们要注意加入激励的方式,加入合适的激励信号可以使我们更好的验证输出波形,如果是自定义波形的话,公式方式添加激励会方便一点,但是要注意的是,这只种方法加入的波形只能限定在周期内的两个变化值的输入,所以有一点局限,不过好在我们本次做的实验需要的激励都可以通过时钟方式,公式方式加激励仿真。
在这里插入图片描述
同时我们注意调试波形时的波形刷新和显示,我们更新波形时常用的两个键如下所示:
在这里插入图片描述

十二、改进建议:
(1)这里采用的主要的设计录入方式是HDL编辑器录入方式,我们还可以用框图录入方式,状态图录入方式。如果需要编程的硬件内部比较复杂的话,用图形输入方式,需要比较繁琐的转化,转化成基本原件的连线很耗时,若用文本输入的话,思路比较清晰,分析起来很简单。一般功能描述用文本输入法,逻辑描述用图形文件比较好,所以我觉得可以将本次实验中的分频器,优先编码器用框图录入方式去实现。
(2)分频器是十分频,我们的设计只能是针对十分频,这样就非常局限,因此我们可以编写一个数控N分频器,实际应用中更加的方便。
代码如下:

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity ndiv is
	port(
		clk : in STD_LOGIC;
		clr : in STD_LOGIC;
		clk_div : out STD_LOGIC
		);
end ndiv;
architecture rtl of ndiv is	
	SIGNAL counter:STD_LOGIC_VECTOR(7 DOWNTO 0);
	SIGNAL clk_temp:STD_LOGIC;	
begin
	process(clk,clr)
	begin
		if(clr='1')then
			counter<="00000001";
			clk_temp<='1';
		elsif(clk'EVENT AND clk='1')THEN
			IF(counter="1010")THEN
				counter<="00000001";
				clk_temp<='1';
			ELSE
				counter<=counter+1;
				clk_temp<='0';
			END IF;
		END IF;
	END PROCESS;
	clk_div<=clk_temp;	
end rtl;

我们可以在代码:IF(counter="1010")THEN中修改counter的数值,实现不同频次的分频器,例如:IF(counter="100")THEN中实现四分频器功能。
在这里插入图片描述
特别要注意的是:在实验中错误理解分频器的功能,一开始我以为分频器实现时钟信号每翻转十次,分频电路翻转一次,但实际上这种说法是错误的,对应的情况是特殊的输出波形,下图这种情况便属于这种情况,但实际上我们一眼可以看出来这个仿真是有问题的,所以针对分频器的功能,我们的正确理解是:N分频就是通过有分频作用的电路结构,在时钟每触发N个周期时,电路输出1个周期信号。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_40531974/article/details/85787806
HDL
今日推荐