F P G A FPGA FPGA实验
文章目录
- F P G A FPGA FPGA实验
-
- 实验目的
- 实验要求
- 实验环境
- 实验原理
- 实验结果及分析
-
- 顶层模块
- 混频模块
-
- 输入信号处理
- 调制
- 载波控制模块
-
- 载波幅值
- 状态机
- 解调模块
- 滤波器模块
- 锁相环模块
- 仿真文件
-
- 系统时钟
- 定义复位和停止时间
- 读取数据
- 存放数据
- 数据对比
- 实验总结
- 附录
-
- 顶层模块
- 混频模块
- 载波控制模块
- 解调模块
- T e s t b e n c h Testbench Testbench
- 生成原始信号数据
- 数据验证
实验目的
- 了解正交调制解调的原理和实现方法
- 学会 I P IP IP核的使用
- 学会利用 m o d e s i m modesim modesim进行仿真
实验要求
- 相关参数: (1)直线阵通道数: 96 96 96 (2)信号频率: 10 k H z 10kHz 10kHz (3)采样率: 400 k H z 400kH 400kHz (4)低通滤波器阶数: 64 64 64 (5)低通滤波器截止频率: 20 k H z 20kHz 20kHz
- 技术要求: (1)结合上述参数完成正交变换(混频+低通滤波),其中混频通过 V e r i l o g Verilog Verilog逻辑代码实现,低通滤波通过 I P IP IP核实现 (2)低通滤波器参数结合上述参数采用 M a t l a b Matlab Matlab计算 (3)通道信号可以采用正弦波,结合上述参数及参考 M a t l a b Matlab Matlab程序仿真生成 (4)仿真生成的通道数据使用方式参考测试平台参考程序
- 提交成果: (1) M o d e l s i m Modelsim Modelsim仿真结果 (2) M a t l a b Matlab Matlab计算结果与 M o d e l s i m Modelsim Modelsim仿真结果的对比结果
实验环境
- Q u a r t u s 18.0 Quartus18.0 Quartus18.0
- M o d e l S i m − I n t e l F P G A S t a r t e r E d i t i o n 10.5 b ( Q u a r t u s P r i m e 18.0 ) ModelSim - Intel FPGA Starter Edition 10.5b (Quartus Prime 18.0) ModelSim−IntelFPGAStarterEdition10.5b(QuartusPrime18.0)
实验原理
为了提高频谱利用率,通信系统通常采用正交调制解调,如下图所示分别为正交调制解调的原理的实现方法:
在调制端,分别输入信号的实部和虚部,实部和虚部信号分别与 c o s ω 0 t cos\omega_{0}t cosω0t和 − s i n ω 0 t -sin\omega_{0}t −sinω0t相乘,再将两路信号相加后可以得到调制信号。
在解调端,将经过信号的调制信号分为两路,在分别与两路互相正交的信号 c o s ω 0 t cos\omega_{0}t cosω0t和 − s i n ω 0 t -sin\omega_{0}t −sinω0t相乘,再分别经过低通滤波器,可以得出解调信号。
实验结果与分析
本次试验中并非严格按照正交调制解调的的原理进行实验,试验中的两路基带信号为 96 96 96路 C W CW CW信号,而非信号实部和虚部,载波频率为 400 k H z 400kHz 400kHz, C W CW CW信号频率为 10 k H z 10kHz 10kHz,系统时钟频率为 100 M H z 100MHz 100MHz
整个工程主要分为四个部分:顶层模块,混频模块, F I R FIR FIR滤波器模块,锁相环模块
顶层模块
对各模块进行例化
混频模块
输入信号处理
assign signal = data-14'd8192;
在实际情况中,处理数据应为 A D AD AD模块量化后的读取信号,所得到的数据为整数,因此需要先对输入数据进行第一步处理,根据 A D AD AD量化精度将信号恢复为有符号数值,本次实验输入数据幅值为 1 − 16384 1-16384 1−16384,即 14 b i t 14bit 14bit数据,因此需对原始数据减去 8192 8192 8192。
调制
两路信号分别与正弦和余弦载波相乘,然后相加得到调制信号
signal_1 <= signal*carrier_cos; // 中间变量,用来debug和调整时序
signal_2 <= signal*carrier_sin;
signal_output <= signal*carrier_cos+signal*carrier_sin;
载波控制模块
载波幅值
载波频率为 100 k H z 100kHz 100kHz,采样频率为 400 k H z 400kHz 400kHz,因此可认为在载波的一个周期内,只采集到四个数据,可以将四个数据特殊化为 1 , 0 , − 1 , 0 1, 0, -1, 0 1,0,−1,0,并采用一个 400 k H z 400kHz 400kHz时钟作为触发时钟,每到时钟上升沿触发,载波数据改变到下一个点,调制解调时需要同步载波,因此将载波生成放入另一模块中
always @(posedge clk_400K) begin
if (!rst_n) begin
cnt_4_sin <= 3'd0;
cnt_4_cos <= 3'd0;
end
else begin
cnt_4_cos <= cnt_4_cos+1'b1;
cnt_4_sin <= cnt_4_sin+1'b1;
if(cnt_4_cos==3)begin
cnt_4_cos <= 3'd0;
end
if(cnt_4_sin==3)begin
cnt_4_sin <= 3'd0;
end
end
end
状态机
根据计数器数值确定载波下一个的状态
always @(posedge clk) begin
if(!rst_n)begin
carrier_cos <= 2'd0;
carrier_sin <= 2'd0;
end
else begin
case(cnt_4_cos)
3'd0: carrier_cos <= 2'b1;
3'd1: carrier_cos <= 2'b0;
3'd2: carrier_cos <= -2'b1;
3'd3: carrier_cos <= 2'b0;
endcase
case(cnt_4_sin)
3'd0: carrier_sin <= 2'b0;
3'd1: carrier_sin <= 2'b1;
3'd2: carrier_sin <= 2'b0;
3'd3: carrier_sin <= -2'b1;
endcase
end
end
下图所示三个信号分别为读入信号和分别与两路正交信号相乘得出的信号
解调模块
解调应分为两部分:与同相载波相乘;过低通滤波器
解调模块中只负责将调制信号分别与两路同相正交载波相乘,本次实验在同一工程下实现调制解调,不需要考虑载波相位问题,实际工程中需要加入valid
信号控制保证载波同相问题
signal_r <= signal_input*carrier_cos;
signal_i <= signal_input*carrier_sin;
滤波器模块
实验采用 96 96 96路滤波器,读入的前 96 96 96个数据分别划为 96 96 96个滤波器的第一个数据,读入的下一组 96 96 96个数据分别划为 96 96 96个滤波器的第二个数据,每个滤波器共需读入 400 400 400个数据
滤波器参数通过 M A T L A B MATLAB MATLAB的滤波器设计工具生成
滤波器
例化信号
fir fir_1(
.clk (sys_clk ),
.reset_n (sys_rst_n ),
.ast_sink_data (signal1 ),
.ast_sink_valid (data_valid ),
.ast_sink_error (2'b00 ),
.ast_sink_sop (ast_sink_sop ),
.ast_sink_eop (ast_sink_eop ),
.ast_source_data (ast_source_data_1 ),
.ast_source_valid (ast_source_valid_1 ),
.ast_source_error (ast_source_error_1 ),
.ast_source_sop ( ),
.ast_source_eop ( ),
.ast_source_channel ( )
F I R FIR FIR I P IP IP核需要输入和输出信号线如上
ast_sink_valid
为输入数据有效信号,滤波器采样频率为 400 k H z 400kHz 400kHz,因此每 250 250 250个时钟周期进行一次采样,因此在这 250 250 250个时钟周期中,前 96 96 96个时钟周期为多通道滤波器的连续采样时刻,此时valid
信号拉高,当一组数据采集完成后,信号拉低,工程中用到两个valid
信号,fir_valid
落后于data_valid
一个时钟周期,因此fir_valid
信号在仿真文件中定义如下:
// wire fir_valid;
assign fir_valid = (((cnt_valid >= 2)&&(cnt_valid <= 97)) ?1 : 0);
ast_sink_sop
和ast_sink_eop
分别为输入数据起始和结束标记脉冲,通过对valid
信号上升沿和下降沿的捕获实现 ,基本思路为对valid
信号延时并取反相与实现,具体实现方法如下:
// 捕获valid信号上升沿和下降沿
reg en_d0, en_d1;
//捕获valid上升沿,得到一个时钟周期的脉冲信号
assign sink_sop = (~en_d1) & en_d0;
//捕获valid下降沿,得到一个时钟周期的脉冲信号
assign sink_eop = (~en_d0) & en_d1;
//对valid信号延迟两个时钟周期
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
en_d0 <= 1'b0;
en_d1 <= 1'b0;
end
else begin
en_d0 <= fir_valid;
en_d1 <= en_d0;
end
end
锁相环模块
试验中需要一个 400 k H z 400kHz 400kHz的时钟控制载波信号取值,因此用到了锁相环
锁相环的使用是存在延时的,而非reset
信号拉高后就会输出 400 k H z 400kHz 400kHz时钟,如图所示:
因此在定义data_valid
信号时,需要延时一定时间至度过锁相环延时周期,才能保证正常运行
initial begin
# 60000; // 锁相环有延时
forever begin
@(posedge sys_clk);
begin
if(cnt_valid == 250)
仿真文件
系统时钟
每隔 5000 p s 5000ps 5000ps翻转一次
// 100MHz sys_clk generating
localparam TCLK_HALF = 5_000;
initial begin
sys_clk = 1'b0 ;
forever begin
# TCLK_HALF sys_clk = ~sys_clk ;
end
end
定义复位和停止时刻
总时间尺度约为 2500000 ∗ 400 + 60000 2500000*400+60000 2500000∗400+60000
initial begin
sys_rst_n = 1'b0 ;
# 30 ;
sys_rst_n = 1'b1 ;
# 1_000_060_000
$finish ;
end
读取数据
readmemh
可读取十六进制数,将读取数据存放到 16 ∗ 38400 16*38400 16∗38400为寄存器中共后续使用
reg [15:0] stimulus [0:38399] ;
integer i ;
initial begin
$readmemh("data_cw_38400.txt", stimulus) ;
i = 1 ;
data = stimulus[0] ;
forever begin
@(negedge sys_clk) ;
if(data_valid && i<38400)begin
data = stimulus[i] ;
i=i+1;
end
end
end
设定读取使能信号,确定何时读取何时停止
// wire data_valid;
assign data_valid = (((cnt_valid >= 1)&&(cnt_valid <= 96)) ?1 : 0);
存放数据
保存数据供后续比对
integer fir1_file, fir2_file;
initial fir1_file = $fopen("data_out_1.txt");
initial fir2_file = $fopen("data_out_2.txt");
always @(posedge sys_clk) begin
if (!sys_rst_n) begin
// reset
end
else if (ast_source_valid_1) begin
$fwrite(fir1_file,"%f\n",$signed(ast_source_data_1));// %f 有符号数保存,\n:换行符
$fwrite(fir2_file,"%f\n",$signed(ast_source_data_2));// %f 有符号数保存,\n:换行符
end
end
数据对比
为验证 V e r i l o g Verilog Verilog程序是否正确,将通过 M o d e l s i m Modelsim Modelsim仿真得出数据与通过 M a t l a b Matlab Matlab仿真得出数据进行对比
原始数据
解调波形
根据观察发现,通过 V e r i l o g Verilog Verilog得出数据与对应位置的通过 M a t l a b Matlab Matlab得出的数据幅值相差三倍,根据分析可能是由于输出数据位宽定义不一致导致的,因此先对通过两种方法得出的数据进行归一化,归一化范围为 2 − 2 20 2-2^{20} 2−220
最后得出误差约为万分之七左右:
实验总结
以前写 V e r i l o g Verilog Verilog都很简单,都是直接写在板子上跑,对于仿真文件了解也很少,时序也都乱写,这次写完这个工程对于仿真文件和时序也算有了一点新的理解