打印
[VHDL]

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

[复制链接]
5381|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 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
非常不错啊

:)

使用特权

评论回复
5
GoldSunMonkey| | 2013-7-31 20:38 | 只看该作者
:)

使用特权

评论回复
6
llf021421| | 2013-8-1 20:39 | 只看该作者
不错!我正在自学FPGA,谢谢分享

使用特权

评论回复
7
mhanchen|  楼主 | 2013-8-1 21:03 | 只看该作者
llf021421 发表于 2013-8-1 20:39
不错!我正在自学FPGA,谢谢分享

:)

使用特权

评论回复
8
liu294826423| | 2013-9-9 19:47 | 只看该作者
谢谢楼主,

使用特权

评论回复
9
GoldSunMonkey| | 2013-9-9 19:55 | 只看该作者
mhanchen 发表于 2013-8-1 21:03

你笑什么呢?

使用特权

评论回复
10
GoldSunMonkey| | 2013-9-9 19:56 | 只看该作者
llf021421 发表于 2013-8-1 20:39
不错!我正在自学FPGA,谢谢分享

欢迎常来啊

使用特权

评论回复
11
sfofyyy| | 2014-11-18 23:18 | 只看该作者
学习

使用特权

评论回复
12
xdh1009| | 2014-12-18 14:44 | 只看该作者
学习@@@

使用特权

评论回复
13
EDAbuffalo| | 2015-1-6 23:35 | 只看该作者
实际写的过程中还真这么写过 找了一阵子 早点看到就好了

使用特权

评论回复
14
chenzhi658| | 2015-1-9 15:59 | 只看该作者
GoldSunMonkey 发表于 2013-7-30 23:49
感谢你的分享

猴哥,这里的第二种方法,与第一种建立的逻辑应该是一样的吗?有什么不好的地方吗?我对于有些信号的优先等级,经常使用第二种方法。

使用特权

评论回复
15
admiration123| | 2015-9-25 09:16 | 只看该作者
不错,如果能详细讲下原因就更好了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

30

主题

252

帖子

2

粉丝