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

2020-02-17 19:44发布

本帖最后由 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"并回零: 1.jpg 四、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",即计数值与代码中不符: 4.jpg

若将第二种写法中计数器加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语句的控制不起作用: 2-.jpg

若将第四种写法中计数器加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"开始: 4-.jpg
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
14条回答
chenzhi658
1楼-- · 2020-02-20 00:01
GoldSunMonkey 发表于 2013-7-30 23:49
感谢你的分享

猴哥,这里的第二种方法,与第一种建立的逻辑应该是一样的吗?有什么不好的地方吗?我对于有些信号的优先等级,经常使用第二种方法。
admiration123
2楼-- · 2020-02-20 02:50
 精彩回答 2  元偷偷看……

一周热门 更多>