编程设计
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语句的方式,延时略有不同)
刚开始还会有一段不定态。