`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // _ _ ____ // | | ___ ___| |__ / ___| __ _ ___ // _ | |/ _ \/ __| '_ \ | | _ / _` |/ _ \ // | |_| | (_) \__ \ | | | | |_| | (_| | (_) | // \___/ \___/|___/_| |_| \____|\__,_|\___/ // // Create Date: 2023/02/25 15:20:22 // Design Name: // Module Name: tx_pre_process // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module tx_pre_process #( parameter ADC_DATA_WIDTH = 12, parameter PRBS = 128'b00000011000010100011110010001011001110101001111101000011100010010011011010110111101100011010010111011100110010101011111110000001, // inverse pseudorandom bit sequence, [0,flip(PRSB7)] parameter PRBS_LEN = 128, // length of pseudorandom bit sequence parameter INTERP_FACTOR = 8 // interpolation factor, max inter-channel delay ranges in [-INTERP_FACTOR+1,INTERP_FACTOR-1] ) ( // clock & reset input clk , input rst , // input data input [ADC_DATA_WIDTH-1:0] tx_data_ch1_i , input [ADC_DATA_WIDTH-1:0] tx_data_ch1_q , input [ADC_DATA_WIDTH-1:0] tx_data_ch2_i , input [ADC_DATA_WIDTH-1:0] tx_data_ch2_q , // ad9361 calibration interface input ad9361_tx_switch , // input [$clog2(ADC_DATA_WIDTH)-1:0] bb_rshift, // output data output [ADC_DATA_WIDTH-1:0] tx_ch1_i , output [ADC_DATA_WIDTH-1:0] tx_ch1_q , output [ADC_DATA_WIDTH-1:0] tx_ch2_i , output [ADC_DATA_WIDTH-1:0] tx_ch2_q ); integer i; // reg [$clog2(PRBS_LEN*INTERP_FACTOR)-1 : 0] chip_interp_cnt = 'b0; reg signed [ADC_DATA_WIDTH-1:0] tx_pn_i = 'b0; reg signed [ADC_DATA_WIDTH-1:0] tx_pn_q = 'b0; always @(posedge clk) begin if (rst) begin chip_interp_cnt <= 'b0; end else begin chip_interp_cnt <= chip_interp_cnt + 1'b1; end end always @(posedge clk) begin if (rst) begin tx_pn_i <= 'b0; tx_pn_q <= 'b0; end else begin tx_pn_i <= PRBS[chip_interp_cnt[$clog2(PRBS_LEN*INTERP_FACTOR)-1 -: $clog2(PRBS_LEN)]] ? {1'b0,{(ADC_DATA_WIDTH-1){1'b1}}} : {1'b1,{(ADC_DATA_WIDTH-2){1'b0}},1'b1}; // (1 or 0) ? 4'b0111 : 4'b1001 tx_pn_q <= PRBS[chip_interp_cnt[$clog2(PRBS_LEN*INTERP_FACTOR)-1 -: $clog2(PRBS_LEN)]] ? {1'b1,{(ADC_DATA_WIDTH-2){1'b0}},1'b1} : {1'b0,{(ADC_DATA_WIDTH-1){1'b1}}}; // (1 or 0) ? 4'b1001 : 4'b0111 end end // buffer input control signals (clock domain crossing from ps to pl clock domain) reg ad9361_tx_switch_d1 = 'b0; reg ad9361_tx_switch_d2 = 'b0; always @(posedge clk) begin ad9361_tx_switch_d1 <= ad9361_tx_switch; ad9361_tx_switch_d2 <= ad9361_tx_switch_d1; end reg [ADC_DATA_WIDTH-1 : 0] tx_ch1_i_buf = 'b0; reg [ADC_DATA_WIDTH-1 : 0] tx_ch1_q_buf = 'b0; reg [ADC_DATA_WIDTH-1 : 0] tx_ch2_i_buf = 'b0; reg [ADC_DATA_WIDTH-1 : 0] tx_ch2_q_buf = 'b0; assign tx_ch1_i = tx_ch1_i_buf; assign tx_ch1_q = tx_ch1_q_buf; assign tx_ch2_i = tx_ch2_i_buf; assign tx_ch2_q = tx_ch2_q_buf; always @(posedge clk) begin if (rst) begin tx_ch1_i_buf <= 'b0; tx_ch1_q_buf <= 'b0; tx_ch2_i_buf <= 'b0; tx_ch2_q_buf <= 'b0; end else if (ad9361_tx_switch_d2) begin tx_ch1_i_buf <= tx_pn_i >>> bb_rshift; tx_ch1_q_buf <= tx_pn_q >>> bb_rshift; tx_ch2_i_buf <= tx_pn_i >>> bb_rshift; tx_ch2_q_buf <= tx_pn_q >>> bb_rshift; end else begin tx_ch1_i_buf <= tx_data_ch1_i; tx_ch1_q_buf <= tx_data_ch1_q; tx_ch2_i_buf <= tx_data_ch2_i; tx_ch2_q_buf <= tx_data_ch2_q; end end endmodule ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 2023/02/25 15:50:45 // Design Name: // Module Name: tb_tx_pre_process // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// // module tb_tx_pre_process; // reg clk = 1'b1; // reg rst = 1'b1; // reg [11:0] tx_data_ch1_i = 'b0; // reg [11:0] tx_data_ch1_q = 'b0; // reg [11:0] tx_data_ch2_i = 'b0; // reg [11:0] tx_data_ch2_q = 'b0; // reg ad9361_tx_switch = 1'b0; // reg [3:0] bb_rshift = 4'd3; // wire [11:0] tx_ch1_i; // wire [11:0] tx_ch1_q; // wire [11:0] tx_ch2_i; // wire [11:0] tx_ch2_q; // tx_pre_process u_tx_pre_process // ( // // clock & reset // .clk (clk ), // .rst (rst ), // // input data // .tx_data_ch1_i (tx_data_ch1_i ), // .tx_data_ch1_q (tx_data_ch1_q ), // .tx_data_ch2_i (tx_data_ch2_i ), // .tx_data_ch2_q (tx_data_ch2_q ), // // ad9361 calibration interface // .ad9361_tx_switch (ad9361_tx_switch ), // // // .bb_rshift (bb_rshift ), // // output data // .tx_ch1_i (tx_ch1_i ), // .tx_ch1_q (tx_ch1_q ), // .tx_ch2_i (tx_ch2_i ), // .tx_ch2_q (tx_ch2_q ) // ); // initial begin // #102 rst = 1'b0; // #100 ad9361_tx_switch = 1'b1; // #10000 ad9361_tx_switch = 1'b0; // end // always #10 clk = ~clk; // always @(posedge clk) begin // if (rst) begin // tx_data_ch1_i <= 'b0; // tx_data_ch1_q <= 'b0; // tx_data_ch2_i <= 'b0; // tx_data_ch2_q <= 'b0; // end // else begin // tx_data_ch1_i <= tx_data_ch1_i + 12'd1; // tx_data_ch1_q <= tx_data_ch1_q + 12'd2; // tx_data_ch2_i <= tx_data_ch2_i + 12'd3; // tx_data_ch2_q <= tx_data_ch2_q + 12'd4; // end // end // endmodule