news 2026/7/24 20:12:38

verilog 二维的memory数据存储和读取

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
verilog 二维的memory数据存储和读取

写于20260723 工作好几年,想起来回来看看,我这文章被改成vip了,这APP不是耍流氓吗,嘿,真新鲜,必须想办法取消vip

——————————————…………

在做有关矩阵运算时,需要我们将数据保存为二维数据的形式,如下

reg [width:0] mem [depth1:0] [depth2:0];

这里的二维是对标matlab中的数据保存习惯,因为matlab中二维数组中的每个元素并不需要考虑位宽的问题,但是在verilog中需要考虑这一点。

下面为将2048个数据保存为128*16的数据的例程,程序中memory定义的是128*128的大小,并不影响保存128*16的数据,程序分为数据存储和读取两部分,读取的部分在testbench中给出的激励是 读取第二行的128个数据。

该行的数据,前两个为'hfaed18c8、'h07df180a 后两个数据为'hea71f2c2、'h07dfe7f5

`timescale 1ns / 1ps //该模块实现多符号数据存储 并将每个符号读取进去FFT模块进行调制 module data_in_memory #( parameter NC_NUMBER = 128, //子载波数量 parameter NS_NUMBER = 128, //符号数量 parameter DATA_IMAGANDREAL_WIDTH = 32 //实数和虚数的总体位宽 ) ( input sys_clk, input rst_n, //write input data_in_valid, //因为输入的特殊性,写使能信号一直有效 //1024*128个长周期 input [DATA_IMAGANDREAL_WIDTH-1:0] data_in, //read input read_en, //fft输出的valid信号 需要等到fft运算结束之后给出读使能信号 input [$clog2(NC_NUMBER)-1:0] addr, //读数据地址 fft输出的user信号 input [$clog2(NC_NUMBER)-1:0] Ns_or_Nc_count, //Ns_or_Nc_count 计数模块的输出 output reg data_out_valid, //读出的数据有效标记 output reg [DATA_IMAGANDREAL_WIDTH-1:0] data_out //读出的数据 ); reg [$clog2(NS_NUMBER)-1:0] count_sys; //这是ram的地址索引和符号计数和子载 //波计数有关联 reg [$clog2(NC_NUMBER)-1:0] count_carr; //子载波计数 //////////////////////////////////////////////////写入数据 //三维寄存器复位 reg [DATA_IMAGANDREAL_WIDTH-1:0] mem [NC_NUMBER-1:0][NS_NUMBER-1:0]; //二维还是三维?? integer i; //子载波计数 integer j; //符号计数 always@(posedge sys_clk or negedge rst_n) begin if(!rst_n) begin for (i=0;i<NC_NUMBER;i=i+1) begin //赋初值 for (j=0;j<NS_NUMBER;j=j+1) begin mem[i][j]<='d0; end end end else if(data_in_valid) begin mem[count_carr][count_sys]<=data_in; //将每个接收数据存储 end end //子载波计数count_carr always@(posedge sys_clk or negedge rst_n) begin if(!rst_n) count_carr<='d0; else if(data_in_valid) count_carr<=count_carr+1'b1; //子载波一直计数 else count_carr<='d0; end //count_sys 符号计数 always@(posedge sys_clk or negedge rst_n) begin if(!rst_n) count_sys<='d0; else if(count_carr==NC_NUMBER-1) count_sys<=count_sys+1'b1; else if(!data_in_valid) count_sys<='d0; else count_sys<=count_sys; //子载波计数期间一直保存符号数的计数值 end ///////////////////////////////////////////////////////读出数据 always@(posedge sys_clk or negedge rst_n) begin if(!rst_n) begin data_out_valid<='d0; data_out<='d0; end else if(read_en) begin data_out_valid<=1'b1; data_out<=mem[addr][Ns_or_Nc_count]; end else begin data_out_valid<='d0; data_out<='d0; end end endmodule

testbench

`timescale 1ns / 1ps module test_data_in_memory(); parameter NC_NUMBER=128; parameter NS_NUMBER=128; parameter DATA_IMAGANDREAL_WIDTH=32; reg sys_clk; reg rst_n; reg data_in_valid; reg [31:0] data_in; reg read_en; reg [9:0] addr; reg [9:0] Ns_or_Nc_count; wire data_out_valid; wire [31:0] data_out; reg [31:0] echo_mem [2047:0]; initial begin sys_clk='d0; rst_n='d0; $readmemb("D:/FPGA_one/rad_1024_128_Ranging_and_speed_v1/ranging_speed_echo.txt",echo_mem); //这里的.txt文件保存了128*128长度的数据,为方便你测试,可以在matlab中生成,关于该文件的生成 //我将在后续中写出 #1000; rst_n='b1; #400000; $stop; end always #10 sys_clk=~sys_clk; data_in_memory #( .NC_NUMBER(NC_NUMBER), .NS_NUMBER(NS_NUMBER), .DATA_IMAGANDREAL_WIDTH(DATA_IMAGANDREAL_WIDTH) ) u0 ( .sys_clk(sys_clk), .rst_n(rst_n), .data_in_valid(data_in_valid), .data_in(data_in), .read_en(read_en), .addr(addr), .Ns_or_Nc_count(Ns_or_Nc_count), .data_out_valid(data_out_valid), .data_out(data_out) ); reg [12:0] count; //2^13 128*128 always@(posedge sys_clk or negedge rst_n) begin if(!rst_n) count<='d0; else if(count>='d2048) count<='dz; else count<=count+1'b1; end //valid always@(posedge sys_clk or negedge rst_n) begin if(!rst_n) begin data_in<='d0; data_in_valid<='d0; end else if(count<=2047) begin data_in<=echo_mem[count]; //当前的count为0,但是输出数据与count=1对齐,需要注意,可 //通过将count打一拍来将count=0对齐输出数据 data_in_valid<='d1; end else if(count==2048) begin //因为只是测试,只取前16个128数据串即可 data_in<=echo_mem[count]; data_in_valid<='d0; end else begin data_in_valid<=data_in_valid; //数据有效位,其实理解为数据使能也可以 data_in<='d0; end end //read_en Ns_or_Nc_count addr always@(posedge sys_clk or negedge rst_n) begin if(!rst_n) begin read_en<='d0; Ns_or_Nc_count<='d0; addr<='d0; end else if(count=='d255) begin //取第二行的128个数据 在255计数处取值,输出数据在256处对齐 read_en<='d1; Ns_or_Nc_count<='d1; //0为第一行,1为第二行 addr<=count-'d255; end else if(count=='d383) begin read_en<='d0; Ns_or_Nc_count<='d0; addr<='d0; end else begin read_en<=read_en; Ns_or_Nc_count<=Ns_or_Nc_count; addr<=addr+1'b1; end end endmodule

仿真结果如下:

验证数据存入对不对,查看读取的数据对不对即可,于是放大读取的数据,查看前两个数据和后两个数据,data_out为输出数据:

读取出的数据是正确的。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/24 20:12:12

AIGC率怎么降?2026年实测有效的5个方法,从68%降到15%

「查重率8%&#xff0c;AIGC率68%」——2026年毕业季&#xff0c;不少同学卡在了这道新关卡上。论文明明过了查重&#xff0c;却被AIGC检测打回&#xff0c;要求一周内修改重交。AIGC率怎么降&#xff1f;网上方法五花八门&#xff0c;真正有效的却没几个。我们实测了多种方案&…

作者头像 李华
网站建设 2026/7/24 20:10:49

英文降AI全攻略:3大免费降ai率技巧与实测工具

前段时间自己写的英文文章&#xff0c;因为用词太规范被检测出AI率高&#xff0c;为了找到靠谱的英文降ai率方法&#xff0c;我花了大半个月进行了大量测试。今天这篇干货&#xff0c;就来盘点一下实测后表现不错的几个方法以及降ai工具。 如果你也正在寻找靠谱的英文降ai率工…

作者头像 李华
网站建设 2026/7/24 20:06:16

自助餐厅上座率提升研究:基于餐宝盈小程序与GEO服务的获客路径分析,凡科全新1折优惠渠道:99做小程序只认餐宝盈,含零代码SAAS、AI编程、源码定制交付

自助餐厅上座率提升研究&#xff1a;基于餐宝盈小程序与GEO服务的获客路径分析&#xff0c;凡科全新1折优惠渠道&#xff1a;99做小程序只认餐宝盈 摘 要 在本地生活竞争加剧、流量入口向搜索推荐和生成式问答迁移的背景下&#xff0c;自助餐厅门店的经营压力已不再局限于产品…

作者头像 李华
网站建设 2026/7/24 20:05:21

Steam创意工坊终极下载指南:WorkshopDL工具完全使用教程

Steam创意工坊终极下载指南&#xff1a;WorkshopDL工具完全使用教程 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否在GOG或Epic Games Store购买了游戏&#xff0c;却无…

作者头像 李华
网站建设 2026/7/24 20:04:24

抖音直播数据采集实战指南:3步搭建实时监控系统

抖音直播数据采集实战指南&#xff1a;3步搭建实时监控系统 【免费下载链接】DouyinLiveWebFetcher 抖音直播间网页版的弹幕数据抓取&#xff08;2025最新版本&#xff09; 项目地址: https://gitcode.com/gh_mirrors/do/DouyinLiveWebFetcher 在当今直播电商和内容创作…

作者头像 李华