原创 【博客大赛】还在为学习枯燥的VHDL而烦恼吗?为何不结合Quartus一起学习

2013-11-6 13:52 2694 16 25 分类: FPGA/CPLD 文集: HDL

        我们通过一个小小的例子来学习VHDL程序设计,同时温习Quartus II工程开发,一举两得。 这个小小的例子最小目标就是要告诉大家怎么使用IF-THEN语句,另一方面通过这个小小的实例告诉大家好的coding就是对设计最大的优化。

IF-THEN是VHDL中典型的行为描述(Behavioral Descriptions)语句,并在进程(Process)中按顺序执行。IF-THEN语句多级嵌套即IF-ELSIF则产生更为复杂的输出逻辑,这些输出又都是互斥关系。同时,IF-ELSIF还将会比IF-THEN使用更多的逻辑资源而且会使得布局布线更加困难。问题在于如何未使用ELSIF的情况下有条件地测试这些互斥信号呢?答案是使用IF-THEN语句。以下代码是我们的测试目标:

 

以下是代码片段:

LIBRARY ieee;

USE ieee.std_logic_1164.ALL;

 

ENTITY if_thn IS

    PORT

        (

            current_state   :   IN      std_logic_vector(8 DOWNTO 0);

            x,y,z           :   IN      std_logic;

            state_out       :   OUT     std_logic_vector(2 DOWNTO 0)

        );

END if_thn;

 

ARCHITECTURE behavior OF if_thn IS

 

CONSTANT s0 :   std_logic_vector(8 DOWNTO 0) := "000000000";

CONSTANT s1 :   std_logic_vector(8 DOWNTO 0) := "100000001";

CONSTANT s2 :   std_logic_vector(8 DOWNTO 0) := "100000010";

CONSTANT s3 :   std_logic_vector(8 DOWNTO 0) := "100000100";

CONSTANT s4 :   std_logic_vector(8 DOWNTO 0) := "100001000";

CONSTANT s5 :   std_logic_vector(8 DOWNTO 0) := "100010000";

CONSTANT s6 :   std_logic_vector(8 DOWNTO 0) := "100100000";

CONSTANT s7 :   std_logic_vector(8 DOWNTO 0) := "101000000";

CONSTANT s8 :   std_logic_vector(8 DOWNTO 0) := "110000000";

 

SIGNAL output1 :   std_logic;

SIGNAL output2 :   std_logic;

SIGNAL output3 :   std_logic;

 

BEGIN

 

PROCESS(current_state,x,y,z)

BEGIN

    IF (current_state = s1) OR (current_state = s3) OR (current_state = s4) THEN

        output1 <= x;

    ELSIF (current_state = s0) OR (current_state = s2) OR (current_state = s5) THEN

        output2 <= y;

    ELSIF (current_state = s6) OR (current_state = s7) OR (current_state = s8) THEN

        output3 <= z;

    ELSE

        output1 <= '0';

        output2 <= '0';

        output3 <= '0';

    END IF;

END PROCESS;

 

    state_out <= output1 & output2 & output3;

   

END behavior;


        下面我们创建一个新的Quartus II工程,打开Quaruts II软件,从File菜单选择New Project Wizard,如图1所示。

11.jpg
图1:新建Quartus II工程

 

第一步:设置工作路径,如图1所示,大家可以在自己的电脑上选择一个没有空格和中文字符的路径作为自己的工作路径。我们为这个新创建的工程命名为if_thn,软件自动为顶层设计实体命名为if_thn。点击Next进入下一步。

第二步:如图2所示,将上述代码保存到一个名为if_thn.vhd的文件里。器件家族选择Cyclone II,并将该源最好放到工作目录下,当然大家以后项目复杂以后可以专门建立一个存放源文件的目录,笔者喜欢在工程目录下创建一个src作为存放所有源文件的目录,创建一个debug目录用于存放虚拟JTAG调试工具以及调试数据的目录。闲话少说,浏览找到源文件,点击Add按钮将源文件加入到工程,点击Next进入下一步。

11.jpg

图2:给工程添加设计文件

第三步:如图3所示,器件型号选择笔者demo板上的EP2C5Q208C8,剩下的设置默认即可,点击Finish按钮完成Quartus II工程创建。

11.jpg

图3:为工程指定设计目标器件

在Quartus II菜单Process里的Start中选择综合命令,或者直接软件工具条中选择综合命令按钮 11.jpg

对刚刚创建的工程进行综合。综合后可以在软件的编译报告中看到几个警告信息(蓝色信息为警告),如图4所示,同时我们从编译报告中了解到整个设计共消耗了19个逻辑单元。
11.jpg

图4:IF语句综合出Latch的警告

          我们可以通过RTL Viewer来进一步检查这些警告信息,从Quartus II软件的Tools菜单下Netlist Viewers里选择RTL Viewer命令,即可打开RTL Viewer来查看刚才的综合结果。如图5所示,我们看到三个输出是各自经过一个Latch出来的,后面笔者在介绍时性分析以及优化的时候,会告诉大家编译后意外产生的这些不受欢迎的锁存器会使得设计的时序分析复杂化,而且也不能精确反映设计者脑子里的本领设计意图。

11.jpg

图5:使用RTL Viewer查看工程综合结果

       关闭RTL Viewer,下面我使用另外一个网表查看工具再来看看上述综合结果,即从刚才打开RTL Viewer的菜单里我们选择打开Technolgy Map Viewer,如图6所示。

11.jpg

 图6:使用Technology Map Viewer查看工程综合结果

图6所示的Technology Map Viewer显示了工程实际的逻辑实现,也即前面代码中的IF-THEN语句的实际逻辑实现。我们可以看到最后三个输出经过了最后一级的三个LCELL,注意这三个LCELL的输出除了驱动设计中的三个输出意外,这三个LCELL的输出同时还反馈到LCELL的输入。后面我们将讨论这种没有必要的反馈走线会使得设计变得意想不到的复杂,应该在coding的时候加以避免。

          既然我们已经发现了代码中的这些问题,那么下面我就通过修改代码来解决这些问题。将上述代码源文件另存为if_thn2.vhd。将原代码里使用单个IF-ELSIF语句修改为使用多个IF-THEN语句,同时修改程序的实体名字,使之和文件名字保持一致。修改后的代码如下所示。

 

LIBRARY ieee;

USE ieee.std_logic_1164.ALL;

 

ENTITY if_thn2 IS

    PORT

        (

            current_state   :   IN      std_logic_vector(8 DOWNTO 0);

            x,y,z           :   IN      std_logic;

            state_out       :   OUT     std_logic_vector(2 DOWNTO 0)

        );

END if_thn2;

 

ARCHITECTURE behavior OF if_thn2 IS

 

CONSTANT s0 :   std_logic_vector(8 DOWNTO 0) := "000000000";

CONSTANT s1 :   std_logic_vector(8 DOWNTO 0) := "100000001";

CONSTANT s2 :   std_logic_vector(8 DOWNTO 0) := "100000010";

CONSTANT s3 :   std_logic_vector(8 DOWNTO 0) := "100000100";

CONSTANT s4 :   std_logic_vector(8 DOWNTO 0) := "100001000";

CONSTANT s5 :   std_logic_vector(8 DOWNTO 0) := "100010000";

CONSTANT s6 :   std_logic_vector(8 DOWNTO 0) := "100100000";

CONSTANT s7 :   std_logic_vector(8 DOWNTO 0) := "101000000";

CONSTANT s8 :   std_logic_vector(8 DOWNTO 0) := "110000000";

 

SIGNAL output1 :   std_logic;

SIGNAL output2 :   std_logic;

SIGNAL output3 :   std_logic;

 

BEGIN

 

PROCESS(current_state,x,y,z)

BEGIN

    IF (current_state=s1) OR (current_state=s3) OR (current_state=s4) THEN

            output1 <= x;

    ELSE

            output1 <= '0';

    END IF;

    IF (current_state=s0) OR (current_state =s2) OR (current_state=s5) THEN

            output2 <= y;

    ELSE

            output2 <= '0';

    END IF;

    IF (current_state=s6) OR (current_state =s7) OR (current_state=s8) THEN

            output3 <= z;

    ELSE

            output3 <= '0';

    END IF;

    END PROCESS;

 

    state_out <= output1 & output2 & output3;

   

END behavior;


 

源文件修改后,将其加入到工程中,具体方法可以通过settings里加入文件到工程的方法,也可以直接在工程导航(Project Navigator)下的Files页面通过右击鼠标弹出的Add/Remove Files in Project…命令来添加文件到工程或者从工程中删除文件。如图7所示。

11.jpg

 图7:网工程添加文件或从工程删除文件

文件添加到工程以后,if_thn2.vhd会出现在图7所示的Files列表里,鼠标右击该文件,选择Set as Top-Level Entity命令将其设置为工程的顶层实体。最后,对工程进行重新综合。查看编译报告,这次只消耗了9个逻辑单元,而且没有任何蓝色的警告信息。

启动RTL Viewer查看重新综合结果,如图8所示。可以看到RTL直观显示了修改后的代码只有简单的9个Equation,看不到后面的锁存器。

11.jpg

 图8:使用RTL Viewer查看工程修改后综合结果

关闭RTL Viewer,我们再次启动Technology Map Viewer,如图9所示。可以看到工程实际逻辑实现消耗的9个LCELL,而且和图2-15比较,我们看到最后三个驱动输出引脚的LCELL的输出没有任何反馈到其输入的逻辑路径。

11.jpg

 图9:使用Technology Map Viewer查看工程修改后综合结果

    所以通过比较我们可以得出一个结论是IF-ELSE-END IF语句除了避免不受欢迎的意外产生的锁存器意外,还可以更有效的利用逻辑。

 

 

 

 

 

 

 

 

 

PARTNER CONTENT

文章评论9条评论)

登录后参与讨论

coyoo 2013-7-22 15:18

呵呵,惶恐啊!!!

用户403664 2013-7-22 14:53

Altera官方微博都转发了你这篇博文 http://e.weibo.com/1069456721/A1cO4CCmG

用户377235 2013-7-18 13:03

output3 <= '0'; state_out <= output1 & output2 & output3; 感觉这个地方是不是应该用 |运算,结果貌似为0

用户413652 2013-7-17 21:11

蛮详细的,支持下!

coyoo 2013-7-9 19:54

还行吧!!呵呵

用户403664 2013-7-9 17:01

对!还可以吧?

coyoo 2013-7-9 16:17

我用了一下,是这样吗?名字似乎叫“代码样式”。

用户403664 2013-7-9 15:39

高级编辑器有一个“插入代码”的选项

coyoo 2013-7-9 12:35

突然发现不知道如何插入代码啊!有这个功能吗?

用户305823 2010-10-29 15:47

来捧下场
相关推荐阅读
coyoo 2024-12-25 14:13
ALTERA Cyclone 10器件的使用-8:特定的上电顺序
概述 Intel 要求用户为其10代FPGA器件使用特定的上电和掉电顺序,这就要求用户在进行FPGA硬件设计的时候必须选择恰当的FPGA供电方案,并合理控制完整的供电上电顺序。经过在Cyclone 1...
coyoo 2024-12-22 11:46
AD9218子板在新处理板上表现的问题
概述 新的数据处理板融合了数字和数据处理功能模块,计划采用ADI的4通道串行ADC芯片代替之前的并行ADC。由于初次使用,所以初次设计时预留了AD9218的子板的插槽。 在调试AD9633功能的同时并...
coyoo 2024-12-14 17:15
在Cyclone 10 GX器件上实现高精度TDC探索
概述 Cyclone 10 GX器件的ALM结构与Cyclone V类似,所以在Cyclone 10 GX器件上实现TDC功能理论上是可以完全参考甚至移植自Cyclone V系列的成功案例。但是,现实...
coyoo 2024-12-10 13:28
Cyclone V GX FPGA设计TDC的优化问题
概述 通过前面的研究学习,已经可以在CycloneVGX器件中成功实现完整的TDC(或者说完整的TDL,即延时线),测试结果也比较满足,解决了超大BIN尺寸以及大量0尺寸BIN的问题,但是还是存在一些...
coyoo 2024-12-03 12:20
比较器检测模拟脉冲说明(四)
概述 说明(三)探讨的是比较器一般带有滞回(Hysteresis)功能,为了解决输入信号转换速率不够的问题。前文还提到,即便使能滞回(Hysteresis)功能,还是无法解决SiPM读出测试系统需要解...
coyoo 2024-11-16 13:54
不同ADC采样同一前端模拟信号时转换用时差异分析
概述 同一组前端模拟信号接入由不同型号ADC组成的模数转换电路时,采样后在FPGA中发现采样用时差异较大。本文主要分析这个时间差异形成的原因,并记录该差异产生对系统造成的影响。系统数字化简介 项目前端...
EE直播间
更多
我要评论
9
16
关闭 站长推荐上一条 /3 下一条