美文网首页
常用器件的Verilog表示

常用器件的Verilog表示

作者: 萍水间人 | 来源:发表于2019-06-13 16:30 被阅读0次

    0x01原始加法器代码

    module ADDER8(CLK, SUM, A,B,COUT,CIN);
        input[7:0] A,B;
        input CLK,CIN;
    
        output COUT;
        output [7:0] SUM;
        reg COUT;
        reg[7:0] SUM;
    
        always @(posedge CLK)
        {COUT,SUM[7:0]} <= A+B+CIN;
    endmodule
    

    又是因为testbench的原因调试了好久才发现是漏了一个信号
    testbench如下:

    module ADDER8_tb();
    
        reg[7:0] A,B;
        reg CLK,CIN;
    
        wire COUT;
        wire[7:0] SUM;
    
        initial
        begin
            CLK = 1;
            A ='d1;
            B = 'd2;
            CIN = 1;
        end
    
        always #10 CLK = ~CLK;
    
        always #5 A = A + 1;
    
        always # 15 B = B + 1;
        ADDER8 a(
            .CLK(CLK),
            .SUM(SUM),
            .A(A),
            .B(B),
            .COUT(COUT),
            .CIN(CIN)
            );
    
    endmodule
    

    仿真波形图:


    只有在时钟上升沿的时候,送入的数据才会相加,当然这里比较神奇,因为A数据的变化和时钟是一摸一样的

    0x0x 加法器用流水线优化的代码

    module ADDER8(CLK,SUM,A,B,COUT,CIN);
        input[7:0] A,B;
        input CLK,CIN;
    
        output COUT;
        output[7:0] SUM;
        reg TC,COUT;
        reg[3:0] TS,TA,TB;
        reg[7:0] SUM;
    
        always @(posedge CLK)
        begin
            {TC,TS}<=A[3:0]+B[3:0]+CIN;
            SUM[3:0] <= TS;
        end
    
        always @(posedge CLK)
        begin
            TA <= A[7:4];
            TB <= B[7:4];
            {COUT, SUM[7:4]} <= TA+TB+TC;
        end
    endmodule
    

    用的是同一份testbench代码
    令人疑惑的是其中为什么在做第二次加法时,不是直接相加而是先将其非阻塞式赋值保存起来?
    当然书上也意识到了这一点,此时的波形图上会有直接的体现:

    由于采用了非阻塞式赋值,所以开始一段是没有东西的


    而且,整体往后移动了一段

    于是就会有这样的疑问了:
    我要是不用TA和TB保存呢?
    直接赋值会怎样呢
    由于之前的testbench存在一点问题
    于是换了一个,波形图如下:
    其中第一张是书上的


    这一张是修改的


    竟然没什么区别!

    这就很神奇了

    应该是好久没写代码了
    testbench调试了好久,全是低级错误

    0x03 异步加载计数器

    代码:

    
    module fiv1(CLK,PM,D,DOUT,RST);
    
        input CLK,RST;
        input[3:0] D;
    
        output PM;
        output[3:0] DOUT;
    
        reg[3:0] Q1;
        reg FULL;
        wire LD;
        always @(posedge CLK or posedge LD or negedge RST)
        if(!RST)
        begin
            Q1<=0;FULL<=0;
        end
        else if(LD)
        begin   Q1<=D;FULL<=1; end
        else begin
            Q1<=Q1+1;FULL<=0;
        end
    
        assign LD = (Q1==4'b0000);
        assign PM = FULL;
        assign DOUT = Q1;
    endmodule
    

    testbench

    module fiv1_tb();
    
        reg CLK,RST;
        reg[3:0] D;
        wire PM;
        wire[3:0] DOUT;
    
        initial
        begin
            CLK = 1;
            D=4'b1101;
            RST=1;
            # 20
            RST=0;
            # 5
            RST = 1;
        end
        always #10 CLK = ~CLK;
        
        fiv0 f(
            .CLK(CLK),
            .PM(PM),
            .D(D),
            .DOUT(DOUT),
            .RST(RST)
            );
    
    endmodule
    
    

    重点关注为什么是Q1==4'b0000的时候才产生进位信号

    Q1==4'b0000的结果 Q1==4'b1111的结果

    f被吃掉了

    0x04 同步加载计数器

    //同步加载计数器
    module fiv0(CLK,PM, D, DOUT, RST);
    
        input CLK, RST;
        input[3:0] D;
    
        output [3:0] DOUT;
        output PM;
    
        reg[3:0] Q1;
        reg FULL;
        wire LD;
    
        always @(posedge CLK or negedge RST)
        if(!RST)
        begin
            Q1<=0;FULL<=0;
        end
        else if(LD)
        begin
            Q1<=D;FULL<=1;
        end
        else 
        begin
            Q1<=Q1+1;
            FULL<=0;
        end
    
        assign LD = (Q1==4'b1111);
        assign DOUT = Q1;
        assign PM = FULL;
    
    endmodule
    

    惊奇的发现这样就可以了。。。


    Q1==4'b1111的结果

    教材上也没有解释为什么。。

    经典D触发器的Verilog表述

    module DEF1(CLK, D, Q);
        output Q;
        input CLK,D;
    
        reg Q;
        always @(posedge CLK)
        Q <= D;
    endmodule
    

    时钟上升沿到来时,对Q进行一次赋值(阻塞和非阻塞在这里失去了意义)

    RTL网表图

    为什么会有一个1'h0就很奇怪了

    异步复位和时钟使能的D触发器

    //异步复位和时钟使能的D触发器
    module DEF2(CLK,D, Q, RST, EN)
        output Q;
        input CLK, D, RST, EN;
    
        reg Q;
        always @(posedge CLK or negedge RST)
        begin
            if(!RST)
                Q <= 0;
            else if(EN)
                Q <= D;
        end
    
    endmodule
    

    时钟上升沿到来且使能信号有效则赋值,如果是复位信号的下降沿则直接清零

    这种设计实现了复位信号不受时钟信号的影响
    这里的异步及时指独立于时钟控制的复位控制端

    RTL网表图

    同步复位时钟的D触发器

    //同步复位时钟的D触发器
    module DEF3(CLK, D, Q, RST);
        output Q;
        input CLK,D,RST;
    
        reg Q;
        always @(posedge CLK)
        if(RST == 1)
            Q = 0;
        else if(RST == 0)
            Q = D;
    
    endmodule
    

    这里说的同步是指某控制信号只有在时钟信号有效时才起作用

    所以将RST信号的判断置于时钟的统一控制下

    RTL网表图

    另一种实现同步复位的方式

    module DEF4(CLK, D, Q, RST);
        output Q;
        input CLK, D, RST;
        reg Q, Q1;
        always @(RST)
        if(RST == 1)
            Q1 = 0;
        else 
            Q1 = D;
    
        always @(posedge CLK)
            Q <= Q1;
    endmodule
    
    RTL网表图

    相关文章

      网友评论

          本文标题:常用器件的Verilog表示

          本文链接:https://www.haomeiwen.com/subject/pjisfctx.html