从零在FPGA上实现OFDM(三)

4 篇文章 9 订阅
3 篇文章 1 订阅

OFDM 调制 PLCP 子层数据字段的生成

说明:PLCP层的数据,我们这里只是实现data域,其余的现在先不考虑

        这是将我们上一个产生的数据每一帧数据,经生成的数据进行处理使之满足 data 域(serive 域 +psdu + tail bits + pad bits) 的数据结构要求。

其中serive 域中前7个为0,用来初始化接收机部分的解扰码器的初始值,因为前 7bit 为 0 时加扰器会输出加扰器的初试状态。后 9 个 bits 预留以便将来使用。

PSDU:其实就是我们实际传输的数据(bit);

tail bits + pad bits :Psdu 后面跟随的尾 bits 的作用和 signal 域的尾比特作用相同,都是为了卷积编码器的移位寄存器的清零。

Pad bits :Pad bits 的意义在于使整个 data 域的比特流长度刚好调整为每一个 ofdm符号数据比特长度的整数倍,如果 data 域的比特数不足 ofdm 符号的整数倍,要适当补零。

总的来说就是将我们的数据进行处理,使满足data域的帧格式。

总的思路:我们上一个模块产生的数据是每字节的数据,而经过这里的转换之后就会转化为单bit的数据,就是8转1,然后进行输出,且满足data域的数据帧格式。

具体思路:总的数据是8转1,所以使用一个异步fifo,将数据进行转换。

模块设计的框图:

 

写fifo时序思路:

1:psdu其实就是我们实际的数据,我么要在前面加上16bit 的serive域的数据,其实我们这里只需要在前面加上2个8bit的0就行了。

加2个8bit 0思路:由于上一个模块会同是输出数据有效和数据,我们只需要将数据有效信号延迟2个拍,然后当数据有效信号延迟1拍的信号有效时,fifo的输入信号就是上一个模块发出的有效数据,其他时刻fifo的输入数据就是0;fifo 的写使能就是上一个数据有效再或上上一个数据有效延迟的2拍的信号。

// fifo写时序  主要就是在前面加入2个8bit 的0 ,就是增加16比特0
assign fifo_generator_8to1_inst_wren = send_data_valid | send_data_valid_dly2;
//delay 2 clk
always @(posedge clk_User ) begin
    {send_data_valid_dly2,send_data_valid_dly1} <= {send_data_valid_dly1,send_data_valid};
end
//send_data_dly1 
always @(posedge clk_User ) begin
    send_data_dly1 <= send_data;
end

 //locked signals
 always @(posedge clk_User ) begin
    if(reset == 1'b1) begin
        fifo_generator_8to1_inst_din <= 1'b0;
    end else if(send_data_valid_dly1 == 1'b1) begin
        fifo_generator_8to1_inst_din <= send_data_dly1;
    end else begin
        fifo_generator_8to1_inst_din <= 1'b0;
    end
 end

//

其实我们在读fifo时,我们需要在读出的数据的尾端加上tail bits + pad bits这两个部分的数据,我们在读fifo之前,就应该将要在后面补多少0,做好准备,计算好。

这是一些802.11a中的一些表

 

 

首先这里使用的是

//编码效率为3/4,带宽20Mhz,数据传输信道为48,调制模式为64QAM,每一个OFDM的符号

//周期统一定义为4us,就是一个OFDM 周期为4us

//传输速率:3/4*48*6*1/48e6 = 54Mb/s 也就是理想总带宽

//每一个ofdm 符号的编码比特(Ncbps):6*48 = 288;//这里的6是由于用的64QAM,2^6 = 64

//由于是3/4编码,所以每一个ofdm数据比特(Ndbps)为288*3/4 = 216

//Nsym = ceiling[(16 + 8 * length + 6)/Ndbps]; Nsym为OFDM符号数。

Ndbps 数据速率,可以查表得这个为tx_Rate的 4倍。

所以就需要用到一个乘法和除法ip将我们所需要的数据计算出来,算出最后需要填充的数据。

实际的传输的bit数:(packetlength << 3) +22 //packetlen 是多少字节,这里是多少bit,22 == service + tail;

//计算的pad bits的一些代码

assign send_data_valid_flag = (~send_data_valid_dly1)& send_data_valid;//上一拍为低,当前拍为高
// valid_bits_length
always @(posedge clk_User ) begin
    if(reset == 1'b1) begin
        valid_bits_length <= 'd0;
end else if(send_data_valid_flag == 1'b1) begin
        valid_bits_length <= (packetlength << 3) +22;//packetlen 是多少字节,这里是多少bit,22 == service + tail;
end else begin
        valid_bits_length <= valid_bits_length; 
end
end
//send_data_valid_flag_dly1;
always @(posedge clk_User) begin
   send_data_valid_flag_dly1 <= send_data_valid_flag; //作为除法的标志位
end
//bits_ofdm_sym  //一个OFDM 中的符号的bit个数
assign bits_ofdm_sym = tx_Rate <<2; //


//data_bit_valid podg
//always @(posedge clk_Modulation ) begin
//    data_bit_valid <= fifo_generator_8to1_inst_rden;
//end

//div 
div_gen_0 div_gen_16_8_isnt (
  .aclk(clk_User),                                      // input wire aclk
  .s_axis_divisor_tvalid(send_data_valid_flag_dly1),    // input wire s_axis_divisor_tvalid
  .s_axis_divisor_tdata(bits_ofdm_sym),      // input wire [7 : 0] s_axis_divisor_tdata
  .s_axis_dividend_tvalid(send_data_valid_flag_dly1),  // input wire s_axis_dividend_tvalid
  .s_axis_dividend_tdata(valid_bits_length),    // input wire [15 : 0] s_axis_dividend_tdata
  .m_axis_dout_tvalid(pad_num_div_valid),          // output wire m_axis_dout_tvalid
  .m_axis_dout_tdata(pad_num_div)            // output wire [23 : 0] m_axis_dout_tdata
);
assign num_ofdm_all = ((pad_num_div[7:0] == 8'd0) ? pad_num_div[23:8] :pad_num_div[23:8] +1);
mult_padnum_16x8 mult_padnum_16x8_inst (
  .CLK(clk_User),  // input wire CLK
  .A(num_ofdm_all),      // input wire [15 : 0] A
  .B(bits_ofdm_sym),      // input wire [7 : 0] B 216 = 54x4 = 216
  .CE(pad_num_div_valid),    // input wire CE
  .P(num_all_data_bits)      // output wire [23 : 0] P    //总的bit的个数
);
//pad_num_div_valid_dly1
always @(posedge clk_User ) begin
    pad_num_div_valid_dly1 <= pad_num_div_valid;  //由于乘法器有一个时钟的延时才会出结果
end
//pad_num
always @(posedge clk_User) begin
    if(reset== 1'b1)begin
        pad_num <= 'd0;
    end else if(pad_num_div_valid_dly1 == 1'b1)begin        //由于乘法器有一个时钟的延时才会出结果,这里对齐
        pad_num <= num_all_data_bits - valid_bits_length;   //我们需要的个数

读fifo

读取fifo的使能信号就是empty信号取反,只要一空了就开始读取。

由于我们最后要加多少个0的已经算出,所以这里使用fifo 读信号延迟一拍来的到一个读取结束信号,使之开始填充0,并且设置一个计数器,来计算我们补了多少个0;

我们最后的需要的补充的数据是tail ,即6个bits的0还有就是pad bits,两个加起来就行了。

说明:这只是本人学习的OFD的一些思路,记录下来,格式什么都没注意,只是单纯的记录

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FPGA是一种可编程逻辑器件,可用于实现各种数字电路和信号处理算法。OFDM(正交频分复用)是一种广泛应用于无线通信系统中的调制技术。通过将信号分成多个子载波进行传输,OFDM可以提供较高的数据传输速率和抗多径干扰能力。 使用FPGA实现OFDM技术可以提供高效的实时信号处理和快速的调试验证能力。下面是一些关键步骤: 1. 子载波生成:OFDM将信号分成多个子载波,并使得这些子载波之间正交。在FPGA中,可以使用相位调制技术和FFT(快速傅里叶变换)来实现子载波生成和正交化。 2. 调制:OFDM使用多种调制方式,如QPSK、16-QAM或64-QAM等。在FPGA中,可以使用数字调制器件或逻辑门电路来实现这些调制方式。 3. 加载调制数据:将数字化的待传输数据加载到适当的位置,并与调制器相连。FPGA中的可编程逻辑电路可用于处理和管理数据。 4. 调制器件配置:对于FPGAOFDM实现,需要对调制器件进行配置,以实现所需的信号调制和反调制。 5. 快速傅里叶变换(FFT):OFDM技术中使用FFT变换将时域信号转换为频域信号,并与子载波一起传输。在FPGA中,可以使用FFT电路模块来进行FFT变换。 6. 频谱处理:OFDM技术通过将数据映射到子载波并在频域上传输,提供了较高的抗多径干扰性能。在FPGA中,可以使用电路模块进行频谱处理和干扰消除。 7. 解调和信号恢复:接收端的FPGA实现用于逆向解调和信号恢复,以获取原始数据。这涉及到反向FFT变换和解调过程,以及对频谱处理和信号解密的支持。 通过FPGA实现OFDM技术可以提供高度灵活和可定制的解决方案,适用于各种无线通信系统中。它可以提供较高的性能和更低的延迟,并且可以快速调试和验证,适用于快速迭代开发的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值