verilog中generate的疑问
- `timescale 1ns/1ps
- `define TWO
- module top(
- clk
- ,rst_n
- ,din0
- ,din1
- ,din2
- ,din3
- ,dout0
- ,dout1
- ,dout2
- ,dout3
- );
- parameter N=4;
- input clk;
- input rst_n;
- input [3:0] din0;
- input [3:0] din1;
- input [3:0] din2;
- input [3:0] din3;
- output [3:0] dout0;
- output [3:0] dout1;
- output [3:0] dout2;
- output [3:0] dout3;
- `ifdef ONE
- generate
- genvar j;
-
- for(j=0;j<N;j=j+1) begin: fuck
-
- wire [3:0] din;
- wire [3:0] dout;
-
- gen gen(
- .clk (clk )
- ,.rst_n (rst_n)
- ,.din (din )
- ,.dout (dout )
- );
- end
- endgenerate
- assign fuck[0].din = din0;
- assign fuck[1].din = din1;
- assign fuck[2].din = din2;
- assign fuck[3].din = din3;
- assign dout0 = fuck[0].dout;
- assign dout1 = fuck[1].dout;
- assign dout2 = fuck[2].dout;
- assign dout3 = fuck[3].dout;
- `elsif TWO
- wire [4*N-1:0] din_w;
- wire [4*N-1:0] dout_w;
- generate
- genvar j;
-
- for(j=0;j<N;j=j+1) begin: fuck
- gen gen(
- .clk (clk )
- ,.rst_n (rst_n )
- ,.din (din_w[(j+1)*4-1 : j*4] )
- ,.dout (dout_w[(j+1)*4-1 : j*4])
- );
- end
- endgenerate
- assign din_w[3:0] = din0;
- assign din_w[7:4] = din1;
- assign din_w[11:8] = din2;
- assign din_w[15:12] = din3;
- assign dout0 = dout_w[3:0] ;
- assign dout1 = dout_w[7:4] ;
- assign dout2 = dout_w[11:8] ;
- assign dout3 = dout_w[15:12];
- `endif
- endmodule
- [code]`timescale 1ns/1ps
module gen(
clk
,rst_n
,din
,dout
);
//---------------------------------
// parameter
//---------------------------------
parameter PAR = 4'd1;
//---------------------------------
// Input and Output
//---------------------------------
input clk;
input rst_n;
input [3:0] din;
output [3:0] dout;
reg [3:0] dout;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
always @(posedge clk,negedge rst_n) begin
if(!rst_n)
dout <= 4'd0;
else
dout <= din + PAR;
end
endmodule
[/code]
忘了说了,上面的代码已经仿真正确,能够通过ISE综合。
应该有人用过的啊,求指教
信号名也是醉了。
先看他第一种引用: assign fuck[0].din = din0; 你for的时候,生成很多fuck[n],n就是j的值,那么按照verilog引用模块内信号的原则,module_inst_name.sig 就可以访问例化名“module_inst_name”的模块内部的"sig"信号,那么他用din0赋值给fuck[0].din,就可以把din0引入到第一1个fuck模块的din信号上,往后以此把每一个din都引入到对应fuck[n]的din上,就是这样的。
他的第二种引用: .din (din_w[(j+1)*4-1 : j*4] ), 这是for里例化模块的输入信号,很明显,随着j的不同,计算后,每次选的din_w的bit也不同,你自己计算一次就清楚了,这样就把din_w[15:0]不同的bit分配给了某个fuck模块的din。
我知道这段代码什么意思啊,就是我写的,只不过我觉得for generate对于多个类似模块的生成很有帮助,减小代码量,改个参数就可以实现很好的扩展性,但是和它相连的信号却不能用循环……是不是我太想偷懒了。?
我知道这段代码什么意思啊,就是我写的,只不过我觉得for generate对于多个类似模块的生成很有帮助,减小代码量,改个参数就可以实现很好的扩展性,但是和它相连的信号却不能用循环……是不是我太想偷懒了。?
谁说不可以,说来说去只是简化代码的技巧而已,定义
reg [2:0] Sig [7:0]; 一个二维变量。
现在你有8个sig[2:0]了,那么你在循环里写sig[n],就把sig[0]~ sig[7]对应到每个for里的模块了,定义n为多少,也是可以参数化的。但是,二维变量不能用于输入输出噢,只能是模块内部变量
但是如果这种寄存器堆规模比较大,在FPGA中不仅仅消耗的是寄存器资源,同时还有为了给地址和存储内容建立映射关系的查找表,后者是完全没必要的资源浪费呀,而且寄存器堆由很多分散寄存器产生,很容易形成关键路径的吧………不知道我说的有问题没……
我刚才有个错误的东西,那就是,应该用wire去定义二维,不该用reg。反正你是连线而已这样就不会造成寄存器浪费了。
还有,别低估FPGA综合器的水平,不是每一种用reg定义的二维数组操作,都会给你综合成RAM实现,大多数情况的综合结果还是多个寄存器实现的。
至于关键路径这种东西,貌似不会因为加寄存器产生吧? 相反,加寄存器恰恰是减少关键路径的方法
可能我没怎么说清楚,如果是很多寄存器,需要很长的布线将这些寄存器组织成寄存器堆,可能会延时比较大。不过用wire定义成类似二维数组的形式,比较新奇,我试一下。谢谢你的指教,
呵呵,算不上指教,我也喜欢偷懒,恰好verilog二维向量,就是简化代码设计的一种方式方便阅读和书写。
请问各位大神,如果 for的次数时不固定的 ,综合器可以综合吗 ,本文中的N是一个变量的话
