ip_ram
定义了一个名为ip_ram的模块,该模块具有以下端口:
sys_clk:系统时钟输入。
sys_rst_n:系统复位输入。
cpp
module ip_ram(
input sys_clk,
input sys_rst_n
);
wire ram_en ;
wire ram_wea ;
wire [4:0] ram_addr ;
wire [7:0] ram_wr_data ;
wire [7:0] ram_rd_data ;
ram_rw模块包含了RAM的读写逻辑,其输入输出信号如下:
clk:时钟输入。
rst:复位输入。
ram_en:RAM使能信号。
ram_wea:RAM写使能信号。
ram_addr:RAM地址信号。
ram_wr_data:RAM写入数据信号。
ram_rd_data:RAM读出数据信号。
cpp
ram_rw ram_rw_u(
.clk (sys_clk),
.rst (sys_rst_n),
.ram_en (ram_en),
.ram_wea (ram_wea),
.ram_addr (ram_addr),
.ram_wr_data(ram_wr_data),
.ram_rd_data(ram_rd_data)
);
blk_mem_gen_0模块则是一个具有标准接口的内存生成器模块,其端口包括:
clka:时钟输入。
ena:内存使能信号。
wea:内存写使能信号。
addra:内存地址信号。
dina:写入内存的数据信号。
douta:从内存读出的数据信号。
cpp
blk_mem_gen_0 your_instance_name (
.clka(sys_clk), // input wire clka
.ena(ram_en), // input wire ena
.wea(ram_wea), // input wire [0 : 0] wea
.addra(ram_addr), // input wire [4 : 0] addra
.dina(ram_wr_data), // input wire [7 : 0] dina
.douta(ram_rd_data) // output wire [7 : 0] douta
);
ram_rw
下面Verilog代码定义了一个名为ram_rw的模块,实现了RAM的读写控制逻辑。该模块具有以下端口:
clk:时钟输入。
rst:复位输入。
ram_en:RAM使能输出。
ram_wea:RAM写使能输出。
ram_addr:RAM地址输出。
ram_wr_data:RAM写入数据输出。
ram_rd_data:RAM读出数据输入。
ram_wea信号在rw_cnt小于或等于31且ram_en为高电平时置为逻辑1,表示RAM写入使能。否则,置为逻辑0。
ram_en信号直接由复位信号控制,在复位信号为高电平时为逻辑0,表示RAM未使能。这意味着RAM在复位时处于禁用状态。
ram_wr_data是一个8位寄存器,用于存储RAM的写入数据。在每个时钟周期的上升沿或复位信号的下降沿触发时递增。当复位信号为低电平时,将ram_wr_data清零;当ram_wr_data小于或等于31时,递增;否则,将其清零。
ram_addr是一个5位寄存器,用于存储RAM的地址。其工作原理与ram_wr_data寄存器相似。
cpp
module ram_rw(
input clk,
input rst,
output ram_en,
output ram_wea,
output reg[4:0] ram_addr,
output reg[7:0] ram_wr_data,
input [7:0] ram_rd_data
);
rw_cnt是一个6位寄存器,用于计数器功能。它在每个时钟周期上升沿或复位信号的下降沿触发时递增。当复位信号为低电平时,rw_cnt被清零。当rw_cnt达到63时,它会被重置为0。
cpp
reg [5:0] rw_cnt;
这两行assign语句的功能是将RAM的写使能信号ram_wea
和RAM的使能信号ram_en
赋值。
-
ram_wea
的赋值逻辑为:如果rw_cnt
小于或等于31(即计数器rw_cnt
的值在0到31之间),并且RAM使能信号ram_en
为高电平(1),则ram_wea
被赋值为1(逻辑真);否则,被赋值为0(逻辑假)。这意味着只有在RAM使能且计数器值小于等于31时,才会使RAM的写入操作有效。 -
ram_en
的赋值逻辑为:直接将ram_en
赋值为复位信号rst
。当复位信号为高电平时,RAM使能信号也被置为高电平,即RAM被使能;当复位信号为低电平时,RAM使能信号被置为低电平,即RAM被禁用。
这两行assign语句定义了RAM使能信号和RAM写使能信号的逻辑,使得RAM的写入操作在特定条件下有效,并且可以通过复位信号控制整个RAM的使能状态。
cpp
assign ram_wea=(rw_cnt<=31&&ram_en)?1'b1:1'b0;
assign ram_en=rst;
模块内部逻辑包括三个always块:
第一个always块用于递增计数器rw_cnt,在时钟上升沿或复位信号下降沿触发。当复位信号为低电平时,计数器被清零;当计数器值达到63时,也将其清零;否则,计数器递增1。
cpp
always@(posedge clk or negedge rst) begin
if(!rst)
rw_cnt<=1'b0;
else if(rw_cnt==6'd63)
rw_cnt<=1'b0;
else
rw_cnt<=rw_cnt+1'b1;
end
第二个always块用于生成RAM写入数据信号ram_wr_data。当复位信号为低电平时,将写入数据清零;当写入数据小于或等于31时,递增写入数据;否则,将其清零。
cpp
always@(posedge clk or negedge rst) begin
if(!rst)
ram_wr_data<=0;
else if(ram_wr_data<=6'd31)
ram_wr_data<=ram_wr_data+1'b1;
else
ram_wr_data<=0;
end
第三个always块用于生成RAM地址信号ram_addr。其逻辑与第二个always块类似,但递增的是RAM地址。
cpp
always@(posedge clk or negedge rst) begin
if(!rst)
ram_addr<=0;
else if(ram_addr<=6'd31)
ram_addr<=ram_addr+1'b1;
else
ram_addr<=0;
end
此外,模块中还包含了一个名为ila_0的实例,ILA(Integrated Logic Analyzer)用于调试,以便在FPGA中观察信号的值