VHDL实现 4-16编码器

编程设计

RTL文件(.vhdl):

将使用if和case的两种方式分别用两个architecture,使用configration选择

此部分的编程还有更多种更规范的方法,日后再更新

library ieee;
use ieee.std_logic_1164.all;
entity decoder4_16 is
    port(   a,b,c,d:in std_logic;
            -- q:out integer range 0 to 15);
            q:out std_logic_vector(15 downto 0));
end entity decoder4_16;

architecture art1 of decoder4_16 is
    signal insignal:std_logic_vector(3 downto 0);
    begin
    insignal <= a & b & c & d;
    process (insignal) is
    begin
        case insignal is
            when "0000" => q <= "1111111111111110";  -- (0=>'1',others=>'0')
            when "0001" => q <= "1111111111111101";
            when "0010" => q <= "1111111111111011";
            when "0011" => q <= "1111111111110111";
            when "0100" => q <= "1111111111101111";
            when "0101" => q <= "1111111111011111";
            when "0110" => q <= "1111111110111111";
            when "0111" => q <= "1111111101111111";
            when "1000" => q <= "1111111011111111";
            when "1001" => q <= "1111110111111111";
            when "1010" => q <= "1111101111111111";
            when "1011" => q <= "1111011111111111";
            when "1100" => q <= "1110111111111111";
            when "1101" => q <= "1101111111111111";
            when "1110" => q <= "1011111111111111";
            when "1111" => q <= "0111111111111111";--不能加_,bitvector的才可以加
            when others => q <= "XXXXXXXXXXXXXXXX";--必须是大写
        end case;
    end process;
end architecture art1;

architecture art2 of decoder4_16 is
    signal insignal:std_logic_vector(3 downto 0);
    begin
    insignal <= a & b & c & d;
    process (insignal) is
    begin
        if(insignal = "0000")        then   q <= "1111111111111110";
        elsif(insignal = "0001")    then    q <= "1111111111111101"; 
        elsif(insignal = "0010")    then    q <= "1111111111111011";
        elsif(insignal = "0011")    then    q <= "1111111111110111"; 
        elsif(insignal = "0100")    then    q <= "1111111111101111"; 
        elsif(insignal = "0101")    then    q <= "1111111111011111"; 
        elsif(insignal = "0110")    then    q <= "1111111110111111"; 
        elsif(insignal = "0111")    then    q <= "1111111101111111"; 
        elsif(insignal = "1000")    then    q <= "1111111011111111"; 
        elsif(insignal = "1001")    then    q <= "1111110111111111"; 
        elsif(insignal = "1010")    then    q <= "1111101111111111"; 
        elsif(insignal = "1011")    then    q <= "1111011111111111"; 
        elsif(insignal = "1100")    then    q <= "1110111111111111"; 
        elsif(insignal = "1101")    then    q <= "1101111111111111"; 
        elsif(insignal = "1110")    then    q <= "1011111111111111"; 
        elsif(insignal = "1111")    then    q <= "0111111111111111"; 
        else                                q <= "XXXXXXXXXXXXXXXX";  
        end if;
    end process;
end architecture art2;

-- configuration cfg1 of decoder4_16 is
--     for art1
--     end for;
-- end configuration cfg1;

configuration cfg2 of decoder4_16 is
    for art2
    end for;
end configuration cfg2;

综合之后的RTL视图如下:
下面首先是使用case语句生成的RTL电路:右侧为放大图
(Quartus 13.1版本的RTL比13.0等版本可能看起来要复杂一些)
在这里插入图片描述在这里插入图片描述

接下来是使用if语句生成的RTL电路:
在这里插入图片描述

可以看出使用case语句的要简便的多,原因可能是综合的时候,case语句不考虑优先级,是综合成了无优先级的MUX,但是if语句是被综合成一个优先级的结构。
if和case语句的综合

激励文件(testbench)(.vhdl):

每40ns对输入的4位(a,b,c,d)生成0或1的随机数,查看输出的波形是否与预设相符。

之前只写过Verilog的tb,没写过VHDL的,所以在写的时候遇到的问题记录一下。
比较好的博客:用vhdl写testbench文件的简单方法
VHDL TestBench基础
VHDL与Verilog硬件描述语言TestBench的编写

library ieee;
use ieee.std_logic_1164.all;
use ieee.math_real.uniform;

entity tb_decoder4_16 is 
end entity tb_decoder4_16;

--内容全都写在architecture中    
architecture art_tb_decoder4_16 of tb_decoder4_16 is
    component decoder4_16 is    --被测试的元件
        port(   a,b,c,d : in    std_logic;
                q       : out   std_logic_vector(15 downto 0)
            );
    end component;
    --信号定义
    signal a : std_logic := '0';
    signal b : std_logic := '0';
    signal c : std_logic := '0';
    signal d : std_logic := '0';
    signal q : std_logic_vector(15 downto 0) := "0000000000000000";
    --变量定义--用于生成随机数
    
begin
    DUT: decoder4_16        --例化元件, 名称为DUT,时序仿真时注意名称,把NA改成DUT
        port map(
            a   =>  a,
            b   =>  b,
            c   =>  c,
            d   =>  d,
            q   =>  q
        );
    -- process (a,b,c,d) is     --有wait语句,不再使用带敏感信号的process
    process  is
    variable seed1, seed2 : positive := 1;
    variable re           : real;
    begin       --随机数
         for i in 0 to 10 loop
            --a
            uniform(seed1, seed2, re);
            if (re < 0.5) then
                a <= '0';
            else
                a <= '1';
            end if;
            -- b 
            uniform(seed1, seed2, re);
            if (re < 0.5) then
                b <= '0';
            else
                b <= '1';
            end if;
            --c
            uniform(seed1, seed2, re);
            if (re < 0.5) then
                c <= '0';
            else
                c <= '1';
            end if;
            --d
            uniform(seed1, seed2, re);
            if (re < 0.5) then
                d <= '0';
            else
                d <= '1';
            end if;  
        wait for 40 ns;--数字和后面的单位要加空格
        end loop ; -- identifier
        
    end process;

end art_tb_decoder4_16;

仿真:

仿真使用Quartus II 与 Modelsim 联和仿真,仿真时间500ns

功能仿真(前仿真):

在这里插入图片描述在这里插入图片描述
可以看到,此时输入输出之间没有延时;

时序仿真(后仿真):

之前没有做过时序仿真,其实时序仿真就是需要几个设置,不需要编写sdf文件,是静态时序分析才需要编写SDF文件。直接综合,加布线,生成的网表就会带有延迟信息。
在这里插入图片描述
在这里插入图片描述
要设置为off才可以
最后,仿真时modelsim报错,找不到NA,,发现是例化名字不对。
关于Quartus+Modelsim 门级仿真 Warning (vopt-2216) Cannot find instance ‘NA’ specified in sdf.的解决办法

在这里插入图片描述
在这里插入图片描述
可以看到时序仿真之后,当输入发生跳变之后,输出信号确实存在延迟,并且信号稳定前存在竞争冒险。
(下面是用if语句的方式,延时略有不同)
在这里插入图片描述

在这里插入图片描述
刚开始还会有一段不定态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值