fpga矩阵转置_matlab 转置

(4) 2024-06-23 15:12

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说
fpga矩阵转置_matlab 转置,希望能够帮助你!!!。

这里写目录标题

  • 1 功能
  • 2 开发环境
  • 3 框架
  • 4 转置公式
  • 5 Simulation
    • 第一部分
    • 第二部分
    • 第三部分
  • 6 Matlab代码
    • 产生FIFO数据
    • 产生转置矩阵
  • 7 HDL
    • 仿真文件
    • 顶层文件
    • FIFO顶层文件
    • FIFO读
    • FIFO写
    • RAM顶层文件
  • 8 IP配置
    • FIFO
    • RAM
    • ROM
  • 9 Reference

1 功能

通过tb读取本地数据保存到FIFO,通过coe文件将转置后的地址数据保存在ROM中,读取FIFO的文件作为输入,读取ROM作为地址。通过地址变换,对矩阵进行转置,最终将转置后的矩阵保存在RAM中。

2 开发环境

Vivado

3 框架

fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第1张
包含IP:FIFO、RAM和ROM

4 转置公式

来源见 Reference
fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第2张
fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第3张
fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第4张

5 Simulation

fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第5张

第一部分

通过tb将数据写到FIFO中,此部分数据为两路(1:32)*32。
这里的数据也就是转置前的数据,每行从1增长到32,总共32行。

第二部分

从FIFO中读取数据。
从ROM中读取地址,此地址为转置后的地址。
将FIFO中的数据按ROM中的地址写入到RAM中。

第三部分

读取RAM,可以从波形上看到转置的效果。
本来每行是1到32逐渐增加,现在每行为1到32中的一个数。
转置成功!

6 Matlab代码

产生FIFO数据

%% export to bin file % specifying a signed, fixed-point data type, rounding towards negative infinity, and saturate on overflow. struct.mode = 'fixed'; struct.roundmode = 'floor'; struct.overflowmode = 'saturate'; struct.format = [8 0]; % 8位二进制数,0位小数,默认1位符号位 q=quantizer(struct); miu1_real = zeros(32,32); for i = 1:32 miu1_real(:,i) = i; end miu1_imag = miu1_real; % 量化值与实际值的误差 q_miu1_real = quantize(q,miu1_real); q_miu1_imag = quantize(q,miu1_imag); disp("最大量化误差"); disp(max(max([abs(miu1_real-q_miu1_real),abs(miu1_imag-q_miu1_imag)]))); % 按行转为列向量 real_o = num2bin(q, reshape(miu1_real', [], 1)); imag_o = num2bin(q, reshape(miu1_imag', [], 1)); % 按列转为列向量 % real_o = num2bin(q,miu1_real(:)); % imag_o = num2bin(q,miu1_imag(:)); %% 将数据写入TXT fid1=fopen('F:\MyTest\FPGA\IPFFT2\IPFFT2.srcs\sources_1\script/real_order.txt','wt'); fid2=fopen('F:\MyTest\FPGA\IPFFT2\IPFFT2.srcs\sources_1\script/imag_order.txt','wt'); for i=1:32*32 fwrite(fid1,real_o(i,:)); fprintf(fid1,'\n'); fwrite(fid2,imag_o(i,:)); fprintf(fid2,'\n'); end fclose(fid1); fclose(fid2); 

数据
fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第6张
imag_order内容一致

产生转置矩阵

close all; clear; clc %% 生成方阵 a = 1:32*32; a_exp = reshape(a, 32, 32); a_exp = a_exp'; disp(a_exp); %% 产生转置系数 m = 32; n = 32; % addr = (i-1)*n+j; addr = 1:32*32; % disp(addr); i = floor((addr-1)/n) + 1; j = mod((addr-1),n) + 1; addr_t = (j-1)*m+i; addr_t = addr_t-1; %0开始 %% 利用转置系数对方阵进行转置 b = zeros(1, 32*32); for i = 1:32*32 b(i) = a(addr_t(i)+1); end b_shrink = reshape(b, 32, 32); b_shrink = b_shrink'; disp(b_shrink); %% 生成coe N = 32*32; fid = fopen('F:\MyTest\FPGA\IPFFT2\IPFFT2.srcs\sources_1\script/tran_matrix_para_1024.coe','wt'); %- standard format fprintf( fid, 'memory_initialization_radix = 10;\n'); fprintf( fid, 'memory_initialization_vector =\n'); %- write data in coe file for i = 1:1:N if(i == N) fprintf(fid,'%d;',addr_t(i)); else fprintf(fid,'%d,\n',addr_t(i)); end end fclose(fid); 

数据
fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第7张

7 HDL

仿真文件

module tb_ip_fft2; reg clk; reg rst_n; reg [7:0] data_real [1023:0]; reg [7:0] data_imag [1023:0]; reg [7:0] dati_in; reg [7:0] datq_in; wire [15:0] fifo_din; reg [9:0] count=0; integer i; initial begin clk=1; rst_n=0; dati_in=0; datq_in=0; // (1:32)*32 $readmemb("F:/MyTest/FPGA/IPFFT2/IPFFT2.srcs/sources_1/script/real_order.txt",data_real); $readmemb("F:/MyTest/FPGA/IPFFT2/IPFFT2.srcs/sources_1/script/imag_order.txt",data_imag); // for(i=0; i<127; i=i+1) // $display("%h %h", data_real[i], data_imag[i]); #100 rst_n=1; end always #5 clk=~clk; assign fifo_din = { 
   datq_in, dati_in}; top u_top ( .clk ( clk ), .rst_n ( rst_n ), .fifo_din ( fifo_din ), .fifo_wr_en_pre ( fifo_wr_en_pre ) ); always @(posedge clk) begin if (!rst_n) begin count <= 1'b0; dati_in <= 1'b0; datq_in <= 1'b0; end else if ( fifo_wr_en_pre ) begin dati_in <= data_real[count]; datq_in <= data_imag[count]; count <= count+1'b1; end else begin count <= count ; dati_in <= dati_in ; datq_in <= datq_in ; end end endmodule 

顶层文件

module top( input clk , input rst_n , input [15:0] fifo_din , output fifo_wr_en_pre ); wire fifo_wr_en ; // wire fifo_wr_en_pre ; wire fifo_rd_en ; wire [1:0] fifo_rd_en_pre ; wire [15:0] fifo_dout ; wire [27 : 0] ram_douta ; ip_fifo u_ip_fifo ( .clk ( clk ), .rst_n ( rst_n ), .fifo_din ( fifo_din ), .fifo_dout ( fifo_dout ), .fifo_wr_en ( fifo_wr_en ), .fifo_wr_en_pre ( fifo_wr_en_pre ), .fifo_rd_en ( fifo_rd_en ), .fifo_rd_en_pre ( fifo_rd_en_pre ) ); //======================================= ip_ram u_ip_ram ( .clk ( clk ), .rst_n ( rst_n ), .fifo_rd_en_pre ( fifo_rd_en_pre ), .fifo_dout ( fifo_dout ), .ram_douta ( ram_douta ) ); endmodule 

FIFO顶层文件

module ip_fifo( input clk , input rst_n , input [15:0] fifo_din , output [15 : 0] fifo_dout , output fifo_wr_en , output fifo_wr_en_pre , output fifo_rd_en , output [1:0] fifo_rd_en_pre ); // wire [15 : 0] fifo_dout ; wire full ; wire empty ; wire [9 : 0] data_count ; // wire fifo_wr_en ; wire almost_full ; wire almost_empty ; fifo_generator_0 u_fifo ( .clk (clk), // input wire clk .din (fifo_din), // input wire [15 : 0] din .wr_en (fifo_wr_en), // input wire wr_en .rd_en (fifo_rd_en), // input wire rd_en .dout (fifo_dout), // output wire [15 : 0] dout .full (full), // output wire full .almost_full (almost_full), // output wire almost_full .empty (empty), // output wire empty .almost_empty (almost_empty), // output wire almost_empty .data_count (data_count) // output wire [9 : 0] data_count ); fifo_wr u_fifo_wr ( .clk ( clk ), .rst_n ( rst_n ), .almost_empty ( almost_empty ), .almost_full ( almost_full ), .fifo_din ( fifo_din ), .fifo_wr_en_pre ( fifo_wr_en_pre ), .fifo_wr_en ( fifo_wr_en ) ); fifo_rd u_fifo_rd ( .clk ( clk ), .rst_n ( rst_n ), .fifo_out ( fifo_dout ), .almost_full ( almost_full ), .almost_empty ( almost_empty ), .fifo_rd_en ( fifo_rd_en ), .fifo_rd_en_pre ( fifo_rd_en_pre ) ); endmodule 

FIFO读

module fifo_rd( input clk, input rst_n, input [15:0] fifo_out, input almost_full, input almost_empty, output reg fifo_rd_en, output reg [1:0] fifo_rd_en_pre ); // reg fifo_rd_en; reg [1:0] state; reg almost_full_d0; reg almost_full_syn; reg [3:0] dly_cnt; always @(posedge clk ) begin if (!rst_n) begin almost_full_d0 <= 1'b0; almost_full_syn <= 1'b0; end else begin almost_full_d0 <= almost_full; almost_full_syn <= almost_full_d0; end end always @(posedge clk ) begin if (!rst_n) begin fifo_rd_en_pre[0] <= 1'b0; state <= 2'd0; dly_cnt <= 4'd0; end else case (state) 2'd0: if(almost_full_syn) state <= 2'd1; else state <= state; 2'd1: if (dly_cnt == 4'd9) begin dly_cnt <= 4'd0; state <= 2'd2; end else dly_cnt <= dly_cnt +1'b1; 2'd2: if (almost_empty) begin fifo_rd_en_pre[0] <= 1'b0; state <= 2'd3; end else fifo_rd_en_pre[0] <= 1'b1; 2'd3: state <= state; default: state <= 2'd0; endcase end always @(posedge clk ) begin fifo_rd_en_pre[1] <= fifo_rd_en_pre[0]; fifo_rd_en <= fifo_rd_en_pre[1]; end endmodule 

FIFO写

module fifo_wr( input clk, input rst_n, input almost_empty, input almost_full, input [15:0] fifo_din , output reg fifo_wr_en, output reg fifo_wr_en_pre // 涓轰簡娑堥櫎鎵撲竴鎷嶅fifo杈撳叆鐨勫奖鍝� ); reg [1:0] state; reg almost_empty_d0; reg almost_empty_syn; reg [3:0] dly_cnt; reg [15:0] fifo_wr_data; //  always @(posedge clk ) begin if (!rst_n) begin almost_empty_d0 <= 1'b0; almost_empty_syn <= 1'b0; end else begin almost_empty_d0 <= almost_empty; almost_empty_syn <= almost_empty_d0; end end always @(posedge clk ) begin if (!rst_n) begin fifo_wr_en_pre <= 1'b0; fifo_wr_data <=16'd0; state <= 2'd0; dly_cnt <= 4'd0; end else begin case (state) // 绛夊緟FIFO绌轰俊鍙� 2'd0: if (almost_empty_syn) state <= 2'd1; else state <= state; // 寤舵椂 2'd1: if (dly_cnt == 4'd9) begin dly_cnt <= 4'd0; state <= 2'd2; fifo_wr_en_pre <= 1'b0; // 姝ゅ涓�1鐨勮瘽锛屽垯榛樿鏁版嵁浼氳鍐欏叆 end else dly_cnt <= dly_cnt +4'd1; // 鍐欐暟鎹� 2'd2: if (almost_full) begin fifo_wr_en_pre <=1'b0; fifo_wr_data <= 16'h0; state <= 2'd3; end else begin fifo_wr_en_pre <=1'b1; fifo_wr_data <= fifo_wr_data +1'd1; end // 姝诲惊鐜� 2'd3: state <= state; default: state <= 2'd0; endcase end end always @(posedge clk ) begin fifo_wr_en <= fifo_wr_en_pre; end endmodule 

RAM顶层文件

module ip_ram( input clk , input rst_n , input [15:0] fifo_dout , input [1:0] fifo_rd_en_pre , output [27 : 0] ram_douta ); // ==========rom============== reg [9:0] rom_addra; reg [9:0] rom_addra_pre; wire [10 : 0] rom_douta; reg rom_ena; //===========ram ============== reg ram_ena ; reg [0 : 0] ram_wea ; reg [9 : 0] ram_addra ; reg [27 : 0] ram_dina ; //============================= reg [1:0] state; parameter START = 2'd0, WRITE = 2'd1, READ = 2'd2, WAIT = 2'd3; reg [9:0] ram_read_counter; always @(posedge clk ) begin if(!rst_n) begin ram_read_counter <= 10'b0; end else begin if(state == READ) ram_read_counter <= ram_read_counter + 1'b1; end end always @(posedge clk ) begin if(!rst_n)begin state <= START; end else begin case(state) START: if (fifo_rd_en_pre[0] == 1'b1) begin state <= WRITE; end else begin state <=state; end // 鍐檙am WRITE: if (fifo_rd_en_pre[0] == 1'b1) begin state <= state; end else begin state <= READ; end // read ram READ: if(ram_read_counter == 10'd1023) state <= WAIT; else state <= state; // if (fifo_rd_en_pre[0] == 1'b0) begin // state <= state; // end // else begin // state <= WAIT; // end WAIT: state <= state; default: state <= START; endcase end end always @(posedge clk ) begin if(!rst_n) begin ram_wea <= 1'b0; end else begin case (state) START: ram_wea <= 1'b0; WRITE: ram_wea <= 1'b1; READ : ram_wea <= 1'b0; WAIT : ram_wea <= 1'b0; default: ram_wea <= 1'b0; endcase end end always @(posedge clk ) begin if(!rst_n) begin ram_ena <= 1'b0; end else begin case (state) START: ram_ena <= 1'b0; WRITE: ram_ena <= 1'b1; READ : ram_ena <= 1'b1; WAIT : ram_ena <= 1'b0; default: ram_ena <= 1'b0; endcase end end always @(posedge clk ) begin if(!rst_n)begin ram_addra <= 10'b0; end else begin case (state) START: ram_addra <= 10'b0; WRITE: ram_addra <= rom_douta; READ : ram_addra <= ram_addra + 1'b1; WAIT : ram_addra <= 10'b0; default: ram_addra <= 10'b0; endcase end end always @(posedge clk ) begin if(!rst_n)begin ram_dina <= 28'b0; end else begin case (state) START: ram_dina <= 28'b0; WRITE: ram_dina <= fifo_dout; READ : ram_dina <= 28'b0; WAIT : ram_dina <= 28'b0; default: ram_dina <= 28'b0; endcase end end ram_wr u_ram_wr ( .clk ( clk ), .rst_n ( rst_n ), .fifo_dout ( fifo_dout ), .fifo_rd_en_pre ( fifo_rd_en_pre ), .rom_douta ( rom_douta ), .ram_ena ( ram_ena ), .ram_wea ( ram_wea ), .ram_addra ( ram_addra ), .ram_dina ( ram_dina ) ); blk_mem_gen_0 u_ram ( .clka (clk), // input wire clka .ena (ram_ena), // input wire ena .wea (ram_wea), // input wire [0 : 0] wea .addra (ram_addra), // input wire [9 : 0] addra .dina (ram_dina), // input wire [27 : 0] dina .douta (ram_douta) // output wire [27 : 0] douta ); // ============rom============================== always @(posedge clk ) begin if(!rst_n)begin rom_ena <= 1'b0; end else begin case (state) START: rom_ena <= 1'b0; WRITE: rom_ena <= 1'b1; READ : rom_ena <= 1'b0; WAIT : rom_ena <= 1'b0; default: rom_ena <= 1'b0; endcase end end always @(posedge clk ) begin if(!rst_n)begin rom_addra <= 10'b0; rom_addra_pre <= 10'b0; end else begin case (state) START: rom_addra_pre <= 10'b0; WRITE: rom_addra_pre <= rom_addra_pre + 1'b1; READ : rom_addra_pre <= 10'b0; WAIT : rom_addra_pre <= 10'b0; default: rom_addra_pre <= 10'b0; endcase rom_addra <= rom_addra_pre; // 鐢变簬ena鏃讹紝addr浠�1寮�濮嬶紝鎵�浠ユ墦涓媿瀛愪粠0寮�濮� end end blk_mem_gen_1 u_rom ( .clka (clk) , // input wire clka .ena (rom_ena) , // input wire ena .addra (rom_addra) , // input wire [9 : 0] addra .douta (rom_douta) // output wire [10 : 0] douta ); // ===================================== endmodule 

8 IP配置

FIFO

fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第8张
fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第9张
fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第10张
fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第11张
fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第12张

RAM

fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第13张
fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第14张
fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第15张

fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第16张

ROM

fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第17张
fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第18张
fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第19张
fpga矩阵转置_matlab 转置_https://bianchenghao6.com/blog__第20张

9 Reference

  1. 李汉清. 基于FPGA的快速原地转置算法. 电子测量技术. 2015;38(11):46-50.

都看到这了,点个赞吧!

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

上一篇

已是最后文章

下一篇

已是最新文章

发表回复