【点滴积累FPGA】例说reg
在VERILOG语言里面,几乎每个代码中出现最多的应该是reg这个关键字,如果问reg是什么,很多初学者会很爽快的回答是寄存器,因为书本上就是这么写的。应该再想想有没有别的补充?下面我就用几个例子说明这个回答不完全正确,同时引出多种不同的reg用法:1,reg生成寄存器:
module my_dff(
input clk,
input d,
output q,
);
reg q;
always @ (posedge clk) q<=d;
endmodule
2,起到wire的作用
module my_and(
input a,
input b,
output c,
);
reg c;
always @*c<=a&b;
endmodule
3,生成了锁存器
module my_lacth(
input d,
input e,
output q
);
always @* if(e)q=d;
endmodule
简单做做分析:
1,reg生成寄存器 flip-flop 是有条件的,就是在时钟的边缘触发赋值。
2,在电平触发进程中(一个always块 一般叫做一个进程)reg可能被综合成一根线(例子2 my_and)也可能被综合成一个LATCH锁存器,这取决于reg赋值条件是否全部被罗列出,在例子2中,赋值条件被全部罗列出,任何一个条件都对应一个reg的输出,因此只起到一个连线作用;在例子3中,赋值条件没有被全部列出,具体说在e为0的情况下没有输出明确列出,编译器认为在e==0情况下保存原来数据不变化,所以就生成的锁存器。
3,在例子2中,这种使用reg代替wire或是输出的写法很普遍,也很灵活。
4,在例子3中,我们这里是故意生成的latch锁存器,有时候很多情况下应为条件没有罗列完整而生成了我们不需要的锁存器。如何在编程中避免生成不需要的latch呢,很简单,在电平触发进程中,有一个if 就配合上一个else,有个case 就配合上一个default.这是用一种形式保障内容的不出错。
5,在verilog中reg的生成的是什么,再次回答这个问题,我们有了更多的答案,但是更重要是理解生成时候生成什么。
6,我还总结出一种reg生成RAM块的应用,等专门做介绍。 等待下文 关于REG生成RAM,先给个例子,以后专门详细论述:
采用reg的形式定义一些寄存器组,之后在代码中FPGA厂家提供的RAM块时序,这样综合器就能知道你是要用一块RAM块,就会分配过来。以下我给出一个模块,是从我的mips处理器内核中提取出来的,是个单口写双口读并且带有冲突检测和前递通路的寄存器组,用来实现MIPS兼容处理器里面的R0-R31寄存器组,每个寄存器是32位,实际生成RAM块。这部分大家随便看看,知道有这么回事,等自己用的时候能考虑到就行了。
module reg_array(
data,
wraddress,
rdaddress_a,
rdaddress_b,
wren,
clock,
qa,
qb,
rd_clk_cls,
// bank_sel
);
input data;
input wraddress;
input rdaddress_a;
input rdaddress_b;
// input bank_sel;
input rd_clk_cls;
input wren;
reg r_data;
reg r_wraddress;
reg r_rdaddress_a;
reg r_rdaddress_b;
reg r_wren;
input clock;
output qa;
output qb;
reg reg_bank;
integer i;
initial
begin
for(i=0;i<32;i=i+1)
reg_bank=0;
end
always@(posedge clock)
begin
r_data <=data;
r_wraddress<=wraddress;//这些的时序都是为了迎合ALTERA RAM宏单元的时序。
r_wren<=wren;
end
always@(posedge clock)
if (~rd_clk_cls)
begin
r_rdaddress_a <=rdaddress_a; //这些的时序都是为了迎合ALTERA RAM宏单元的时序。
r_rdaddress_b <=rdaddress_b;//这些的时序都是为了迎合ALTERA RAM宏单元的时序。
end
always@(posedge clock)
if (r_wren)
reg_bank <= r_data ;
assign qa=(r_rdaddress_a==0)?0:
((r_wraddress==r_rdaddress_a)&&(1==r_wren))?r_data:
reg_bank;//解决读写冲突
assign qb=(r_rdaddress_b==0)?0:
((r_wraddress==r_rdaddress_b)&&(1==r_wren))?r_data:
reg_bank;//解决读写冲突
endmodule 嗯。期待后文。 verilog里面reg其实就是一个保存数值的变量 很佩服楼主的学习态度,受教了。谢谢 。谢谢 支持 楼主什么时候能不能把你的这个系列整理好后全部上传上来,很好的东西 楼主的说法不易理解,个人觉得还是按教科书的描述好理解。 reg就是寄存器,其他一切都是 综合器智能化的结果,怕用户乱用,所以没什么好总结的,还不如总结代码风格
页:
[1]