crazybird

【原创】generate你会用吗?

0
阅读(2450)

在我们的FPGA设计中,常常会对某些信号进行多级的缓存或进行多级类似的操作,如果不采取适当的技巧,就会是我们的设计代码变得冗余、不好维护。本博文提出的generate将可以解决这个问题。为了更加直观表现出使用generate的好处,接下来给出使用generate前后的代码描述。该设计实现的功能对信号dina进行20个时钟周期的延时以及对信号dinb进行25个时钟周期的延时。没有使用generate时的Verilog HDL描述如下所示:

`timescale 1ns / 1ps
/*******************************************************
Author       :  CrazyBird
Filename     :  delay_tap.v
Data         :  2015-4-26
Description  :  delay of signal 
********************************************************/
module delay_tap(
    sys_clk,
    rst_n,
    dina,
    dinb,
    douta,
    doutb
    );
    //  parameter define
    parameter   DELAY_TAP20 = 20;
    parameter   DELAY_TAP25 = 25;
    
    //  input/output define
    input               sys_clk;
    input               rst_n;
    input               dina;
    input               dinb;
    output              douta;
    output              doutb;
    
    //  delay 20 clock period of dina
    reg     [DELAY_TAP20-1:0]   dina_buf;
    
    always @(posedge sys_clk or negedge rst_n)
    begin
        if(rst_n==1'b0)
            dina_buf <= {(DELAY_TAP20){1'b0}};
        else
        begin
            dina_buf[ 0] <= dina;
            dina_buf[ 1] <= dina_buf[ 0];
            dina_buf[ 2] <= dina_buf[ 1];
            dina_buf[ 3] <= dina_buf[ 2];
            dina_buf[ 4] <= dina_buf[ 3];
            dina_buf[ 5] <= dina_buf[ 4];
            dina_buf[ 6] <= dina_buf[ 5];
            dina_buf[ 7] <= dina_buf[ 6];
            dina_buf[ 8] <= dina_buf[ 7];
            dina_buf[ 9] <= dina_buf[ 8];
            dina_buf[10] <= dina_buf[ 9];
            dina_buf[11] <= dina_buf[10];
            dina_buf[12] <= dina_buf[11];
            dina_buf[13] <= dina_buf[12];
            dina_buf[14] <= dina_buf[13];
            dina_buf[15] <= dina_buf[14];
            dina_buf[16] <= dina_buf[15];
            dina_buf[17] <= dina_buf[16];
            dina_buf[18] <= dina_buf[17];
            dina_buf[19] <= dina_buf[18];
        end
    end
    
    assign  douta = dina_buf[DELAY_TAP20-1];
    
    //  delay 25 clock period of dina
    reg     [DELAY_TAP25-1:0]   dinb_buf;
    
    always @(posedge sys_clk or negedge rst_n)
    begin
        if(rst_n==1'b0)
            dinb_buf <= {(DELAY_TAP25){1'b0}};
        else
        begin
            dinb_buf[ 0] <= dinb;
            dinb_buf[ 1] <= dinb_buf[ 0];
            dinb_buf[ 2] <= dinb_buf[ 1];
            dinb_buf[ 3] <= dinb_buf[ 2];
            dinb_buf[ 4] <= dinb_buf[ 3];
            dinb_buf[ 5] <= dinb_buf[ 4];
            dinb_buf[ 6] <= dinb_buf[ 5];
            dinb_buf[ 7] <= dinb_buf[ 6];
            dinb_buf[ 8] <= dinb_buf[ 7];
            dinb_buf[ 9] <= dinb_buf[ 8];
            dinb_buf[10] <= dinb_buf[ 9];
            dinb_buf[11] <= dinb_buf[10];
            dinb_buf[12] <= dinb_buf[11];
            dinb_buf[13] <= dinb_buf[12];
            dinb_buf[14] <= dinb_buf[13];
            dinb_buf[15] <= dinb_buf[14];
            dinb_buf[16] <= dinb_buf[15];
            dinb_buf[17] <= dinb_buf[16];
            dinb_buf[18] <= dinb_buf[17];
            dinb_buf[19] <= dinb_buf[18];
            dinb_buf[20] <= dinb_buf[19];
            dinb_buf[21] <= dinb_buf[20];
            dinb_buf[22] <= dinb_buf[21];
            dinb_buf[23] <= dinb_buf[22];
            dinb_buf[24] <= dinb_buf[23];
        end
    end
    
    assign  doutb = dinb_buf[DELAY_TAP25-1];

endmodule

如果当延时周期改变了,我们要对该设计修改的地方包括参数定义以及always过程块的内容,要是稍微复杂一点的大工程,代码量将非常多且很不好维护。接下来,看看generate是如何解决这些问题的,相应Verilog HDL描述如下所示:

`timescale 1ns / 1ps
/*******************************************************
Author       :  CrazyBird
Filename     :  delay_tap1.v
Data         :  2015-4-26
Description  :  delay of signal 
********************************************************/
module delay_tap1(
    sys_clk,
    rst_n,
    dina,
    dinb,
    douta,
    doutb
    );
    //  parameter define
    parameter   DELAY_TAP20 = 20;
    parameter   DELAY_TAP25 = 25;
    
    //  input/output define
    input               sys_clk;
    input               rst_n;
    input               dina;
    input               dinb;
    output              douta;
    output              doutb;
    
    //  delay 20 clock period of dina
    wire    [DELAY_TAP20:0]     dina_buf;
    genvar                      i;
    
    assign  dina_buf[0] = dina;
    
    generate
        for(i=0;i<=DELAY_TAP20-1;i=i+1)
        begin  
            always @(posedge sys_clk or negedge rst_n)    
                if(rst_n==1'b0)    
                    dina_buf[i+1] <= 1'b0;
                else
                    dina_buf[i+1] <= dina_buf[i];
        end 
    endgenerate
    
    assign douta = dina_buf[DELAY_TAP20];
    
    //  delay 25 clock period of dina
    wire    [DELAY_TAP25:0]     dinb_buf;
    genvar                      j;
    
    assign dinb_buf[0] = dinb;
    
    generate
        for(j=0;j<=DELAY_TAP25-1;j=j+1)
        begin  
            always @(posedge sys_clk or negedge rst_n)    
                if(rst_n==1'b0)    
                    dinb_buf[j+1] <= 1'b0;
                else
                    dinb_buf[j+1] <= dinb_buf[j];
        end 
    endgenerate
    
    assign doutb = dinb_buf[DELAY_TAP25];

endmodule

代码量是不是减少了很多,在大工程中它的优势将更加突出。另外,如果在本设计中改变延时周期,只需修改参数定义就行了,有没有感觉设计变得容易维护了?

总结:在设计中正确使用generate,一方面可使代码量变得简洁清晰,另一方面可使设计更加容易维护。