在通过编写Verilog代码实现ram功能时,需要自己先计算寄存器的位数和深度再编写代码。
而如果需要在编写的ram中预置值的话,就需要使用Verilog语言编写程序读写文件,来将相应的数据赋给寄存器。
这里给出Verilog实现ram的代码:
module dpram(
rclk,
raddr,
dout,
wclk,
we,
waddr,
din
);
parameter aw = 16; //address widtth
parameter dw = 12; //data address
input rclk; //read clock
input [aw-1:0] raddr; //read address
output [dw-1:0] dout; //data output
input wclk; //write clock
input we; //write enable
input [aw-1:0] waddr; //write address
input [dw-1:0] din; //data input
reg [dw-1:0] mem[(1<<aw)-1:0]; //block-ram
reg [aw-1:0] ra; //register read address
always @(posedge rclk)
begin
ra <= #1 raddr;
end
assign dout = mem[ra];
always @(posedge wclk)
begin
if(we)
mem[waddr] <= #1 din;
end
//读取mem文件存取程序中的mem寄存器
initial $readmemh("bmp_64K.mem",mem);
endmodule
下面的程序定义了ram中寄存器的位数和深度,决定了ram的大小:
reg [dw-1:0] mem[(1<<aw)-1:0]; //block-ram
整段程序不是很复杂,其他部分主要是用于实现ram的读写控制功能,这里不做赘述。
Verilog实现读写文件功能的部分代码如下:
//读取mem文件存取程序中的mem寄存器
initial $readmemh("bmp_64K.mem",mem);
这段程序的功能是从文件名是“bmp_64K.mem”的文件中读取其中的数据并置入前面定义的mem寄存器,即将数据置入ram中。
$readmemh("file_name.xxx",data)
就是将file_name.xxx中的数据读入到data数组中。
使用格式有6种:
$readmemb("<数据文件名>",<存贮器名>);
$readmemb("<数据文件名>",<存贮器名>,<起始地址>);
$readmemb("<数据文件名>",<存贮器名>,<起始地址>,<结束地址>);
$readmemh("<数据文件名>",<存贮器名>);
$readmemh("<数据文件名>",<存贮器名>,<起始地址>);
$readmemh("<数据文件名>",<存贮器名>,<起始地址>,<结束地址>);
$readmemb要求数据格式必须是二进制形式,$readmemh则要求数据格式必须是16进制格式。
下面一些用法格式:(摘自https://wenku.baidu.com/view/81075c1f964bcf84b9d57b57.html)
1,打开文件
integer file_id;
file_id = fopen("file_path/file_name");
2,写入文件
//$fmonitor只要有变化就一直记录
$fmonitor(file_id, "%format_char", parameter);
eg:$fmonitor(file_id, "%m: %t in1=%d o1=%h", $time, in1, o1);
//$fwrite需要触发条件才记录
$fwrite(file_id, "%format_char", parameter);
//$fdisplay需要触发条件才记录
$fdisplay(file_id, "%format_char", parameter);
$fstrobe();
3,读取文件
integer file_id;
file_id = $fread("file_path/file_name", "r");
4,关闭文件
$fclose(fjile_id);
5,由文件设定存储器初值
$readmemh("file_name", memory_name"); //初始化数据为十六进制
$readmemb("file_name", memory_name"); //初始化数据为二进制