分析Verilog版的step模块的原理图

来源:互联网 发布:美即面膜知乎 编辑:程序博客网 时间:2024/05/02 08:28
2009/3/8

Verilog版的step模块

      昨天一位大哥来我们实验室玩。我对他抱怨说VHDL的语法太烦人了,大哥说那就用Verilog啊,我说可是学院派的人都用VHDL,我不好太标新立异。

      大哥语重心长的说,在基督教初期,不受罗马政府的欢迎,但最后不还是成为罗马的国教了吗……

      我明白了大哥的心意,立刻就去找了本夏宇闻的Verilog教程。

      中午看了看,然后进行了简单的实践,把《在FPGA里做FIR》中提到的Step模块用Verilog描述了。

      文中关于step模块的描述如下:

……

      FIR模块的复位端需要输入一个上升沿,才能使它工作起来。连接此端我想需要一个这样的模块:
      系统启动时,模块输出低电平,往模块里输入若干个周期的时钟信号后,模块输出高电平,从此不再变化,除非对模块进行复位。
      Quartus II里一定有实现这样功能的模块,但是初次接触FPGA和Quartus,对其提供了哪些资源不了解,为了能够尽快开始对FIR模块的测试,就用VHDL编写了一个符合要求的模块。

      这样想,做一个计数器,将计时器的输出用一些门组合起来构成一个信号(假设为信号A),使计数器输出某一个特定的数值(假设为数值C)时使这个信号为低电平(其它时刻输出高电平),将这个信号与时钟信号一同输入到一个二输入的与门,与门的输出(假设为信号B)接到计数器的计数输入端。一开始,信号A输出高电平,时钟信号通过与门,输入到计数器的输入端,当计数器计到某一个特定的数值时,信号A输出低电平,使得时钟信号无法通过与门,计数停止。模块只要把信号A经过一个非门就可得到想要的输出。

……

      使用同样的思路,我试着写了下面的Verilog代码:

module stepv(clk,stopnum,reset,s);
    input clk;
    input [3:0] stopnum;
    input reset;
    output s;
    reg [3:0] count=4'b0000;
    always @ (posedge clk)
    begin
        if (reset == 1)
            count<=4'b0000;
        else
            if (count<stopnum)
                count<=count+1;
            else
                count<=stopnum;
    end
    assign s=(count==stopnum) ? 1:0;
endmodule

      仿真,得到的结果符合我的要求

 

 

2009/3/12

分析Verilog版的step模块的原理图

      记得去年夏初,我问sandygreta同学,使用硬件描述语言编写的可综合的程序,能够看到其对应的原理图吗?他不清楚。今天晚上我在Quartus II里发现了我想要的功能,名为RTL viewer的工具。它可以展现硬件描述语言编写的电路对应的原理图。

      研究原理图,大概类似于研究高级语言编译之后生成的汇编代码。也许了解了硬件描述语言程序中语句与硬件的对应关系,就能写出更好的代码。

      分析了一个功能简单的电路,是我自己用Verilog写的,关于它的详细描述,参见《Verilog版的step模块》 。

      程序的全部代码如下:

module stepv(clk,stopnum,reset,s);
    input clk;
    input [3:0] stopnum;
    input reset;
    output s;
    reg [3:0] count=4'b0000;
    always @ (posedge clk)
    begin
        if (reset == 1)
            count<=4'b0000;
        else
            if (count<stopnum)
                count<=count+1;
            else
                count<=stopnum;
    end
    assign s=(count==stopnum) ? 1:0;
endmodule

      下面是这段代码生成的原理图(点击查看大图):

 

      程序中定义的reg型变量count在图中对应名为count[3..0]的4bit的D触发器元件。
      看always块,该块由clk的上升沿触发。原理图中看出,clk与count[3..0]的ENA相连。当clk上升沿到来时,count[3..0]就会锁存数据选择器count~[7..4]的输出。
      always中首先是一个"if (reset==1)...else",这个if生成了原理图中的数据选择器count[7..4],当reset输入1时,选择DATAB作为输出,即输出0000。这对应了代码:
        if (reset == 1)
            count<=4'b0000;
      而该数据选择器输入端DATAA所连接的电路则对应了else后面的代码:
        else
            if (count<stopnum)
                count<=count+1;
            else
                count<=stopnum;
      这个else里面又有一个if:if(count<stopnum)...else...。同样,这个if也对应生成了一个数据选择器,即原理图中的count~[3..0]。因为if的条件是一个不等式,所以数据选择器的SEL端接的是一个比较器LessThan0,其名字的含义并不是小于0的意思,而是“比较器,ID为0”。通过这个比较器操纵数据选择器count~[3..0],就使得当D触发器count[3..0]存储的值小于stopnum[3..0]时,让数据选择器输出由if(count<stopnum)后面的代码(count<=count+1)生成的电路产生的数据;否则,让数据选择器输出由else后面的代码(count<=stopnum)生成的电路产生的数据。
      count<=count+1生成了一个加法器Add0,这个加法器的输入端一端接D触发器的输出,另一端接1,当数据选择器选通了这一路数据(即条件reset!=1和count<stopnum满足)时,D触发器count[3..0]存储的值与1相加,结果存入count[3..0],实现了count<=count+1的功能。
      count<=stopnum,当数据选择器选择了此路信号时,stopnum端的数据就会从D端输入到count[3..0]中,存储,并从Q端输出。
      程序的最后一句:
    assign s=(count==stopnum) ? 1:0;
      生成了电路中名为Equal0的元件。该元件实现了对D触发器count[3..0]的Q端输出和stopnum的比较,若相等,则输出1到s端口,否则输出0。
      总结一下,如果程序中利用if...else...结构来控制某一信号的取值,就会生成MUX21:二选一的数据选择器,该MUX的SEL端所连接的电路由if后面的条件生成,如果比较大小,会生成数值比较器与SEL端相连,如果比较相不相等,我想大概会生成Equal吧。三目运算符?:,利用它给1bit信号赋值时,大约会根据条件,生成数值比较器或者Equal或者等等,如果是给多bit信号赋值,我想还是生成数据选择器MUX21吧。

 

原创粉丝点击