• 重拾VHDL和Verilog系列(一)——VHDL编写结构


    已经有几年没有接触过VDHL或者Verilog了,在大二时,对VHDL是如此的热爱,疯狂得不用看仿真只通过看代码就能知道问题所在,在那一年,我喜欢FPGA,喜欢了VHDL。

    就在那一年,老师给我的项目失败了,可能是自己技术不到家(那时连SDRAM工作原理还不懂,却说要用VHDL实现SDRAM读写,当年还是有很多东西不了解,也没有自己的一套学习方法),为了不让老师失望,我决意转向ARM,从此,我与FPGA、VHDL失去了交集,渐渐地,我把VHDL遗忘了。。。。。

    其中在那一年,虽然主攻VHDL,但对Verilog也有作过少许学习(毕竟Verilog学习资料多),只是随着时间的推移,Verilog与VHDL的转换已成为过去。

    今年,我又有机会与VHDL产生交集,其实是我主动向上司要求,我想研究FPGA、VHDL,可以减轻团队的压力。

    好了,费话了一堆。现在的我又要从头开始捡起VHDL了。

     

    VHDL中的库文件包含:

    在VHDL中,少不了一些标准库,如:std_logic这类声明,都是来源于ieee这个库的。

    library ieee;
    use ieee.std_logic_1164.all;

     

    VHDL中实体声明:

    和高级语言一样,VHDL也要声明,这时有点不同的是,这种声明是用于对外的接口,即输入/输出都在这里声明的。

    entity CRC_Unit is
    port(
          iBitVal : in std_logic;
          iClock : in std_logic;
          iClear : in std_logic;
          oCRC : out std_logic_vector(4 downto 0)
    );
    end CRC_Unit;

     

    VHDL结构功能:

    有了对外的接口外,还得有内部的处理,这样才能算是一个整体。architecture 就是对实体的内部功能的描述。

    architecture ClacCRC of CRC_Unit is
    signal inv : std_logic;
    signal CRC : std_logic_vector(4 downto 0);
    
    begin
    
    inv <= iBitVal xor CRC(4);
    
    process(iClock,iClear)
    begin
          if iClear = '1' then
                CRC <= (others =>'0');
          elsif falling_edge(iClock) then
                CRC(4) <= CRC(3);
                CRC(3) <= CRC(2) xor inv;
                CRC(2) <= CRC(1);
                CRC(1) <= CRC(0) xor inv;
                CRC(0) <= inv;
          end if;
    end process;
    
    oCRC <= CRC;
    
    end ClacCRC;

    到此,就把VHDL的结构简述完毕。

    别急,我还没有说完,下面还会对各个部分进行分析。由于代码已经在上文给出,下文将不会再重复代码。

    VHDL中的库

    VHDL中的库有哪些?

    std_logic_1164
    std_logic_arith
    std_logic_unsigned
    std_logic_signed

    除了系统自带的库外,自己也可以编写自己的,编写格式如下:

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_arith.all;
    use ieee.std_logic_unsigned.all;
    
    package PackageName is 
    
    component Component1 is 
        PORT
        (    
              ...
        );
    end component;
    
    component Component2 is 
        PORT
        (    
             ...
        );
    end component; 
    
    end package;

    格式和写一个普通的VHDL文件差不多,不同的是,这个没有实体,也没有结构,只有包(component后面将描述)。

    VHDL如何使用库?

    库可以分为二大类,一类是系统自带的标准库,另一类的用户自己编写的,两种类调用方式不太一样。

    上面代码讲到如何调用库,如果使用标准库,一般如下:

    library ieee;     --表示使用什么库
    use ieee.std_logic_1164.all;    --表示使用库中的具体的库

    其中std_logic_1164是在ieee库中的,一般情况下,上而两行代码是必需的。

    如果使用的是用户自编写库,就要:

    use work.PackageName.all;  --work表示当前工作目录

    使用用户自编写的库看起来就简单多了,只要使用use就可以了,值得注意的是,work是指当前工作目录,而PackageName就是包的名字,前面的讲述到。

    VHDL中的实体

    VHDL中的实体就简单多了,主要是对引脚(或接口)的输入、输出或者双向作定义。

    其中port();中的为对外引脚。

    引脚分三种:

    输入使用关键字:in

    输出使用关键字:out

    双向使用关键字:inout

    对不同引脚要定义具体类型,引脚常用只有两种类型,一种是单点引脚,一种是多点引脚。(单点、多点引脚是我的说法,不一定正常,但能表示其意思)

    单点引脚使用:std_logic

    多点引脚使用:std_logic_vertor(x downto 0)

    有点类似普通变量和数组变量,一个表示单线、一个表示集合了多条单线(类似总线)。

    注:在port();中,最后一个引脚不要加分号!

     

     

    VHDL中的architecture

    在architecture中且在begin前声明

    1、信号。信号如其名,就是传递信号用的。

    2、组件(component),组件就是其他已经写好的VHDL,组件只是把其引脚复述一遍,用于后期数据处理。

    architecture XXX of XXX_Unit is
    signal One:std_logic;    --声明信号
    
    component Component1 is  --声明组件
        port
        (    
              ...  --具体一个实体的引脚
        );
    end component;
    
    begin
         ...
    end XXX;

    组件是将一个已经写好的VHDL模块(实现某一功能的VHDL文件) ,加入本VHDL中的方式,但加入还不够,还要使用port map,下文将描述。

    在architecture中且在begin后

    在begin后常用的有语句不多,主要有if...else...end if,if...elsif...elsif...end if,process,port map等(这些语句能实现大部分逻辑)。

    architecture XXX of XXX_Unit is
    
    component CRC_Unit is
    port(
          iBitVal : in std_logic;
          iClock : in std_logic;
          iClear : in std_logic;
          oCRC : out std_logic_vector(4 downto 0)
    );
    end component;
    
    signal bitVal : std_logic;
    signal clock  : std_logic;
    signal clr    : std_logic;
    signal crc    : std_logic_vector(4 downto 0);
    
    begin
    
        oOut <= One;
    
        process(rst)      --敏感信号列表
        begin
             if rst = '0' then
               ...
             elsif
               ...
             end if;
        end process;
    
       u1:CRC_Unit port map(iBitVal => bitVal ,iClock => clock ,iClear => clr ,oCRC =>crc);
    end XXX;

    在VHDL中,只要在architecture中的语句都会被同时执行,但process一点特别,同时执行的是整个process,而不是process里面的各行语句。process其实更像是一个块,一个对外同时执行,对内顺序执行的一个单元。

    在process的括号中的rst,被称为敏感信号列表,只要放在这括号中的数据发生变化,就会同时执行期间触发process内部操作。即oOut <= One、process及port map同时执行。

     port map是将原来component进architecture的组件进行使用,port map 后,会将对应的信号输入或输出。

    VHDL architecture中的变量

    变量需要声明在process中,而且只能在process中被赋值,被调用。变量声明在process中begin前。

    process(rst)
    variable val : integer ;
    begin
          val := 10;
    end process;

    VHDL architecture中的赋值 

    VHDL中有两种赋值方式,一种是直接赋值,一种是延时赋值。还有一种不太像赋值,而是像指向的方式,port map (符号是"=>"),这里不把此方式当作赋值。

    直接赋值:(赋值符号为":=" )

    variable 就是直接的代表,当赋值后,左值将等于右值。

    延时赋值:(赋值符号为"<=“ )

    所有信号、引脚被赋值都是延时赋值。那什么是延时赋值?个人认为可以与实际电路理解(虽然不知是否正确)。信号可以看成一条线(引脚也是),当我在线的右端给出高电平的瞬间,左端的电平还没有变化,因为从右到左需要一定的时间(那时间是光速),所以在同一周期作出了操作,但信号的值还没有来得及改变,所以出现了延时赋值。

    在VHDL中只有两种赋值操作,如果想和高级语言一样使用"="一般会出错,因为在VHDL中"="是比较操作。

    总结:

    由于边幅太长不利浏览,因此对VHDL、Verilog将以一个系列来讲述。局限于本人技术有限,可能上文会有表达不通,或者表达不清的情况,如果有看不懂的,或者找出错处的,欢迎大家提出。

     

  • 相关阅读:
    从内存中加载并启动一个exe
    使用Hamcrest增强JUnit的测试能力
    Delphi编译指令说明
    Delphi 64与32位的差异
    获取exe文件窗口抓图,将memo转化为JPG输出
    Delphi 的 Utf-8 转换
    我的第一个破解软件,试验成功!
    Qt之QComboBox(基本应用、代理设置)
    常见寄存器以及常见汇编指令,常见爆破指令 good
    大神级回答exists与in的区别
  • 原文地址:https://www.cnblogs.com/bakasen/p/2647799.html
Copyright © 2020-2023  润新知