打工人日报#20251010

打工人日报#20251010

知识点

BMG IP 核配置成双端口 RAM

ip_2port_ram.v

csharp 复制代码
module ip_2port_ram(
input sys_clk , //系统时钟
input sys_rst_n //系统复位,低电平有效
);

//wire define
wire ram_wr_en ; //端口 A 使能
wire ram_wr_we ; //ram 端口 A 写使�?
wire ram_rd_en ; //端口 B 使能
 wire rd_flag ; //读启动标�?
 wire [5:0] ram_wr_addr; //ram 写地�?
 wire [7:0] ram_wr_data; //ram 写数�?
 wire [5:0] ram_rd_addr; //ram 读地�?
 wire [7:0] ram_rd_data; //ram 读数�?

 //*****************************************************
 //** main code
 //*****************************************************

 //RAM 写模�?
 ram_wr u_ram_wr(
 .clk (sys_clk ),
 .rst_n (sys_rst_n ),

 .rd_flag (rd_flag ),
 .ram_wr_en (ram_wr_en ),
 .ram_wr_we (ram_wr_we ),
 .ram_wr_addr (ram_wr_addr),
 .ram_wr_data (ram_wr_data)
 );

 //�?单双端口 RAM
 blk_mem_gen_0 u_blk_mem_gen_0 (
 .clka (sys_clk ), // input wire clka
 .ena (ram_wr_en ), // input wire ena
 .wea (ram_wr_we ), // input wire [0 : 0] wea
 .addra (ram_wr_addr), // input wire [5 : 0] addra
 .dina (ram_wr_data), // input wire [7 : 0] dina
 .clkb (sys_clk ), // input wire clkb
 .enb (ram_rd_en ), // input wire enb
 .addrb (ram_rd_addr), // input wire [5 : 0] addrb
 .doutb (ram_rd_data) // output wire [7 : 0] doutb
 );

 //RAM 读模�?
 ram_rd u_ram_rd(
 .clk (sys_clk ),
 .rst_n (sys_rst_n ),

 .rd_flag (rd_flag ),
 .ram_rd_en (ram_rd_en ),
 .ram_rd_addr (ram_rd_addr),
 .ram_rd_data (ram_rd_data)
 );
ila_0 u_ila_0 (
.clk (sys_clk ), // input wire clk
.probe0 (ram_wr_en ), // input wire [0:0] probe0
.probe1 (ram_wr_we ), // input wire [0:0] probe1
.probe2 (ram_rd_en ), // input wire [0:0] probe2
.probe3 (rd_flag ), // input wire [0:0] probe3
.probe4 (ram_wr_addr), // input wire [5:0] probe4
.probe5 (ram_wr_data), // input wire [7:0] probe5
.probe6 (ram_rd_addr), // input wire [5:0] probe6
.probe7 (ram_rd_data) // input wire [7:0] probe7
);

 endmodule

ram_wr.v

csharp 复制代码
module ram_wr(
input clk , //时钟信号
input rst_n , //复位信号,低电平有效

//RAM 写端口操作
output ram_wr_we , //ram 写使能
output reg ram_wr_en , //端口使能
output reg rd_flag , //读启动信号
output reg [5:0] ram_wr_addr , //ram 写地址
 output [7:0] ram_wr_data //ram 写数据
 );

 //*****************************************************
 //** main code
 //*****************************************************

 //ram_wr_we 为高电平表示写数据
 assign ram_wr_we = ram_wr_en ;

 //写数据与写地址相同,因位宽不等,所以高位补 0
 assign ram_wr_data = {2'b0,ram_wr_addr} ;

 //控制 RAM 使能信号
 always @(posedge clk or negedge rst_n) begin
 if(!rst_n)
 ram_wr_en <= 1'b0;
 else
 ram_wr_en <= 1'b1;
 end

 //写地址信号 范围:0~63
 always @(posedge clk or negedge rst_n) begin
 if(!rst_n)
 ram_wr_addr <= 6'd0;
 else if(ram_wr_addr < 6'd63 && ram_wr_we)
 ram_wr_addr <= ram_wr_addr + 1'b1;
 else
 ram_wr_addr <= 6'd0;
 end
 //当写入 32 个数据(0~31)后,拉高读启动信号
 always @(posedge clk or negedge rst_n) begin
 if(!rst_n)
 rd_flag <= 1'b0;
 else if(ram_wr_addr == 6'd31)
 rd_flag <= 1'b1;
 else
 rd_flag <= rd_flag;
 end

 endmodule

ram_rd.v

csharp 复制代码
module ram_rd(
input clk , //时钟信号
input rst_n , //复位信号,低电平有效

//RAM 读端口操作
input rd_flag , //读启动标志
input [7:0] ram_rd_data, //ram 读数据
output ram_rd_en , //端口使能
output reg [5:0] ram_rd_addr //ram 读地址
 );
 //*****************************************************
 //** main code
 //*****************************************************
 assign ram_rd_en = rd_flag;

 //读地址信号 范围:0~63
 always @(posedge clk or negedge rst_n) begin
 if(!rst_n)
 ram_rd_addr <= 6'd0;
 else if(ram_rd_addr < 6'd63 && ram_rd_en)
 ram_rd_addr <= ram_rd_addr + 1'b1;
 else
 ram_rd_addr <= 6'd0;
 end

 endmodule

tb_ip_2port_ram.v

csharp 复制代码
`timescale 1ns / 1ps //仿真单位/仿真精度

module tb_ip_2port_ram();

//parameter define
parameter CLK_PERIOD = 20; //时钟周期 20ns

//reg define
reg sys_clk;
 reg sys_rst_n;

 //信号初始化
 initial begin
 sys_clk = 1'b0;
 sys_rst_n = 1'b0;
 #200
 sys_rst_n = 1'b1;
 end

 //产生时钟
 always #(CLK_PERIOD/2) sys_clk = ~sys_clk;
 ip_2port_ram u_ip_2port_ram(
 .sys_clk (sys_clk ),
 .sys_rst_n (sys_rst_n )
 );

 endmodule

在"IP Catalog"窗口的搜索栏中输入"Block Memory"关键字后





ram_wr_we 信号拉高,说明此时是对 ram 进行写操作。ram_wr_we 信号拉高之后,地址

和数据都是从 0 开始累加,

当 ram 地址为 0 时,写入的数据也是 0;当 ram 地址为 1 时,写入的数据

也是 1。当地址为 32 时,读启动信号(rd_flag)被拉高,此时将读端口使能,开始读出 ram 中的数据,这

里大家可能会有一个疑惑,明明我们代码中是在写地址计数到 31 的时候给 rd_flag 赋值为 1(即拉高)的,

但是仿真结果为什么是在 32 的时候才拉高呢?这是因为在时序逻辑中,rd_flag 的赋值是在写地址计数到 31

时的下一个时钟信号的上升沿完成的,所以我们在仿真中看到的结果就是在写地址为 32 时,rd_flag 才被拉

高

阅读

《杀死一只知更鸟》

第十三章

姑姑到来,与我们同住,需要教会我们一些道理

相关推荐
陈卫军老师6 小时前
陈卫军语录全集总结:12句话,一条主线
经验分享·笔记
2501_9269783310 小时前
给自指系统接一个外部锚 —— 一个关于「用 AI 观察自己」的方法
人工智能·经验分享·笔记·机器学习·ai写作
我命由我1234513 小时前
Photoshop - Photoshop 使用对齐功能定位元素
学习·职场和发展·产品运营·求职招聘·职场发展·产品经理·学习方法
AOI小白新手上路14 小时前
anomalib 缺陷检测复现笔记:从跑通库到 EfficientAD 落地
人工智能·笔记·机器学习
xxwl58514 小时前
RabbitMQ 学习笔记
笔记·学习·rabbitmq
szxinmai主板定制专家15 小时前
基于Zynq的高精度多通道数据采集卡完整解决方案(工业振动/高速采集/边缘传输)
fpga开发·zynq·数据采集卡
加油努力有饭吃15 小时前
DLMS/COSEM 蓝皮书解读(二十六):Auto connect(class_id = 29)—— 自动拨号与主动连接(出站管理)
笔记
CarIise15 小时前
Java实训阶段查漏补缺复习笔记1
java·开发语言·笔记
陈卫军老师15 小时前
陈卫军谈商业底线:营销是术,产品是道
经验分享·笔记·流量运营
智者知已应修善业16 小时前
【51单片机只有一个8*8点阵数据如何滚动起来一片595+一组IO+花样】2022-1-15
c++·经验分享·笔记·单片机·蓝桥杯·硬件架构