321 lines
13 KiB
Verilog
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
|