VHDL实现4_16译码器

编程设计RTL文件(.vhdl):激励文件(testbench)(.vhdl):

仿真:功能仿真(前仿真):时序仿真(后仿真):

编程设计

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的编写

过程中需要生成随机数,但是查了很久,才用例程改的 在 vhdl 中生成随机整数要让赋值语句循环执行多次,所以使用loop语句,循环,然后用wait决定多少次换一次值 VHDL 的延迟语句

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语句的方式,延时略有不同)

刚开始还会有一段不定态。

查看原文