USRP B210 RX_IQ处理

一、b200_io模块

  • 通过 IDDR2 将 12 位单速率数据拆分为 12 位 I 分量和 12 位 Q 分量。
  • 根据 rx_frame 和 mimo_sync,将数据分配到 CH0 或 CH1(MIMO),或复制到两路通道(SISO)。
  • 最终生成四路 12 位 IQ 信号(rx_i0, rx_q0, rx_i1, rx_q1)。
b200_io b200_io_i0 (
    .rx_i0(rx_data0[31:20]), 
    .rx_q0(rx_data0[15:4]),  
    .rx_i1(rx_data1[31:20]),  
    .rx_q1(rx_data1[15:4]),   
    ...
);
assign {rx_data0[19:16], rx_data0[3:0], rx_data1[19:16], rx_data1[3:0]} = 16'h0;

最终生成rx_data0和rx_data1给到b200_core模块

二、b200_core模块

1、数字下变频

(1) IQ 分量提取与精度扩展

wire [31:0] rx_fe = loopback ? tx : rx; // 环路回传时使用 TX 数据
ddc_chain ddc_chain (
    .rx_fe_i({rx_fe[31:16], 8'd0}), 
    .rx_fe_q({rx_fe[15:0], 8'd0}),   
    ...
);

提升数字滤波、频率转换等操作的精度,减少量化噪声影响。

(2) 数字下变频(DDC)

  • 预处理
    通过多路选择器支持信号交换、反相或实模式(单极性)处理,由寄存器配置控制:
always @(posedge clk)
  if(swap_iq) begin
    rx_fe_i_mux <= invert_i ? ~rx_fe_q : rx_fe_q;  // 交换 IQ 并可选反相
    rx_fe_q_mux <= realmode ? 24'h0 : invert_q ? ~rx_fe_i : rx_fe_i;  // 实模式时 Q 置零
  end else begin
    rx_fe_i_mux <= invert_i ? ~rx_fe_i : rx_fe_i;  // 单独反相 I 分量
    rx_fe_q_mux <= realmode ? 24'h0 : invert_q ? ~rx_fe_q : rx_fe_q;  // 实模式时 Q 置零
  end
  • 符号扩展:
    将 24 位的 rx_fe_i_mux/rx_fe_q_mux 扩展为 25 位(to_cordic_i/to_cordic_q),避免 CORDIC 运算中的溢出:
   // CORDIC  24-bit I/O
   // (Algorithmic gain through CORDIC => 1.647 * 0.5 = 0.8235)
   // (Worst case gain through rotation => SQRT(2) = 1.4142)
   // Total worst case gain => 0.8235 * 1.4142 = 1.1646
   // So add an extra MSB bit for word growth.

   sign_extend #(.bits_in(WIDTH), .bits_out(cwidth)) sign_extend_cordic_i (.in(rx_fe_i_mux), .out(to_cordic_i));
   sign_extend #(.bits_in(WIDTH), .bits_out(cwidth)) sign_extend_cordic_q (.in(rx_fe_q_mux), .out(to_cordic_q));

  • CORDIC 算法:
    通过 CORDIC 核实现数控振荡器(NCO),将输入信号与本地载波混频,完成频率搬移:
cordic_z24 #(.bitwidth(25)) cordic (
    .xi(to_cordic_i), .yi(to_cordic_q), .zi(phase[31:8]),  // phase 为 NCO 相位累加器
    .xo(i_cordic), .yo(q_cordic)  // 输出搬移后的 I/Q 分量(25 位)
);

phase 由 phase_inc(寄存器配置的频率控制字)驱动,决定混频频率。
混频频率phase_inc由USB传输过来然后解析:

radio_ctrl_proc radio_ctrl_proc
  (.ctrl_tdata(ctrl_tdata_proc),  // 解析后phase_inc
   .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data));  // 寄存器配置信号
   setting_reg #(.my_addr(BASE+0)) sr_0
     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
      .in(set_data),.out(phase_inc),.changed());
  • 流水线寄存器:
    对 CORDIC 输出进行流水线寄存,降低时序路径延迟:
always @(posedge clk) begin
    i_cordic_pipe[23:0] <= i_cordic[24:1];  // 截取 24 位(丢弃最高位,避免溢出)
    q_cordic_pipe[23:0] <= q_cordic[24:1];
end

2、CIC 抽取滤波

对 CORDIC 输出的信号进行 CIC 滤波器抽取,降低采样率并抑制镜像频率:

   cic_decim #(.bw(WIDTH))
     decim_i (.clock(clk),.reset(rst),.enable(run),
	      .rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic),
	      .signal_in(i_cordic_pipe),.signal_out(i_cic));

   cic_decim #(.bw(WIDTH))
     decim_q (.clock(clk),.reset(rst),.enable(run),
	      .rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic),
	      .signal_in(q_cordic_pipe),.signal_out(q_cic));

输出24位i_cic和q_cic
抽取率cic_decim_rate由USB传输过来然后解析:

radio_ctrl_proc radio_ctrl_proc
  (.ctrl_tdata(ctrl_tdata_proc),  // 解析后的控制数据
   .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data));  // 寄存器配置信号
   setting_reg #(.my_addr(BASE+2), .width(10)) sr_2
     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
      .in(set_data),.out({enable_hb1, enable_hb2, cic_decim_rate}),.changed());

3、半带滤波器(HB Filter)

有新旧两种半带滤波器,通过NEW_HB_DECIM 控制,默认parameter NEW_HB_DECIM = 0,选择旧半带滤波器:

// First (small) halfband  24 bit I/O
	 small_hb_dec #(.WIDTH(WIDTH),.DEVICE(DEVICE)) small_hb_i
	   (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run),
	    .stb_in(strobe_cic),.data_in(i_cic),.stb_out(strobe_hb1),.data_out(i_hb1));

	 small_hb_dec #(.WIDTH(WIDTH),.DEVICE(DEVICE)) small_hb_q
	   (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run),
	    .stb_in(strobe_cic),.data_in(q_cic),.stb_out(),.data_out(q_hb1));

	 // Second (large) halfband  24 bit I/O
	 wire [8:0] 	  cpi_hb = enable_hb1 ? {cic_decim_rate,1'b0} : {1'b0,cic_decim_rate};
	 hb_dec #(.WIDTH(WIDTH),.DEVICE(DEVICE)) hb_i
	   (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb),
	    .stb_in(strobe_hb1),.data_in(i_hb1),.stb_out(strobe_hb2),.data_out(i_hb2));

	 hb_dec #(.WIDTH(WIDTH),.DEVICE(DEVICE)) hb_q
	   (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb),
	    .stb_in(strobe_hb1),.data_in(q_hb1),.stb_out(),.data_out(q_hb2));

支持通过 enable_hb1/enable_hb2 控制滤波器启用状态。
enable_hb1和enable_hb2也是由上位机控制:

 setting_reg #(.my_addr(BASE+2), .width(10)) sr_2
     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
      .in(set_data),.out({enable_hb1, enable_hb2, cic_decim_rate}),.changed());

4、比例因子调整与幅度控制

(1)滤波后的数据进入舍入器,将 24 位的 q_hb2 信号转换为 19 位的 q_hb_out_rnd:

	 round #(
	   .bits_in(WIDTH),
	   .bits_out(19)
	 ) hb_out_rnd_q (
	   .in(q_hb2),
	   .out(q_hb_out_rnd)
	 );

(2)将 19 位的 q_hb_out_rnd 信号限幅并转换为 18 位:

	 clip_reg #(.bits_in(19), .bits_out(18), .STROBED(1)) unscaled_clip_q
	   (.clk(clk), .in(q_hb_out_rnd), .strobe_in(strobe_hb2), .out(q_unscaled_clip[17:0]), .strobe_out());

(3) 增益补偿
通过乘法器应用比例因子 scale_factor(18 位USB传输),补偿 CORDIC 和 CIC 滤波器的固定增益:

MULT_MACRO #(.WIDTH_A(18), .WIDTH_B(18)) mult_i (
    .A(q_unscaled_clip),  // 18 位
    .B(scale_factor),  // 比例因子
    .P(prod_i)  // 乘积结果(36 位)
);

(4) 截位与舍入
对乘法结果进行截位和舍入,转换为 16 位有符号数(sample[31:16] 和 sample[15:0]),适配后续帧生成模块的输入格式:

	 clip_reg #(.bits_in(36), .bits_out(33), .STROBED(1)) clip_i
	   (.clk(clk), .in(prod_i[35:0]), .strobe_in(strobe_scaled), .out(i_clip), .strobe_out(strobe_clip));
	 clip_reg #(.bits_in(36), .bits_out(33), .STROBED(1)) clip_q
	   (.clk(clk), .in(prod_q[35:0]), .strobe_in(strobe_scaled), .out(q_clip), .strobe_out());

	 round_sd #(.WIDTH_IN(33), .WIDTH_OUT(16)) round_i
	   (.clk(clk), .reset(rst), .in(i_clip), .strobe_in(strobe_clip), .out(sample[31:16]), .strobe_out(strobe));
	 round_sd #(.WIDTH_IN(33), .WIDTH_OUT(16)) round_q
	   (.clk(clk), .reset(rst), .in(q_clip), .strobe_in(strobe_clip), .out(sample[15:0]), .strobe_out());

三、new_rx_framer模块

将连续的 IQ 样本数据流转换为符合 VITA 49 标准的网络数据包

  • 头部信息:包含包长、序列号、流 ID(SID)等元数据。
  • 时间戳:嵌入精确的时间信息(vita_time),支持时间同步应用。
  • 数据有效载荷:将 IQ 样本按 64 位字打包(两个 32 位样本 / 字)。

四、chdr_16sc_to_xxxx_chain 模块

   chdr_16sc_to_xxxx_chain #(.BASE(SR_RX_FMT)) convert_16sc_to_xxxx
     (.clk(radio_clk), .reset(radio_rst),
      .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
      .i_tdata(rx_tdata_i), .i_tlast(rx_tlast_i), .i_tvalid(rx_tvalid_i), .i_tready(rx_tready_i),
      .o_tdata(rx_prefc_tdata_r), .o_tlast(rx_prefc_tlast_r), .o_tvalid(rx_prefc_tvalid_r), .o_tready(rx_prefc_tready_r),
      .debug());

该模块将CHDR 格式的 16 位有符号复数(IQ)数据流转换为其他精度或类型的格式:

demux_dst功能功能描述
2’b00直通输入数据直接输出,不做转换
2’b0016sc→12sc将 16 位复数(16sc)转换为 12 位复数(12sc)
2’b0016sc→32f转换为 32 位浮点数(32f)
2’b0016sc→8sc转换为 8 位复数(8sc)

demux_dst也是由USB传输解析而来:

   //------------------------------------------------------------------
   // Demux destination setting register - safe switch for demux
   //------------------------------------------------------------------
   wire [1:0] 	  demux_dst;
   setting_reg #(.my_addr(BASE), .width(2), .at_reset(2'b00)) sr_demux_dst
     (.clk(clk),.rst(reset),
      .strobe(set_stb),.addr(set_addr), .in(set_data),
      .out({demux_dst}),.changed());

五、source_flow_control_legacy 模块

作用是流量控制(Flow Control),核心是根据接收方的处理能力和信用窗口(credit window)动态决定是否放行数据,对数据不做任何处理。

六、USB传输至上位机

1、axi_mux4 :正常接收数据 和 错误状态数据 之间进行优先级选择,并输出符合 AXI Stream 协议的数据流
2、rx_fifo:将数据转化成bus_clk时钟域 然后通过USB传输到上位机。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值