VHDL语法入门 (七) 包集和元件

包集和元件

元件(component),函数(function)以及过程(procedure)等部分的使用往往是为了实现常用代码的共享。这些代码一般都被放在包集(package),然后编译到目标库文件(library)中。设计者可以将自己设计的一些常用代码段添加到library中,有利于使一个复杂设计具有更加清晰的结构。

包集

除了component,function和procedure之外,package中还包括类型(type)和常量(constant)的定义

--格式
PACKAGE package_name is
    (declaration)
end package_name;
[package body package_name id
    (function和procedure描述)
end package_name;]

上面语法结构中主要包含两个部分:package和package body。第一部分是必须的,包括声明语句。如果第一部分中有一个或多个function或procedure声明,那么在package body中一定要存在对于的描述代码。package和package body的名称必须相同。

package的声明部分包括以下内容:元件,函数,过程,类型和常量说明等

library ieee;
use ieee.std_logic_1164.all;

package my_package is
    type state is(st1,st2,st3,st4);
    type color is(red,green,blue);
    constant vec: std_logic_vector(7 downto 0) := "11111111";
    function positive_edge(signal s: std_logic)return boolean;
end my_package;

package body my_package is
    function positive_edge(signal s: std_logic)return boolean is
    begin
        return(s'event and clk = '1');
    end positive_edge;
end my_package;


--调用上面的package时,需要进行如下声明
library ieee;
use work.my_package.all;

元件

一个元件(component)是一段结构完整的常用代码(包括库声明,实体和结构体这些基本组成部分)。然而,如果将这些代码声明为component,就可以被其他电路调用,从而使代码具有层次化的结构。

--元件的声明
component component_name is
    port(
        port_name: signal_mode signal_type;    
        port_name: signal_mode signal_type;    
        ...
    );
end component;


--元件实例化
label: component_name port map (port_list);

component和entity的声明格式一样,必须指出端口名称以及端口模式(in,out,buffer或inout)以及数据类型(std_logic_vector,interger和boolean等)。为了实例化元件,在元件名和端口映射声明的前面还需要加入一个符号。端口列表将元件预定义的端口和实例化时的端口关联起来。

声明一个元件有两种基本方法。一旦将元件设计完成并放到目标库中,就可以采用下图所示方法进行声明

 此外还可以使用包集的方式进行声明,可以避免每次元件实例化时都需要重复声明。

 下面将分别通过这两种方法实现如图所示电路结构

-------------------在主代码中声明元件------------------------
--------file inverter.vhd--------
library ieee;
use ieee.std_logic_1164.all;

entity inverter is
    port (a: in std_logic;
          b: out std_logic
        );
end inverter;

architecture inverter of inverter is
begin
    b <= not a;
end inverter

--------file nand_2.vhd--------
library ieee;
use ieee.std_logic_1164.all;

entity nand_2 is
    port (a,b: in std_logic;
          c: out std_logic
        );
end nand_2;

architecture nand_2 of nand_2 is
begin
    c <= not (a and b);
end and_2;

--------file nand_3.vhd--------
library ieee;
use ieee.std_logic_1164.all;

entity nand_3 is
    port (a,b,c: in std_logic;
          d: out std_logic
        );
end nand_3;

architecture nand_3 of nand_3 is
begin
    d <= not (a and b and c);
end and_3;

--------file project.vhd--------
library ieee;
use ieee.std_logic_1164.all;

entity project is
    port(a,b,c,d: in std_logic;
         x,y: out std_logic
         );
 end project;
 
 architecture structural of project is
     component inverter is
         port(a: in std_logic; b: out std_logic);
     end component;
     component nand_2 is
         port(a,b: in std_logic; c: out std_logic);
     end component;
     component nand_3 is
         port(a,b,c: in std_logic; d: out std_logic);
     end component;
     signal w: std_logic;
 begin
     u1: inverter port map(b,w);
     u2: nand_2 port map(a,b,x);
     u3: nand_3 port map(a,b,c,y);
 end structure;
 
 
 
 -------------------在包集中声明元件------------------------
 --------file inverter.vhd--------
library ieee;
use ieee.std_logic_1164.all;

entity inverter is
    port (a: in std_logic;
          b: out std_logic
        );
end inverter;

architecture inverter of inverter is
begin
    b <= not a;
end inverter

--------file nand_2.vhd--------
library ieee;
use ieee.std_logic_1164.all;

entity nand_2 is
    port (a,b: in std_logic;
          c: out std_logic
        );
end nand_2;

architecture nand_2 of nand_2 is
begin
    c <= not (a and b);
end and_2;

--------file nand_3.vhd--------
library ieee;
use ieee.std_logic_1164.all;

entity nand_3 is
    port (a,b,c: in std_logic;
          d: out std_logic
        );
end nand_3;

architecture nand_3 of nand_3 is
begin
    d <= not (a and b and c);
end and_3;

--------file nand_3.vhd--------
library ieee;
use ieee.std_logic_1164.all;

package my_component is
    component inverter is
        port(a: in std_logic; b: out std_logic);
    end component
    component nand_2 is
        port(a,b: in std_logic; c: out std_logic);
    end component
    component nand_3 is
        port(a,b,c: in std_logic; d: out std_logic);
    end component
end my_component;

--------file project.vhd--------
library ieee;
use ieee.std_logic_1164.all;
use work.my_components.all;

entity project is
    port(a,b,c,d: in std_logic;
         x,y: out std_logic
         );
 end project;
 
 architecture structural of project is
     signal w: std_logic;
 begin
     u1: inverter port map(b,w);
     u2: nand_2 port map(a,b,x);
     u3: nand_3 port map(a,b,c,y);
 end structure;

端口映射

对端口的映射有位置映射和名称映射两种方式。位置映射书写比较简单,但名称映射的方法不容易出错。对于不需要使用的端口可以使用关键词OPEN断开

--位置映射
component inverter is
    port(a: in std_logic; b: out std_logic);
end component;
...
u1: inverter port map(x,y);    --此处x,y对应a,b

--名称映射
u1: inverter port map(x => a, y => b);

--使用open断开映射
u2:my_circuit port map(x => a, y => b, w => open, z =>d);

generic参数的映射

如果元件实例化需要通过generic传递参数,那么一定需要进行generic参数的映射。此时,元件实例化的格式需要进行如下更新:

label: compon_name generic map(param.list)port map(port list);

实例

1.奇偶效验器

下面的代码实现一个通用奇偶效验产生器,当输入矢量中‘1’的数量位偶数时,在输入矢量中插入一个‘0’,当输入矢量中‘1’的个数为奇数时,则插入一个‘1’,从而使输出矢量中始终包含偶数个‘1’

 这段代码通用性较强,因为输入矢量的宽度n使generic参数,可以取任意整数。

-------------这一部分是对电路的描述,后面作为包集调用------------------
library ieee;
use ieee.std_logic_1164.all;

entity parity_gen is
    generic (n: integer := 7);    --默认矢量宽度为7,该值会在后面实例化时被覆盖
    port (input: in bit_vector(n downto 0);
          output: out bit_vector(n_1 downto 0));
end parity_gen;
  
architecture parity of parity_gen is
begin
    process(input)
        variable temp1: bit;
        variable temp2: bit_vector(output'range);
    begin
        temp1 := '0';
        for i in input'range loop
            temp1 := temp1 xor input(i);
            temp2(i) := input(i);
        end loop;
        temp2 (output'high) := temp1;
        output <= temp2;
    end process;
end parity;

-------------这一部分是对电路的引用------------------
library ieee;
use ieee.std_logic_1164.all;

entity my_code is
    generic(n: positive := 2);    --这里的2在实例化前面的电路时会覆盖默认值7
    port (inp: in bit_vector(n downto 0);
          outp: out bit_vector(n+1 downto 0));
end my_code;

architecture my_arch of my_code is
    component parity_gen is
        generic(n: positive);
        port (input: in bit_vector(n downto 0);
              output: out bit_vector(n+1 downto 0));
    end component;
begin
    c1: parity_gen genric map (n) port map (inp,outp);
end my_arch;

2.算术逻辑单元

下面代码实现了通过元件实例化设计ALU(算术逻辑单元),在这个例子中,假设文件中包含了构建ALU的3个元件:逻辑单元,算术单元和多路选择器

-------------arith_unit component------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity arith_unit is
    port(a,b: in std_logic_vector(7 downto 0 )
          sel: in std_logic_vector(2 downto 0)
          cin: in std_logic;
          x: out std_logic_vector(7 downto 0));
end arith_unit;

architecture arith_unit of arith_unit is
    signal arith, logic: std_logic_vector(7 downto 0);
begin
    with sel select
        x <= a when "000",
             a+1 when "001",
             a-1 when "010",
             b when "011",
             b+1 when "100",
             b-1 when "101",
             a+b when "110",
             a+b+cin when others;
end arith_unit;

-------------logic_unit component------------------
library ieee;
use ieee.std_logic_1164.all;

entity logic_unit is
    port(a,b: in std_logic_vector(7 downto 0);
         sel: in std_logic_vector(2 downto 0);
         x: out std_logic_vector(7 downto 0));
end logic_unit;

architecture logic_unit of logic_unit is
begin
    with sel secect
        x <= not a when "000",
             not b when "001",
             a and b when "010",
             a or b when "011",
             a nand b when "100",
             a nor b when "101",
             a xor b when " 110",
             not(a nxor b) when others;
end logic_unit;

-------------mux component------------------
library ieee;
use ieee.std_logic_1164.all;

entity mux is
    port(a, b: in std_logic_vector(7 downto 0);
         sel: in std_logic;
         x:out std_logic_vector(7 downto 0));
end mux;

architecture mux of mux is
begin
    with sel select
        x <= a when '0'
             b when others;
end mux;

-------------main code------------------
library ieee;
use ieee.std_logic_1164.all;

entity alu is
    port(a, b: in std_logic_vector(7 downto 0);
         cin: in std_logic;
         sel: in std_logic_vector(3 downto 0);
         y: out std_logic_vector(7 downto 0));
end alu;

architecture alu of alu is 
    component arith_unit is
        port (a, b: in std_logic_vector(7 downto 0);
              cin: in std_logic;
              sel: in std_logic_vector(2 downto 0);
              x: out std_logic_vector(7 downto 0));
    end component;
    component logic_unit is
        port(a,b: in std_logic_vector(7 downto 0);
             sel: in std_logic_vector(2 downto 0);
             x: out std_logic_vector(7 downto 0));
    end component;
    component mux is
        port(a,b: in std_logic_vector(7 downto 0);
             sel: in std_logic;
             x: out std_logic_vector(7 downto 0));
    end component;
    signal x1, x2: std_logic_vector(7 downto 0);
begin
    u1: arith_unit port map(a,b,cin,sel(2downto 0),x1);
    u2: logic_unit port map(a,b,sel(2 downto 0),x2);
    u3: mux port map(x1,x2,sel(3),y);
end alu;

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值