[VHDL] 举例说明VHDL中关于变量和信号的赋值、if语句的描述方法

[复制链接]
 楼主| mhanchen 发表于 2013-7-30 17:35 | 显示全部楼层 |阅读模式
本帖最后由 mhanchen 于 2013-7-30 17:37 编辑

       所用例子实现功能很简单,2 bits的计数器循环计数,计到2后清零。在这里强烈推荐第一种写法,原因如下:在一个process(或者always)中不要描述并列语句,在控制信号增多或者计数器位数增加的情况下也会出现错误,而且综合后电路与各并列语句的描述顺序有很大关系,电路规模大时会影响综合器的工作效率,第二种和第四种写法就是典型的C风格,不符合HDL的代码风格而且容易出错(见最后两个例子)。第三种写法其实也不会出错,但是习惯的写法都是尽量用signal,这样会准确地综合出触发器。下面每个综合后的电路效果大家可以仿真一下或者按时钟节拍去分析各个触发器的输出。
       我用的综合工具是Synplify 2012.03,映射芯片是S6 LX9。
PS:以下例程对应到Verilog HDL将信号和变量赋值分别改为非阻塞和阻塞赋值可得到相同的综合结果。
一、
……
process(clk, rst)
begin
      if(rst = '1') then
           cnt <= (others => '0');
      elsif(clk'enent and clk = '1') then
           if(cnt = "10") then
                 cnt <= (others => '0');
           else
                 cnt <= cnt + '1';              
           end if;
      end if;
end process;
……
二、
……
process(clk,rst)   
begin
      if(rst = '1') then
           cnt <= (others => '0');
      elsif(clk'enent and clk = '1') then
           cnt <= cnt + '1';
           if(cnt = "10") then
                 cnt <= (others => '0');
           end if;
      end if;
end process;
……
三、
……
process(clk, rst)
variable cnt_reg :std_logic_vector(1 downto 0);
begin
      if(rst = '1') then
           cnt_reg := (others => '0');
      elsif(clk'enent and clk = '1') then
           if(cnt_reg = "10")then
                 cnt_reg := (others => '0');
           else
                 cnt_reg := cnt_reg + '1';            
           end if;
      end if;
      dout <= cnt_reg;
end process;
……
以上三种写法的综合后电路如下图,此时计数器可以正确计数到"10"并回零:
四、
process(clk, rst)
variable cnt_reg :std_logic_vector(1 downto 0);
begin
      if(rst = '1') then
           cnt_reg := (others => '0');
      elsif(clk'event and clk = '1') then
           cnt_reg := cnt_reg + '1';
           if(cnt_reg = "10") then
                 cnt_reg := (others => '0');
           end if;
      end if;
      dout <= cnt_reg;
end process;
第四种写法综合后电路图如下,此时计数器只能计数到"01",即计数值与代码中不符:


若将第二种写法中计数器加1的操作语句放到if条件判断之后,即:
process(clk, rst)   
begin
      if(rst = '1') then
           cnt <= (others => '0');
      elsif(clk'event and clk = '1') then
           if(cnt = "10") then
                 cnt <= (others => '0');
           end if;
           cnt <= cnt + '1';
      end if;
end process;
综合后电路图如下,此时计数器可以从0计到3if语句的控制不起作用:


若将第四种写法中计数器加1的操作语句放到if条件判断之后,即:
process(clk, rst)
variable cnt_reg :std_logic_vector(1 downto 0);
begin
      if(rst = '1') then
           cnt_reg := (others => '0');
      elsif(clk'event and clk = '1') then
           if(cnt_reg = "10") then
                 cnt_reg := (others => '0');
           end if;
           cnt_reg := cnt_reg + '1';
      end if;
      dout <= cnt_reg;
end process;
综合后电路图如下,此时计数器可以计到"10",但之后无法回零,而是从"01"开始:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

评分

参与人数 1威望 +10 收起 理由
GoldSunMonkey + 10 很给力!

查看全部评分

GoldSunMonkey 发表于 2013-7-30 23:49 | 显示全部楼层
感谢你的分享
GoldSunMonkey 发表于 2013-7-30 23:49 | 显示全部楼层
非常不错啊
 楼主| mhanchen 发表于 2013-7-31 18:43 | 显示全部楼层
GoldSunMonkey 发表于 2013-7-30 23:49
非常不错啊

:)
GoldSunMonkey 发表于 2013-7-31 20:38 | 显示全部楼层
llf021421 发表于 2013-8-1 20:39 | 显示全部楼层
不错!我正在自学FPGA,谢谢分享
 楼主| mhanchen 发表于 2013-8-1 21:03 | 显示全部楼层
llf021421 发表于 2013-8-1 20:39
不错!我正在自学FPGA,谢谢分享

:)
liu294826423 发表于 2013-9-9 19:47 | 显示全部楼层
谢谢楼主,
GoldSunMonkey 发表于 2013-9-9 19:55 | 显示全部楼层
mhanchen 发表于 2013-8-1 21:03

你笑什么呢?
GoldSunMonkey 发表于 2013-9-9 19:56 | 显示全部楼层
llf021421 发表于 2013-8-1 20:39
不错!我正在自学FPGA,谢谢分享

欢迎常来啊
sfofyyy 发表于 2014-11-18 23:18 | 显示全部楼层
学习
xdh1009 发表于 2014-12-18 14:44 | 显示全部楼层
学习@@@
EDAbuffalo 发表于 2015-1-6 23:35 | 显示全部楼层
实际写的过程中还真这么写过 找了一阵子 早点看到就好了
chenzhi658 发表于 2015-1-9 15:59 | 显示全部楼层
GoldSunMonkey 发表于 2013-7-30 23:49
感谢你的分享

猴哥,这里的第二种方法,与第一种建立的逻辑应该是一样的吗?有什么不好的地方吗?我对于有些信号的优先等级,经常使用第二种方法。
admiration123 发表于 2015-9-25 09:16 | 显示全部楼层
不错,如果能详细讲下原因就更好了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

30

主题

252

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部