Files
MM7020/hdl/Receiver.v
T
2024-07-19 14:09:20 +08:00

321 lines
13 KiB
Verilog

`timescale 1ns / 1ns
module Receiver (
input clk,
input clk_2x,
input clk_4x,
input rst,
input [ 2:0] speed_mode,
input [11:0] ad9361_rx_data_i,
input [11:0] ad9361_rx_data_q,
output frame_sync_pulse // in domain clk
);
// ******** Wire & Reg ********
// reg [23:0] mf_data_d1; // clk_4x
// reg [23:0] mf_data_d2; // clk_4x
// wire rst_4x; // NOTE: HIGH FANOUT to be fixed
reg [11:0] mf_data_i;
reg [11:0] mf_data_q;
reg [20:0] dmf_data_i;
reg [20:0] dmf_data_q;
wire [23:0] dmf_tdata_interp4_i;
wire [23:0] dmf_tdata_interp4_q;
wire [23:0] dmf_tdata_interp16_i;
wire [23:0] dmf_tdata_interp16_q;
reg dmf_tvalid;
wire dmf_tvalid_interp4_i;
wire dmf_tvalid_interp4_q;
wire dmf_tvalid_interp16_i;
wire dmf_tvalid_interp16_q;
wire dmf_ready;
wire [31:0] mf_data_interp16_i;
wire [31:0] mf_data_interp16_q;
wire [31:0] mf_data_interp4_i;
wire [31:0] mf_data_interp4_q;
wire [21:0] mag;
wire mag_valid;
wire frame_sync;
wire fifo_out_valid;
reg [ 2:0] cnt_fifo_out_valid;
reg [ 2:0] cnt_fifo_out_valid_sel; // 根据speed mode对应的计数器边界值
wire [31:0] fifo_out;
reg dmf_s_valid;
reg [ 8:0] cnt_startup;
wire startup;
wire startup_4x;
wire frame_sync_4x;
// ******** Assingment ********
assign startup = (cnt_startup == 9'd511);
// ******** Logic Block ********
always @(posedge clk) begin
if (rst) begin
cnt_startup <= 9'd0;
end
else if (cnt_startup < 9'd511) begin
cnt_startup <= cnt_startup + 8'd1;
end
end
// valid signal for dmf
always @(posedge clk_4x) begin
if (rst) begin
dmf_s_valid <= 1'd0;
end
else if (startup_4x && fifo_out_valid && cnt_fifo_out_valid == cnt_fifo_out_valid_sel) begin
dmf_s_valid <= 1'd1;
end
else begin
dmf_s_valid <= 1'd0;
end
end
always @(posedge clk_4x) begin
if (rst) begin
cnt_fifo_out_valid <= 3'd0;
end
else if (fifo_out_valid) begin
if (cnt_fifo_out_valid == cnt_fifo_out_valid_sel) begin
cnt_fifo_out_valid <= 3'd0;
end
else begin
cnt_fifo_out_valid <= cnt_fifo_out_valid + 3'd1;
end
end
else begin
cnt_fifo_out_valid <= cnt_fifo_out_valid;
end
end
// speed mode select
always @(*) begin
case (speed_mode)
3'd0: begin // 16
mf_data_i = mf_data_interp16_i[31-:12];
mf_data_q = mf_data_interp16_q[31-:12];
dmf_data_i = dmf_tdata_interp16_i[20:0];
dmf_data_q = dmf_tdata_interp16_q[20:0];
dmf_tvalid = dmf_tvalid_interp16_i;
cnt_fifo_out_valid_sel = 3'd7;
end
// 3'd1: begin // 8
// end
3'd2: begin // 4
mf_data_i = mf_data_interp4_i[29-:12];
mf_data_q = mf_data_interp4_q[29-:12];
dmf_data_i = dmf_tdata_interp4_i[20:0];
dmf_data_q = dmf_tdata_interp4_q[20:0];
dmf_tvalid = dmf_tvalid_interp4_i;
cnt_fifo_out_valid_sel = 3'd1;
end
// 3'd3: begin // 2
// end
default: begin
mf_data_i = mf_data_interp16_i[31-:12];
mf_data_q = mf_data_interp16_q[31-:12];
dmf_data_i = dmf_tdata_interp16_i[20:0];
dmf_data_q = dmf_tdata_interp16_q[20:0];
dmf_tvalid = dmf_tvalid_interp16_i;
cnt_fifo_out_valid_sel = 3'd7;
end
endcase
end
// ******** Inst ********
xpm_cdc_sync_rst #(
.DEST_SYNC_FF (4), // DECIMAL; range: 2-10
.INIT (1), // DECIMAL; 0=initialize synchronization registers to 0, 1=initialize synchronization
// registers to 1
.INIT_SYNC_FF (1), // DECIMAL; 0=disable simulation init values, 1=enable simulation init values
.SIM_ASSERT_CHK(1) // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
) xpm_cdc_sync_rst_inst (
.dest_rst(rst_4x), // 1-bit output: src_rst synchronized to the destination clock domain. This output
// is registered.
.dest_clk(clk_4x), // 1-bit input: Destination clock.
.src_rst (rst) // 1-bit input: Source reset signal.
);
// match filter
// fir_match_interp16 u_fir_match_filter_interp16_i (
// .aclk (clk), // input wire aclk
// .s_axis_data_tvalid(startup), // input wire s_axis_data_tvalid
// .s_axis_data_tready(), // output wire s_axis_data_tready
// .s_axis_data_tdata ({4'd0, ad9361_rx_data_i}), // input wire [15 : 0] s_axis_data_tdata
// .m_axis_data_tvalid(), // output wire m_axis_data_tvalid
// .m_axis_data_tdata (mf_data_interp16_i) // output wire [31 : 0] m_axis_data_tdata
// );
// fir_match_interp16 u_fir_match_filter_interp16_q (
// .aclk (clk), // input wire aclk
// .s_axis_data_tvalid(startup), // input wire s_axis_data_tvalid
// .s_axis_data_tready(), // output wire s_axis_data_tready
// .s_axis_data_tdata ({4'd0, ad9361_rx_data_q}), // input wire [15 : 0] s_axis_data_tdata
// .m_axis_data_tvalid(), // output wire m_axis_data_tvalid
// .m_axis_data_tdata (mf_data_interp16_q) // output wire [31 : 0] m_axis_data_tdata
// );
fir_match_interp4 u_fir_match_filter_interp4_i (
.aclk (clk), // input wire aclk
.s_axis_data_tvalid(startup), // input wire s_axis_data_tvalid
.s_axis_data_tready(), // output wire s_axis_data_tready
.s_axis_data_tdata ({4'd0, ad9361_rx_data_i}), // input wire [15 : 0] s_axis_data_tdata
.m_axis_data_tvalid(), // output wire m_axis_data_tvalid
.m_axis_data_tdata (mf_data_interp4_i) // output wire [31 : 0] m_axis_data_tdata
);
fir_match_interp4 u_fir_match_filter_interp4_q (
.aclk (clk), // input wire aclk
.s_axis_data_tvalid(startup), // input wire s_axis_data_tvalid
.s_axis_data_tready(), // output wire s_axis_data_tready
.s_axis_data_tdata ({4'd0, ad9361_rx_data_q}), // input wire [15 : 0] s_axis_data_tdata
.m_axis_data_tvalid(), // output wire m_axis_data_tvalid
.m_axis_data_tdata (mf_data_interp4_q) // output wire [31 : 0] m_axis_data_tdata
);
// TODO: 削峰
fifo_shift u_fifo_shift (
// input
.s_aclk (clk), // input wire s_aclk
.s_aresetn (startup), // input wire s_aresetn
.s_axis_tvalid(startup), // input wire s_axis_tvalid
.s_axis_tready(), // output wire s_axis_tready
.s_axis_tdata ({8'd0, mf_data_q, mf_data_i}), // input wire [31 : 0] s_axis_tdata
// output
.m_aclk (clk_4x), // input wire m_aclk
.m_axis_tvalid(fifo_out_valid), // output wire m_axis_tvalid
.m_axis_tready(1'b1), // input wire m_axis_tready
.m_axis_tdata (fifo_out), // output wire [31 : 0] m_axis_tdata
.wr_rst_busy (),
.rd_rst_busy ()
);
// TODO: dmf根据不同的速率挡位来选择不同的内插值的fir滤波器
// NOTE: 编写关于抽取的滤波器设计相关文档
// dmf filter
// fir_dmf_interp16 u_fir_dmf_interp16_i (
// .aclk (clk_4x), // input wire aclk
// .s_axis_data_tvalid(dmf_s_valid), // input wire s_axis_data_tvalid
// .s_axis_data_tready(), // output wire s_axis_data_tready
// .s_axis_data_tdata ({4'd0, fifo_out[11:0]}), // input wire [15 : 0] s_axis_data_tdata
// .m_axis_data_tvalid(dmf_tvalid_interp16_i), // output wire m_axis_data_tvalid
// .m_axis_data_tdata (dmf_tdata_interp16_i) // output wire [31 : 0] m_axis_data_tdata
// );
// fir_dmf_interp16 u_fir_dmf_interp16_q (
// .aclk (clk_4x), // input wire aclk
// .s_axis_data_tvalid(dmf_s_valid), // input wire s_axis_data_tvalid
// .s_axis_data_tready(), // output wire s_axis_data_tready
// .s_axis_data_tdata ({4'd0, fifo_out[23:12]}), // input wire [15 : 0] s_axis_data_tdata
// .m_axis_data_tvalid(dmf_tvalid_interp16_q), // output wire m_axis_data_tvalid
// .m_axis_data_tdata (dmf_tdata_interp16_q) // output wire [31 : 0] m_axis_data_tdata
// );
fir_dmf_interp4 u_fir_dmf_interp4_i (
.aclk (clk_4x),
.s_axis_data_tvalid(dmf_s_valid),
.s_axis_data_tready(),
.s_axis_data_tdata ({4'd0, fifo_out[11:0]}),
.m_axis_data_tvalid(dmf_tvalid_interp4_i),
.m_axis_data_tdata (dmf_tdata_interp4_i)
);
fir_dmf_interp4 u_fir_dmf_interp4_q (
.aclk (clk_4x),
.s_axis_data_tvalid(dmf_s_valid),
.s_axis_data_tready(),
.s_axis_data_tdata ({4'd0, fifo_out[23:12]}),
.m_axis_data_tvalid(dmf_tvalid_interp4_q),
.m_axis_data_tdata (dmf_tdata_interp4_q)
);
MagnitudeEstimator #(
.VEC_WIDTH(21)
) u_MagnitudeEstimator (
.clk (clk_4x),
.rst (rst),
.vec_valid(dmf_tvalid),
.I (dmf_data_i),
.Q (dmf_data_q),
.mag (mag),
.mag_valid(mag_valid)
);
PAPR #(
.MAG_WIDTH (22),
.WINDOW_DEPTH(1023)
) u_PAPR (
.clk (clk_4x),
.rst (rst),
.vec_mag (mag),
.mag_valid (mag_valid),
.frame_sync (frame_sync_4x),
.frame_sync_pulse()
);
xpm_cdc_single #(
.DEST_SYNC_FF (2), // DECIMAL; range: 2-10
.INIT_SYNC_FF (1), // DECIMAL; 0=disable simulation init values, 1=enable simulation init values
.SIM_ASSERT_CHK(1), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
.SRC_INPUT_REG (1) // DECIMAL; 0=do not register input, 1=register input
) xpm_cdc_startup_inst (
.dest_out(startup_4x), // 1-bit output: src_in synchronized to the destination clock domain. This output is
// registered.
.dest_clk(clk_4x), // 1-bit input: Clock signal for the destination clock domain.
.src_clk (clk), // 1-bit input: optional; required when SRC_INPUT_REG = 1
.src_in (startup) // 1-bit input: Input signal to be synchronized to dest_clk domain.
);
xpm_cdc_pulse #(
.DEST_SYNC_FF (4), // DECIMAL; range: 2-10
.INIT_SYNC_FF (0), // DECIMAL; 0=disable simulation init values, 1=enable simulation init values
.REG_OUTPUT (0), // DECIMAL; 0=disable registered output, 1=enable registered output
.RST_USED (0), // DECIMAL; 0=no reset, 1=implement reset
.SIM_ASSERT_CHK(1) // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
) xpm_cdc_frame_sync_pulse_inst (
.dest_pulse(frame_sync_pulse), // 1-bit output: Outputs a pulse the size of one dest_clk period when a pulse
// transfer is correctly initiated on src_pulse input. This output is
// combinatorial unless REG_OUTPUT is set to 1.
.dest_clk (clk), // 1-bit input: Destination clock.
.dest_rst (), // 1-bit input: optional; required when RST_USED = 1
.src_clk (clk_4x), // 1-bit input: Source clock.
.src_pulse (frame_sync_4x), // 1-bit input: Rising edge of this signal initiates a pulse transfer to the
// destination clock domain. The minimum gap between each pulse transfer must be
// at the minimum 2*(larger(src_clk period, dest_clk period)). This is measured
// between the falling edge of a src_pulse to the rising edge of the next
// src_pulse. This minimum gap will guarantee that each rising edge of src_pulse
// will generate a pulse the size of one dest_clk period in the destination
// clock domain. When RST_USED = 1, pulse transfers will not be guaranteed while
// src_rst and/or dest_rst are asserted.
.src_rst () // 1-bit input: optional; required when RST_USED = 1
);
// ******** Debug ********
endmodule