序
赛灵思官方ram示例中用的是vhdl语言,相比与Verilog和Sv来说实在是过于繁琐,不过好处在于ram时序并不复杂,只要能仿出来就能看出咋回事。
RAM时序列
ip核配置如下,基本没啥太大改动
激励编写
又到了紧张刺激的猜时序环节了
对于读时序而言,需要维持两个时钟周期才有输出
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2024/06/12 12:29:51
// Design Name:
// Module Name: frame_gen_01
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
// 实际就是相当于一个16bit生成器。
// 每次初始化时给ram写入数据。
module frame_gen_01(
);
reg [127:0] blk_mem_file [0:159];
reg clka; // 实际上只是为了初始化用的,谁给都行。
reg ena;
reg wea;
reg [7:0] addra;
reg [127:0] dina;
reg clkb;
reg enb;
reg [7:0] addrb;
wire [127:0] doutb;
initial begin
clka = 1'b1;
forever #20 clka = ~clka;
end
initial begin
clkb = 1'b1;
forever #40 clkb = ~clkb;
end
initial begin
$readmemh("C:/fpgaPrj/20240612_ram_dispose/20240612_ram_dispose.srcs/file_ram/file_data01.txt",blk_mem_file);
ena = 0;
wea = 0;
addra = 8'b0;
dina = 128'b0;
enb = 0;
addrb = 8'b0;
#300;
send_a_data;
#2000;
read_b_data;
end
task send_a_data;
integer a_index;
begin
// @(posedge clka);
for(a_index = 0;a_index< 4; a_index = a_index+1) begin
@(posedge clka) begin
ena = 1;
wea = 1;
addra = a_index;
dina = blk_mem_file[a_index];
end
end
@(posedge clka); //当a_index == 3的时候,需要维持一个时钟周期,之后才让是能信号赋值为0
ena = 0;
wea = 0;
end
endtask
task read_b_data;
integer b_index;
begin
for(b_index = 0;b_index<2;b_index = b_index+1) begin
@(posedge clkb);
enb = 1; // 该使能信号必须维持两个时钟以后才能输出结果,
addrb = 3;
end
@(posedge clkb);
enb = 0;
end
endtask
blk_mem_gen_0 your_instance_name (
.clka(clka), // input wire clka
.ena(ena), // input wire ena
.wea(wea), // input wire [0 : 0] wea
.addra(addra), // input wire [7 : 0] addra
.dina(dina), // input wire [127 : 0] dina
.clkb(clkb), // input wire clkb
.enb(enb), // input wire enb
.addrb(addrb), // input wire [7 : 0] addrb
.doutb(doutb) // output wire [127 : 0] doutb
);
endmodule
番外
文件读写:
对于读取ram而言,给定的文件一般都是8bit十六进制数。
然而实际取用时,需要128bit或者256bit
目前想到的有三种处理方式:
1、最暴力的,我直接修改你的文件格式即可。(具体实现略)
2、写task,或function,该方式适用于仿真,但没法作用于实际工程。因为实际工程中没有这么大的ram让你取用。
task change_width;
integer mem_use_index;
reg [127:0] tem_change_data;
begin
for(mem_use_index=0;mem_use_index<=159;mem_use_index = mem_use_index+1) begin
eight_2_hx(.mem_file_index(mem_use_index*16),.hx_mem_data(tem_change_data));
blk_mem_use[mem_use_index] = tem_change_data;
end
end
endtask
task eight_2_hx;
input mem_file_index;
output [127:0] hx_mem_data;
integer i;
begin
for(i=0;i<16;i=i+1) begin
hx_mem_data = {hx_mem_data,blk_mem_file[mem_file_index*8+i]};
end
end
endtask
3、实际情况是这样的:类似于一个输出8bit数据的ram,你需要给它使能信号与地址它才会返回数据。并且,该ram也并不是一个非常大的ram,而是需要满足一定的时序条件。
。。做设计的师傅喜欢这写