crazybird

【原创】generate你会用吗?

0
阅读(2439)

在我们的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,一方面可使代码量变得简洁清晰,另一方面可使设计更加容易维护。

Baidu
map