matlab联合vivada创建FIR滤波器

本文介绍了利用Matlab联合Vivado创建FIR滤波器的过程。先使用Matlab生成.coe文件作为Vivado的IP文件,再生成两个不同频率波叠加后的采样数据,以16进制写入文本文件作为仿真输入波形。还提及了Matlab和Vivado部分的参考内容,以及遇到的进制转换等问题及解决办法。

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

matlab联合vivada创建FIR滤波器

整体过程:利用matlab生成.coe 作为vivado的IP文件 接着利用matlab生成两个不同频率波s1 s2 并叠加生成s采样数据以16进制写入文本文件 作为仿真输入波形 查看滤波器效果

1、matlba部分

  1. 创建一个fir滤波器 参考如下公众号:FIR滤波器matlab部分
  2. 其中各部分想要补充的:在这里插入图片描述在这里插入图片描述

这是一些参数的描述 后面就是 file export–> target .coe file

2、vivado部分

同样参考上述链接 fir滤波器
其中想要补充对代码的一些理解:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2023/10/06 16:21:48
// Design Name: 
// Module Name: fir_ip_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module fir_ip_tb(
    );
    reg clk;
    reg [15:0] data_in;
    wire [31:0] data_out;
    wire data_out_valid;
    wire data_in_ready;
    //Instantiate a Module
   design_1_wrapper U1_design_1_wrapper
   (
     .M_AXIS_DATA_0_tdata (data_out),
     .M_AXIS_DATA_0_tvalid(data_out_valid),
     .S_AXIS_DATA_0_tdata(data_in),
     .S_AXIS_DATA_0_tready(data_in_ready),
     .S_AXIS_DATA_0_tvalid(1'b1),
     .aclk_0(clk)
    );
    initial begin 
        clk = 0;
    end
    
    always #16 clk = ~clk;
	//get the data from the file named s1_s2_bit.txt 
parameter data_num = 64;
integer Pattern;
reg [15:0] stimulus[1:data_num];//upon the length of reg 16bit so each data is 16bit
initial
begin
    $readmemh("D:/FPGA_MATLAB/s1_s2_bit.txt",stimulus);//Read Hexadecimal Data it is important that you have to save data in the way of hex and each data needs to be on a new line
	Pattern=0;
	repeat(30) begin 
        repeat(data_num) begin
			Pattern = Pattern+1;
			data_in = stimulus[Pattern];
			#32;
        end
        Pattern = 0;
    end 
    #500;
    $stop;
end


//Write the generated data to the file data_out.txt.
integer file_out;
initial 
begin                                                  
	file_out = $fopen("D:/FPGA_MATLAB/data_out.txt");
	if(!file_out)
		begin
			$display("could not open file!");
			$finish;
		end
end

wire signed [31:0] data_out_signed;
assign data_out_signed = data_out;
always @(posedge clk )
begin 
    if(data_out_valid) begin 
	   $fdisplay(file_out,"%d",data_out_signed);
    end 
end     
endmodule

下面会有s1_s2_bit.txt文件的内容

3、遇到的一些问题 (还有待解决)

关于生成波数据存储方式的问题:

f1 = 0.5;   %信号1频率为 500 kMZ
f2 = 5;     %信号2频率为 5   MHZ
Fs = 32;    %采样频率为  32  MHZ
N = 16;     %量化位数
N_2 = 18;
%产生信号
t = 0:1/Fs:5;   %0为开头 1/Fs为步进值 5为结尾的一系列数 用于生成函数点
c1 = 2*pi*f1*t;
c2 = 2*pi*f2*t;

f1 = 0.5;   %信号1频率为 500 kMZ
f2 = 5;     %信号2频率为 5   MHZ
Fs = 32;    %采样频率为  32  MHZ
N = 16;     %量化位数

%产生信号
t = 0:1/Fs:5;   %0为开头 1/Fs为步进值 5为结尾的一系列数 用于生成函数点
c1 = 2*pi*f1*t;
c2 = 2*pi*f2*t;

s1 = sin(c1);
s2 = sin(c2);
s = s1+s2;  %两个单波载波合成的信号

%绘图
subplot(2,2,1);
plot(c1,s1);
title('s1');
subplot(2,2,2);
plot(c2,s2);
title('s2');
s = s/max(abs(s));
subplot(2,2,3);
plot(s);
title('s');

%16比特量化
Q_s = round(s*(2^(N-1)-1));

%将生成的数以十进制写入txt文件中
fid = fopen('D:\FPGA_MATLAB\s1_s2.txt','w');
fprintf(fid,'%16d\r\n',Q_s);
fprintf(fid,";");
fclose(fid);

i = 1;  %1开始,因为在 MATLAB 中数组索引是从1开始的
%下面进行10进制转换成16进制的操作
while i < 162
    if Q_s(i) < 0
        Q_s(i) = Q_s(i) + 65536;
    end
    i = i + 1;
end

disp(Q_s);

Q_s = dec2hex(Q_s);
disp(Q_s);

fia = fopen('D:\FPGA_MATLAB\s1_s2_bit.txt','w');
fprintf(fia,'%s\r\n',Q_s);
fprintf(fia,";");
fclose(fia);

关于带符号10进制转成16进制:dec2hex()只能转换正数
关于负数只需将10进制负数加上65536(2的16次方)就将全部数字转换成0-65535
我的理解是0-32768表述的是0-32768
而从 32769-65535表示 -32768–1
详情参考进制转换

实际上输出到s1_s2_bit.txt的内容是:

在这里插入图片描述
(离谱 找不到问题出在哪)

索性直接把disp显示的数据c_v到下面的文件中

以下是采用上述c_v大法的文件数据
在这里插入图片描述
找到问题了 最后代码这样改进:
在这里插入图片描述
感谢这位老哥
在这里插入图片描述

波形
在这里插入图片描述
matlab仿真的波形:
在这里插入图片描述

### 实现LED数码管显示学号最后八位的设计方法 #### 设计概述 为了实现在FPGA开发板上通过LED数码管显示学号的最后8位,需要完成以下几个方面的工作: - 使用Vivado工具创建项目并配置目标器件。 - 编写Verilog代码来定义逻辑功能,特别是用于驱动7段数码管的部分。 - 设置定时器或分频器以控制刷新频率。 - 将待显示的数据映射到相应的7段编码。 #### Vivado环境设置 启动Vivado后新建工程,指定所使用的FPGA型号(如EGO1),然后按照向导逐步建立RTL设计文件夹结构。确保选择了正确的部分和版本以便于后续编译与仿真[^1]。 #### Verilog代码实现 下面是一个简单的例子展示如何利用Verilog编程让7段显示器显示出特定数值。此实例假设已经有一个模块负责提供秒级时间基准信号`clk_1hz`作为输入给本模块;同时假定存在一个外部按钮`btn_rst_n`用来触发重置操作。 ```verilog module show_last_eight_digits ( input wire clk, // 主时钟源 input wire rst_n, // 复位信号(低电平有效) output reg [6:0] seg_led,// 连接到7段显示屏的线 ); // 定义内部寄存器保存当前要显示的数字 reg [3:0] current_digit; // 存储学号最后8位数对应的BCD码数组 parameter DIGITS = 8'b0000_0101; // 假设这里填入学号最后一位对应二进制表示形式 initial begin current_digit <= 4'd0; end always @(posedge clk or negedge rst_n) begin : proc_current_digit if (!rst_n) begin current_digit <= 4'd0; end else begin case (current_digit) 4'd0: current_digit <= DIGITS[7:4]; 4'd1: current_digit <= DIGITS[3:0]; default: current_digit <= 4'd0; endcase end end // 转换函数:将4bit BCD转换成7-seg pattern function automatic [6:0] bcd_to_seg(input [3:0]bcd); case(bcd) 4'h0: return 7'b1000000; 4'h1: return 7'b1111001; ... // 继续补充其他情况... default: return 7'bx; endcase endfunction assign seg_led = ~bcd_to_seg(current_digit); // 取反是因为有些屏幕采用共阴极连接方式 endmodule ``` 请注意上述代码片段仅展示了基本框架,并未完全填充所有可能的情况。对于完整的应用来说还需要考虑更多细节比如多位数之间的切换机制等[^2]。 #### 测试平台搭建 构建Testbench来进行初步的功能验证是非常重要的一步。这有助于确认设计能否按预期工作,在正式烧录至物理芯片前发现潜在错误。可以参照如下模板编写测试脚本: ```verilog module tb_show_last_eight_digits(); reg clk_tb; reg rst_n_tb; wire [6:0] seg_led_tb; initial begin $dumpfile("wave.vcd"); $dumpvars(0,tb_show_last_eight_digits); clk_tb = 0; forever #5ns clk_tb =~ clk_tb; end initial begin rst_n_tb = 0; #10ns; rst_n_tb = 1; // 更多激励条件可以根据具体需求添加 #1us; $finish; end show_last_eight_digits uut( .clk(clk_tb), .rst_n(rst_n_tb), .seg_led(seg_led_tb) ); endmodule ``` 这段代码会生成波形记录文件(`wave.vcd`)供观察者分析电路行为模式。此外还包含了周期性的时钟发生器以及初始化过程中的复位序列模拟[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值