来自牛客的题:
由于本人知识尚浅,只是想记录一下自己的刷题过程中遇到的问题以及想法,也行存在不对的地方,欢迎各位大佬指正;
在此之前,我也会偶尔用到RAM,但并不清楚怎么设计它,如今好像明白了点;
在RAM模块中,我们会定义一个寄存器,通过这个寄存器对读写数据进行处理,在这道题中,我们需要设计一个位宽为4,深度为128的单端口RAM;
首先,我们定义一个存储器mem:
前面的[3:0]指数据位宽,后面的[127:0]指数据深度,即存储的数据量;但是数据量太多,我们不可能一一赋值,因此,我考虑使用generate... for...语句减少代码量;
那么,什么是 generate... for...语句,复习一下:
generate...for
1 2 3 4 5 6 |
|
作用上:和for是一样的;
区别:
(1)generate for的循环变量必须用genvar声明,for的变量可以用reg、integer整数等多种类型声明;
(2)for只能用在always块里面,generate for可以做assign赋值,用always块话always写在generate for里;
(3)generate for后面必须给这个循环起一个名字,for不需要;
(4)generate for还可以用于例化模块;
以for循环和generate for的循环举例子:
always @ (posedge clk)
begin
data_reg[0] <= data_in;
end
genvar i;
generate for(i = 0; i < 4; i = i+1) begin : shift_reg
always @ (posedge clk) begin
data_reg[i+1] <= data_reg[i];
end
end
endgenerate
等效的语句:
always @ (posedge clk)
begin
data_reg[0] <= data_in;
end
integer i;
always @ (posedge clk) begin
for(i = 0; i < 4; i = i+1)
data_reg[i+1] <= data_reg[i];
end
回到本题,使用generate... for...语句是为了在复位信号有效时,为每一个mem赋初值,当enb信号有效时,我们将写数据赋值给mem相应的地址,这个地址信号需要由调用RAM模块的部分给出,当enb信号无效时,我们将mem相应的地址的数据赋值给读数据;
完整代码如下:
`timescale 1ns/1ns
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] mem [127:0];
genvar i;
generate for(i=0 ; i<128 ;i = i+1)
begin : ram
always@(posedge clk or negedge rst)
if(rst == 1'b0)
mem[i] <= 1'b0;
else if(enb == 1'b1)
mem[addr] <= w_data;
else
mem[addr] <= mem[addr];
end
endgenerate
assign r_data = (enb == 1'b0)? mem[addr]:4'b0;
//*************code***********//
endmodule