verilog 二维的memory数据存储和读取 📅 2026/7/24 20:12:44 写于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、h07dfe7f5timescale 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 (i0;iNC_NUMBER;ii1) begin //赋初值 for (j0;jNS_NUMBER;jj1) 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_carrd0; else if(data_in_valid) count_carrcount_carr1b1; //子载波一直计数 else count_carrd0; end //count_sys 符号计数 always(posedge sys_clk or negedge rst_n) begin if(!rst_n) count_sysd0; else if(count_carrNC_NUMBER-1) count_syscount_sys1b1; else if(!data_in_valid) count_sysd0; else count_syscount_sys; //子载波计数期间一直保存符号数的计数值 end ///////////////////////////////////////////////////////读出数据 always(posedge sys_clk or negedge rst_n) begin if(!rst_n) begin data_out_validd0; data_outd0; end else if(read_en) begin data_out_valid1b1; data_outmem[addr][Ns_or_Nc_count]; end else begin data_out_validd0; data_outd0; end end endmoduletestbenchtimescale 1ns / 1ps module test_data_in_memory(); parameter NC_NUMBER128; parameter NS_NUMBER128; parameter DATA_IMAGANDREAL_WIDTH32; 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_clkd0; rst_nd0; $readmemb(D:/FPGA_one/rad_1024_128_Ranging_and_speed_v1/ranging_speed_echo.txt,echo_mem); //这里的.txt文件保存了128*128长度的数据为方便你测试可以在matlab中生成关于该文件的生成 //我将在后续中写出 #1000; rst_nb1; #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) countd0; else if(countd2048) countdz; else countcount1b1; end //valid always(posedge sys_clk or negedge rst_n) begin if(!rst_n) begin data_ind0; data_in_validd0; end else if(count2047) begin data_inecho_mem[count]; //当前的count为0但是输出数据与count1对齐需要注意可 //通过将count打一拍来将count0对齐输出数据 data_in_validd1; end else if(count2048) begin //因为只是测试只取前16个128数据串即可 data_inecho_mem[count]; data_in_validd0; end else begin data_in_validdata_in_valid; //数据有效位其实理解为数据使能也可以 data_ind0; end end //read_en Ns_or_Nc_count addr always(posedge sys_clk or negedge rst_n) begin if(!rst_n) begin read_end0; Ns_or_Nc_countd0; addrd0; end else if(countd255) begin //取第二行的128个数据 在255计数处取值输出数据在256处对齐 read_end1; Ns_or_Nc_countd1; //0为第一行1为第二行 addrcount-d255; end else if(countd383) begin read_end0; Ns_or_Nc_countd0; addrd0; end else begin read_enread_en; Ns_or_Nc_countNs_or_Nc_count; addraddr1b1; end end endmodule仿真结果如下验证数据存入对不对查看读取的数据对不对即可于是放大读取的数据查看前两个数据和后两个数据data_out为输出数据读取出的数据是正确的。