ram ip核读写操作
读写控制模块
module ram_ctrl(
input clk ,
input rst_n ,
output reg wren ,//读写信号,高写低读
output reg [7:0] addr ,//地址信号
output reg [7:0] data
);
//参数定义
//中间信号定义
reg state; //定义状态寄存器
always @(posedge clk or negedge rst_n)begin
if(rst_n == 1'b0)begin
wren <= 1'b0;
addr <= 8'd0;
data <= 8'd0;
state <= 1'b0;
end
else begin
case(state)
1'b0 : begin //在此状态把数据写入ram
if(addr < 255)begin //地址在0~255之间,写信号有效
addr <= addr + 1'b1;
wren <= 1'b1; //写信号有效
end
else begin //转到下一个状态,让地址清零,让读信号有效
addr <= 8'd0; //让地址清零
state <= 1'b1; //转到下一个状态
wren <= 1'b0; //读信号有效
end
if (data < 255)
data <= data + 8'd1;
else
data <= 8'b0;
end
1'b1 : begin //在此状态下把数据从ram中读出来
if(addr < 255)begin //地址在0~255之间,读信号有效
addr <= addr + 1'b1;
wren <= 1'b0; //让读信号有效
end
else begin //转移到0状态,地址清零
state <= 1'b0; //转到0状态
addr <= 8'b0; //地址清零
end
end
default : state <= 0; //若系统不稳定,则直接进入0状态
endcase
end
end
endmodule
顶层模块
module ram_test(
input clk ,
input rst_n ,
output wire [7:0] q
);
wire wren;
wire [7:0] addr;
wire [7:0] data;
ram_ctrl u_ram_ctrl(
.clk (clk),
.rst_n (rst_n),
.wren (wren),//读写信号,高写低读
.addr (addr),//地址信号
.data (data)
);
ram ram_inst (
.address (addr),
.clock (clk),
.data (data),
.wren (wren),
.q (q)
);
endmodule
测试模块
`timescale 1ns/1ns
module ram_test_tb();
//激励信号定义
reg tb_clk ;
reg tb_rst_n ;
//输出信号定义
wire [7:0] q ;
//时钟周期参数定义
parameter CLOCK_CYCLE = 20 ;
ram_test u_ram_test(
.clk (tb_clk) ,
.rst_n (tb_rst_n) ,
.q (q)
);
//产生时钟
initial tb_clk = 1'b0;
always #(CLOCK_CYCLE/2) tb_clk = ~tb_clk;
//产生激励
initial begin
tb_rst_n = 1'b0;
// tb_din0 = 0;
#(CLOCK_CYCLE*20);
tb_rst_n = 1'b1;
repeat (256*3)begin
@(posedge tb_clk);
end
end
endmodule
总结
综合之后先检查rtl视图,rtl视图有问题先检查顶层文件是否正确,因为顶层不同,rtl视图不同
注意:一定要设置顶层,不然仿真和rtl视图都会出现问题。进到modsim先看work(如下图)下是否包含所有文件,没有的话先检查顶层设置
在复位结束后,写信号有效,同时给出数据和地址。Ram 的q 端在写的过程中会进行输出(存在两个周期的延时)
1.一个时钟周期的延迟是由于内部结构导致的(在检测地址变化时,只有在下一个时钟周期上升沿到来时才能输出数据)
2.另一个时钟周期的延迟是由于在输出时添加了一个寄存器(IP核调用时)
注:
在写数据的过程中,q端也会输出,这是由IP核功能决定的;
当写完数据后可进行读操作,同时给出地址,ram在两个时钟周期后可输出对应地址中的数据