generate语法
很多情况下,需要编写很多结构相同而参数不同的赋值语句或者逻辑语句,如果参数量很大的情况下,原本的列举就会显得心有余而力不足。c语言中常用for语句来解决此类问题,verilog则为我们提供了generate语句。
generate语句的最主要功能就是对module,reg,assign,always,task等语句或者模块进行复制。
generate语句有generate_for,generate_if,generate_case三种语句。
generate_for
(1)必须使用genvar申明一个正整数变量,用做for循环的判断。(genvar是generate语句中的一种变量类型,用在generate_for中声明正整数变量)
(2)需要复制的语句必须写到begin_end语句里面。就算只有一句。
(3)begin_end需要有一个类似于模块名的名字。
generate_if语句
generate_for用于复制模块,generate_if则是根据模块的参数(必须是常量)作为条件判断,来产生满足条件的电路。相当于判断语句。
generate_case语句
generate_case其实和generate_if一样,都是根据参数(都必须为常量)作为判断条件,来产生满足条件的电路,不同于使用了case语法而已。
定义genvar,作为generate种的循环变量。
generate语句中定义的for语句,必须要有begin,为后续增加标签做准备。
begin必须要有名称,也就是必须要有标签,因为标签会作为generate循环的实例名称。
generate-loop循环语句
generate-conditional条件语句
.generate-case分支语句
integer类型也是一种寄存器数据类型,integer类型的变量为有符号数,而reg类型的变量则为无符号数。
单端口RAM
设计一个单端口RAM,它有: 写接口,读接口,地址接口,时钟接口和复位;存储宽度是4位,深度128。
enb为低电平读取数据.
reg [3:0] myRAM[127:0]; 深度为128,因为地址有7位。
写法1
module RAM_1port(
input clk,
input rst,
input enb,
input [6:0]addr,
input [3:0]w_data,
output wire [3:0]r_data
);
//*************code***********//
reg [3:0] myRAM[127:0];
reg [3:0]r_data_r;
//写入ram
genvar i;
generate
for(i=0;i<128;i=i+1)
always@(posedge clk or negedge rst) begin
if(!rst) begin
myRAM[i] <= 0;
end
else if(enb)
myRAM[addr] <= w_data;
end
endgenerate
// 当enb为低电平,读取数据
assign r_data = (!enb) ?myRAM[addr] :'b0;
//*************code***********//
endmodule
写法2
module RAM_1port(
input clk,
input rst,
input enb,
input [6:0]addr,
input [3:0]w_data,
output wire [3:0]r_data
);
//*************code***********//
reg [3:0] myRAM[127:0];
reg [3:0]r_data_r;
//写入ram
genvar i;
generate
for(i=0;i<128;i=i+1)
always@(posedge clk or negedge rst) begin
if(!rst) begin
myRAM[i] <= 0;
end
else if(enb)
myRAM[addr] <= w_data;
end
endgenerate
// 读取RAM
always@(*) begin
if(~rst)
r_data_r <= 0;
else
r_data_r <= ~enb? myRAM[addr]: r_data_r;
end
assign r_data = r_data_r;
//*************code***********//
endmodule
双端口RAM 可以同时读写,故需要两个always语句独立
实现一个深度为8,位宽为4bit的双端口RAM,数据全部初始化为0000。具有两组端口,分别用于读数据和写数据,读写操作可以同时进行。
当读数据指示信号read_en有效时,通过读地址信号read_addr读取相应位置的数据read_data,并输出;当写数据指示信号write_en有效时,通过写地址信号write_addr 和写数据write-data,向对应位置写入相应的数据。
reg [8:0] i ; 位宽得为9位,不然会溢出。
八位地址,所以reg [3:0] myRAM [255:0];
module ram_mod(
input clk,
input rst_n,
input write_en,
input [7:0]write_addr,
input [3:0]write_data,
input read_en,
input [7:0]read_addr,
output reg [3:0]read_data
);
reg [3:0] myRAM [255:0];
reg [8:0] i ;
//写数据
always@(posedge clk or negedge rst_n)
if(!rst_n)
for(i=0;i<256;i=i+1)
myRAM[i]<=0;
else
myRAM[write_addr] <= write_en?write_data:myRAM[write_addr];
//读数据
always@(posedge clk or negedge rst_n)
if(!rst_n)
read_data <= 0;
else
read_data <= read_en?myRAM[read_addr]:read_data;
endmodule