当前位置:   article > 正文

2ASK调制解调_verilog的2ask调制解调

verilog的2ask调制解调

        ASK调制解调中,调制信号为二进制数字信号(2ASK),载波幅度仅有两种状态变化,发送的信号上没有载波时表示发送的码元0,信号上有载波时发送的码元1,可看作一个单极性的脉冲序列和一个载波相乘。

2ASK信号调制模型:

2ASK信号解调模型:

 由整流电路对输入信号取整,将交流信号转换成直流信号,低通滤波器滤出基带信号的包络,经判决输出,完成解调。

FPGA 端的实验框图:

        发送端:由ARM将数据传入DDR,通过DMA进行数据读取并进行并串转换,再由tx_ask进行调制,将调制后的信号送入AD9361经PA后发送出去;

        接收端:AD9361接收到的数据送入rx_fir进行整流以及滤波,再由mean模型进行均值平滑滤波器以消除噪声干扰,bitsync模块进行数据同步,判决输出,将接收到的模拟信号转为数字信号,由串并转换将数据恢复成8位有效数据,通过DMA写回DDR,ARM端用串口将数据返回至上位机,由上位机进行解调正确性的判断。

        实验采用AD9361+zynq 框架实现,首先需要搭建基于AD9361 的收发器框架。

1、AD9361 PL侧框架搭建

        AD9361框架图:

 1T1R和2T2R读写时序图:

         1T1R模式需要两个时钟才能完整的接收完一个 12 位的数据,根据data_clk 和 rx_frame 信号先接收 I Q 路数据的高 6 位,再接收低 6 位;

        2T2R模型需要四个时钟才能完整接收完一个12位数据,在rx_frame 信号为高时,接收1个通道数据,为低时接收另一个通道数据;需要注意的是,rx_frame为高时,接收的是两个通道的高6位,反之接收低6位数据;

        AD9361接口模块设计框图:

RX 链路:IBUFDS -> IDELAY -> IDDR ->RX_CHANNEL_IQ

TX 链路:TX_CHANNEL_IQ -> ODDR -> OBUFDS

IBUFDS和OBUFDS进行单端信号与差分信号的相互转换,因为FPGA无法处理差分信号;

IDDR和ODDR进行单沿与双沿采样数据的转换;

IDELAY用于动态调制接收数据与时钟的延迟;

RX_CHANNEL_IQ 和 TX_CHANNEL_IQ 是对RX 和 TX数据的解析,提取1T1R和2T2R模式下的  I /Q 路数据;

FPGA系统搭建:

2、ASK信号的调制

         调制原理:发送的数据为0,则输出0;发送的数据为1,则输出载波信号,即正余弦信号。

        参数:采样时钟 40MHZ,数据频率100Kbps,载波频率1.25MHZ,每个载波周期内采样点数 40/1.25=32个,每个数据周期内有 40/0.1=400个采样点

        模块设计思路:调制模块内部需要先声明两个数组存放sin和cos对应的数据;通过计数器,在采样时钟作用下,从0~32进行循环计数,模块每输入一个数进行一次判断;当输入数据为0,输出0;输入数据为1,输出sin 和cos数组内与当前计数器对应的值。

使用MATLBA生成 sin 和 cos 数组:

  1. t = 1:1/32:1;
  2. y1 = 255 * sin(2*pi*t);
  3. y2 = 255 * cos(2*pi*t);
  4. y1 = round(y1);
  5. y2 = round(y2);
  6. file = fopen('data.txt','w');
  7. fprintf(file,'%d, ',y1);
  8. fprintf(file,'\n');
  9. fprintf(file,'%d, ',y2);
  10. fclose(file);

HLS实现tx_ask模块:

  1. void tx_ask(ap_uint<1> data_in, ap_int<12> *sin, ap_int<12> *cos){
  2. ap_int<12> cos_table[32] ={255 ,250 ,236 ,212 ,180 ,142 ,98 ,50 ,0 ,-
  3. 50 ,-98 ,-142 ,-180 ,-212 ,-236 ,-250 ,-255 ,-250 ,-236 ,-212 ,-180 ,-142 ,-98 ,-50 ,0 ,50 ,98 ,142 ,180 ,212 ,236 ,250};
  4. ap_int<12> sin_table[32] ={0 ,50 ,98 ,142 ,180 ,212 ,236 ,250 ,255 ,250 ,236 ,212 ,180 ,142 ,98 ,50 ,0 ,-50 ,-98 ,-142 ,-180 ,-212 ,-236 ,-250 ,-255 ,-250 ,-236 ,-212 ,-180 ,-142 ,-98 ,-50};
  5. if(data_in == 1){
  6. *sin = sin_table[count.range(4, 0)];
  7. *cos = cos_table[count.range(4, 0)];
  8. }
  9. else
  10. {
  11. *sin=0;
  12. *cos=0;
  13. }
  14. count ++;
  15. if(count == 32) {
  16. count =0;
  17. } }
  18. }

3、接收链路rx_fir 模块实现

        先进行abs()函数取绝对值进行整流,再由FIR低通滤波,滤除高频载波信号。

        fir参数设置:采样率40MHZ,54阶低通滤波器,Hamming窗,通带频率100K;

 

 

  1. void rx_ask (
  2. ap_int<20> *y,
  3. ap_int<12> x
  4. ) {
  5. const ap_int<8> c[54] = {
  6. 1, 1, 2, 2, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9, 10, 11,
  7. 12, 13, 14, 15, 16, 16, 17, 17, 18, 18, 18, 18, 18, 18, 17, 17, 16, 16, 15,
  8. 14, 13, 12, 11, 10, 9, 8, 7, 7, 6, 5, 4, 3, 3, 2, 2, 2, 1, 1
  9. };
  10. static ap_int<12> shift_reg[54];
  11. ap_int<26> acc;
  12. ap_int<12> x_t;
  13. int i;
  14. acc=0;
  15. x_t = abs(x);
  16. Shift_Accum_Loop: for (i=54-1;i>=0;i--) {
  17. if (i==0) {
  18. acc+=x_t*c[0];
  19. shift_reg[0]=x_t;
  20. } else {
  21. shift_reg[i]=shift_reg[i-1];
  22. acc+=shift_reg[i]*c[i];
  23. } }
  24. *y = acc.range(25,6);
  25. }

 4、均值滤波

        将连续输入的相邻的数进行累加求平均值,以滤除噪声产生的毛刺,再送入同步模块,使得其减少误判。

  1. void mean(ap_int<20> dina,ap_int<20> *dout){
  2. static ap_int<20> shift_reg[16];
  3. ap_int<24> acc;
  4. acc =0;
  5. int i;
  6. Shift_Accum_Loop:for(i=16-1;i>=0;i--){
  7. if(i==0) {
  8. shift_reg[0] = dina;
  9. acc += dina;
  10. }
  11. else{
  12. shift_reg[i]=shift_reg[i-1];
  13. acc+=shift_reg[i];
  14. }
  15. }
  16. *dout=acc.range(23, 4); //div 16
  17. dout =0;
  18. }

5、判决输出

        包络检波输出基带波形后,需要将其进行判决转换为二进制,因此要考虑判决门限的大小和符号采样问题,保证门限判决的正确性和只对每一位符号判决后的二进制值采样一次。

        数据帧结构:

        工作流程:

         当输入值增大,则认为有数据输入,但也需要排除噪声干扰的情况,所以对输入值求均值,当均值大于门限值,可判定有数据输入,可进行符号判决;利用FIFO进行数据延拍,以便在最佳采样点采集到稳定数据。

         判决门限:

        输入数据大于门限值,判定数据为1;输入数据小于门限值,判定数据为0;

        符号判决:

        保证一个符号周期内,只对符号采样一次,且在判决后的二进制数据的正中间时刻采样;

        判断帧头:

        帧头由巴克码和定界符组成,利用序列检测器即可实现。

        检测到帧头后,可提取LEN信息,得到数据的长度,以便得到裸数据,写入DDR。

6、DMA实现

        ARM端通过串口接收数据并写入DDR,FPGA通过DMA将数据读出送入调制部分;而解调部分则将数据通过DMA写回DDR,由ARM返回给上位机。

 DMA IP:

 

 S_AXI_LITE:配置通道,axi_dma IP去DDR里面哪个地址空间,读多少数据,由此接口配置读取的地址及读取数据的长度;S_AXI_LITE配置后之后启动读,就能够从IP输出端驱动 HP口读取数据,中间需要经过协议转换IP(interconnected);

M_AXI_MM2S输出的是从DDR存储器中读出要发送的数据,该数据需要通过自定义缓存模块(s_axis_rd)进行数据位宽转换(64bit->8bit)和跨时钟域处理,每次缓存一帧突发数据;

M_AXI_S2MM输出的数据同样需要通过自定义缓存模块(m_axis_wr)进行数据位宽转换(8bit->64bit)和跨时钟域处理,缓存完一帧突发长度时进行写操作,将解调数据写入DDR;

        解决输入数据长度不为 8字节整数倍的问题:

        因为总数据长度不可知,当不为8字节整数倍时需要插入无效字节,使得FIFO读的时候可以整体8字节读出,便于FIFO读空内部的数据。如果是8字节的整数倍的数据长度,其低三位为000;

如果不是8字节的整数倍,可以将数据长度的低三位取反再加1得到的值作为无效数据填充进FIFO内部。举例:数据长度低三位为3'b011,余数为3,需要写入5字节凑齐8字节,则将3'b011取反再加1,即得到3'b101,为十进制5。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/482397
推荐阅读
相关标签
  

闽ICP备14008679号