文章目录
一、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’b00 | 16sc→12sc | 将 16 位复数(16sc)转换为 12 位复数(12sc) |
2’b00 | 16sc→32f | 转换为 32 位浮点数(32f) |
2’b00 | 16sc→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传输到上位机。