ddc_input_interface.v
1 `timescale 1ns / 1ps 2 // ddc_input_interface.v 3 module ddc_input_interface ( 4 input wire clk, // 100MHz 5 input wire reset_n, 6 7 // DDC Input (18-bit) 8 input wire signed [17:0] ddc_i, 9 input wire signed [17:0] ddc_q, 10 input wire valid_i, 11 input wire valid_q, 12 13 // Scaled output (16-bit) 14 output reg signed [15:0] adc_i, 15 output reg signed [15:0] adc_q, 16 output reg adc_valid, 17 18 // Status 19 output wire data_sync_error 20 ); 21 22 // Synchronize valid signals 23 reg valid_i_reg, valid_q_reg; 24 reg valid_sync; 25 26 always @(posedge clk or negedge reset_n) begin 27 if (!reset_n) begin 28 valid_i_reg <= 1'b0; 29 valid_q_reg <= 1'b0; 30 valid_sync <= 1'b0; 31 adc_valid <= 1'b0; 32 end else begin 33 valid_i_reg <= valid_i; 34 valid_q_reg <= valid_q; 35 36 // Require both I and Q valid simultaneously 37 valid_sync <= valid_i_reg && valid_q_reg; 38 adc_valid <= valid_sync; 39 end 40 end 41 42 // Scale 18-bit to 16-bit with convergent rounding + saturation 43 // ddc_i[17:2] extracts the upper 16 bits; ddc_i[1] is the rounding bit. 44 // Without saturation, 0x7FFF + 1 = 0x8000 (sign flip at positive full scale). 45 // Fix: saturate to 0x7FFF when rounding would overflow a positive value. 46 // Negative values cannot overflow: the most negative 18-bit value (-131072) 47 // truncates to -8192 (0x8000 as 16-bit) and rounding only moves toward zero. 48 wire [15:0] trunc_i = ddc_i[17:2]; 49 wire [15:0] trunc_q = ddc_q[17:2]; 50 wire round_i = ddc_i[1]; 51 wire round_q = ddc_q[1]; 52 53 // Overflow occurs only when truncated value is max positive AND round bit set 54 wire sat_i = (trunc_i == 16'h7FFF) & round_i; 55 wire sat_q = (trunc_q == 16'h7FFF) & round_q; 56 57 always @(posedge clk) begin 58 if (valid_sync) begin 59 adc_i <= sat_i ? 16'sh7FFF : (trunc_i + {15'b0, round_i}); 60 adc_q <= sat_q ? 16'sh7FFF : (trunc_q + {15'b0, round_q}); 61 end 62 end 63 64 // Error detection 65 assign data_sync_error = (valid_i_reg ^ valid_q_reg); 66 67 endmodule