从Matlab到FPGA(Matlab生成coe文件或mem文件)

本文介绍如何将MATLAB中的滤波器设计转化为FPGA可实现的形式,包括输出滤波器系数为COE文件、生成RAM初始化文件及通过Verilog进行数据交互的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当定点仿真完成后,就需要使用FPGA实现。

这时候需要把之前仿好的滤波器参数或者输入信号输出为coes文件:

%% output coe file
Ff = fimath('CastBeforeSum', 0, 'OverflowMode', 'Saturate', ...
            'RoundMode', 'round', 'ProductMode', 'SpecifyPrecision', 'SumMode', 'SpecifyPrecision', ...
            'ProductWordLength', 16, 'ProductFractionLength', 15, 'SumWordLength', 16, 'SumFractionLength', 15);
Tf = numerictype('WordLength', 16, 'FractionLength', 15);
wr = 'ram';  % select the output type
outset = fi(hmc.Numerator, Tf, Ff);  % the filter need to be outputted, datatype:fi
outset_len = length(outset);
fp = fopen('D:\tmp\fpga_matlab\FIR.coe','w');
if( strcmp(wr, 'ram') )
fprintf( fp, 'MEMORY_INITIALIZATION_RADIX=16;\n' );
fprintf( fp, 'MEMORY_INITIALIZATION_VECTOR=\n' );
elseif( strcmp(wr, 'fir') )
fprintf( fp, 'radix=10;\n' );
fprintf( fp, 'coefdata=\n' );
end
for i = 1:outset_len
    out = outset(i);
    if( strcmp(wr, 'ram') )
        out_r = real(out); %ram
        out_i = imag(out);
        fprintf(fp, '%s%s\n', out_i.hex, out_r.hex);
    elseif( strcmp(wr, 'fir') )
        out = outset(i);  %fir
        fprintf(fp, '%.17f\n', out);
    end
end
fclose(fp);

由于滤波器在仿真中一个结构体,所以把里面的参数变成fi对象,这样可以很方便输出十六进制或者二进制之类。

这里代码还提供了RAM的coe文件输出的选择。

这样,使用IP核的时候就可以把这些文件拖进去。

也可以使用原语的方式实现RAM,这样可以很方便地移植代码,如下:

xpm_memory_sdpram # (

  // Common module parameters
  .MEMORY_SIZE        (4096),            //positive integer
  .MEMORY_PRIMITIVE   ("auto"),          //string; "auto", "distributed", "block" or "ultra";
  .CLOCKING_MODE      ("common_clock"),  //string; "common_clock", "independent_clock" 
  .MEMORY_INIT_FILE   (file),          //string; "none" or "<filename>.mem" 
  .MEMORY_INIT_PARAM  (""    ),          //string;
  .USE_MEM_INIT       (1),               //integer; 0,1
  .WAKEUP_TIME        ("disable_sleep"), //string; "disable_sleep" or "use_sleep_pin" 
  .MESSAGE_CONTROL    (0),               //integer; 0,1
  .ECC_MODE           ("no_ecc"),        //string; "no_ecc", "encode_only", "decode_only" or "both_encode_and_decode" 
  .AUTO_SLEEP_TIME    (0),               //Do not Change

  // Port A module parameters
  .WRITE_DATA_WIDTH_A (16),              //positive integer
  .BYTE_WRITE_WIDTH_A (16),              //integer; 8, 9, or WRITE_DATA_WIDTH_A value
  .ADDR_WIDTH_A       (8),               //positive integer

  // Port B module parameters
  .READ_DATA_WIDTH_B  (16),              //positive integer
  .ADDR_WIDTH_B       (8),               //positive integer
  .READ_RESET_VALUE_B ("0"),             //string
  .READ_LATENCY_B     (2),               //non-negative integer
  .WRITE_MODE_B       ("no_change")     //string; "write_first", "read_first", "no_change" 

) xpm_memory_sdpram_inst (

  // Common module ports
  .sleep          (1'b0),

  // Port A module ports
  .clka           (clk),
  .ena            (1'b1),
  .wea            (enw),
  .addra          (waddr),
  .dina           (wdata),
  .injectsbiterra (1'b0),
  .injectdbiterra (1'b0),

  // Port B module ports
  .clkb           (clk),
  .rstb           (1'b0),
  .enb            (1'b1),
  .regceb         (1'b1),
  .addrb          (raddr),
  .doutb          (rdata),
  .sbiterrb       (),
  .dbiterrb       ()
);
这样就例化了一个读写RAM

这里RAM的初始化数据是mem文件,可以用如下Matlab代码输出:

outset = [0;ER1];
outset = fi(outset, T, F);  % the filter need to be outputted, datatype:fi
outset_len = length(outset);
fp = fopen('D:\tmp\fpga_matlab\ER1.mem','w');
for i = 1:outset_len
    out = outset(i);
    fprintf(fp, '@%04x %04x\n', (i-1), out.int);
end
fclose(fp);

使用Verilog测试时,需要读取txt文件的数据输入仿真的模块,并把输出的数据保存到txt再用Matlab读取出来分析,Matlab侧输出数据到txt的代码如下:

%% output fi object
outset = RR;%fi(Tx, T, F);  % the filter need to be outputted, datatype:fi
outset_len = length(outset);
% if(outset_len>10000)
%     outset_len = 10000;
% end
fp = fopen('D:\tmp\fpga_matlab\Tx.txt','w');
for i = 1:outset_len
    out = outset(i);
    r_out = real(out);
    i_out = imag(out);
    fprintf(fp, '%s %s\n', r_out.dec, i_out.dec);
end
fclose(fp);

Matlab侧读取txt的代码为:

%% input fi object
fp = fopen('D:\tmp\fpga_matlab\Rx.txt','r');
in = textscan(fp, '%s');
fclose(fp);
ins = in{1,1};
in_l = length(ins);
rx = zeros( in_l/2, 1 );
for i = 1:2:in_l
    in_r = str2double(ins{i});
    in_i = str2double(ins{i+1});
    rx( (i+1)/2 ) = in_r/(2^14) + 1j*in_i/(2^14);
end
对应的verilog代码如下:
integer fp_r, fp_w, cnt, r_n, w_n;
// read data
initial begin
	fp_r = $fopen("D:/tmp/fpga_matlab/Tx1.txt", "r");
	r_n = 0;
	s_axis_data_tvalid = 0;
	s_axis_data_tdata = 0;
	wait(rst_n==1);
	@(posedge clk)
	while(!$feof(fp_r)) begin
	#1
	cnt = $fscanf(fp_r, "%d %d", data_in_I, data_in_Q);
	r_n = r_n + 1;
	s_axis_data_tdata = { data_in_Q[15:0], data_in_I[15:0] };
	s_axis_data_tvalid = 1;
	@(posedge clk);
	#1
	s_axis_data_tvalid = 0;
	#(1*PERIOD);
	end
	s_axis_data_tvalid = 0;
	s_axis_data_tdata = 0;
	$fclose(fp_r);
end

// write data
initial begin
	fp_w = $fopen("D:/tmp/fpga_matlab/Tx2_fpga.txt","w");//以写的方式打开文件
	w_n = 0;
	@(posedge m_axis_data_tvalid)
	while(m_axis_data_tvalid)
	begin
		@(posedge clk)
		data_out_I = m_axis_data_tdata[15:0];
		data_out_Q = m_axis_data_tdata[31:16];
		$fwrite(fp_w,"%d %d\n", $signed(data_out_I), $signed(data_out_Q));
		w_n = w_n + 1;
	end
	$fclose(fp_w);
end


### 如何使用MATLAB创建COE文件 #### 创建COE文件的基础方法 COE文件通常用于定义FPGA中的ROMRAM初始内容。通过MATLAB可以很方便地生成这种类型的文件,下面是一个简单的例子说明如何实现这一点。 为了创建一个COE文件,在MATLAB脚本中首先要指定要写入的数据以及一些必要的参数,比如数据宽度和地址深度等[^1]: ```matlab % 定义内存的位宽 (Memory Bit Width) mem_width = 8; % 定义内存的深度 (Memory Depth, 即地址数量) mem_depth = 256; % 初始化数据向量,这里假设我们填充的是全0 data_vector = zeros(1, mem_depth); % 者自动生成特定模式的数据序列作为示例, % 这里采用线性递增的方式填充数据 for i = 1:mem_depth data_vector(i) = mod((i-1), 2^mem_width); end ``` 接着构建COE文件的具体内容字符串并保存到目标位置: ```matlab % 构建coe文件头信息 header_str = sprintf('memory_initialization_radix=%d;\n', ... 'memory_initialization_vector=\n'); % 将数值转换成十六进制表示形式,并组合成一行多行文本 hex_data_lines = arrayfun(@(x)sprintf('%X', x), data_vector, 'UniformOutput', false); formatted_hex_line = strjoin(hex_data_lines,',\n','Data'); content_str = [header_str formatted_hex_line ';']; % 设置coe文件路径及名称 file_name = 'example_memory_content.coe'; % 打开文件准备写入 fid = fopen(file_name,'w'); % 写入文件头部信息加上实际数据部分 fprintf(fid,'%s\n%s;', header_str, strjoin(hex_data_lines, ',\n')); % 关闭文件句柄完成操作 fclose(fid); disp(['COE 文件已成功创建:', file_name]); ``` 上述代码片段展示了怎样利用MATLAB编写程序来自动生成所需的COE文件。此过程涉及设置好基本属性之后再按照一定规则格式化输出所需的内容至外部文件。 对于更复杂的应用场景,如生成正弦波、三角波等形式的记忆体映射表,则可以通过调整`data_vector`内的算法逻辑来满足需求[^2]。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值