module radio_controller_TxTiming ( input clk, input reset, input [0:1] clk_div, input sw_start, input [0:7] dly_GainRamp, input [0:7] dly_TxEn, input [0:7] dly_PHYStart, input [0:7] dly_PowerAmpEn, input [0:5] gainRamp_TxGainTarget, input [0:3] gainRamp_GainStep, input [0:3] gainRamp_TimeStep, output [0:5] gainRamp_TxGainOut, output TxEn, output PAEn, output PHYStart ); reg [0:11] timing_counter_big; reg [0: 7] timing_counter; //clk_div = 0 -> Select 8 LSB for fastest processing ([4:11]) //clk_div = 3 -> Select 8 MSB for slowest processing ([1:8]) always @* begin case(clk_div) 2'b00: timing_counter <= timing_counter_big[3:10]; 2'b01: timing_counter <= timing_counter_big[2:9]; 2'b10: timing_counter <= timing_counter_big[1:8]; 2'b11: timing_counter <= timing_counter_big[0:7]; endcase end //Enable the outputs when the timing counter has excedded the various control thresholds given by the dly_* inputs // A delay value of 254 will hold the corresponding output high forever // A delay value of 255 will hold the corresponding output low forever assign TxEn = (((timing_counter > dly_TxEn) || dly_TxEn == 8'd254) && dly_TxEn != 8'd255); assign PAEn = (((timing_counter > dly_PowerAmpEn) || dly_PowerAmpEn == 8'd254)&& dly_PowerAmpEn != 8'd255); assign PHYStart = (((timing_counter > dly_PHYStart) || dly_PHYStart == 8'd254) && dly_PHYStart != 8'd255);; //Instantiate a counter that starts when the software enables Tx mode and stops at its max value // The counter used for timing is sliced from this big counter always @( posedge clk ) begin if(reset | ~sw_start) timing_counter_big <= 0; else if(sw_start & timing_counter < 255) timing_counter_big <= timing_counter_big + 1; end //Tx gain ramp logic // Tx gain output starts at zero // Once master counte reaches dly_GainRamp, Tx gain output begins incrementing // Gain increments by gainRamp_GainStep every gainRamp_TimeStep cycles until reaching gainRamp_TxGainTarget // Gain remains at gainRamp_TxGainTarget until Tx is disabled and process starts over wire GainRampEn; wire [0:6] NewTxGain; reg [0:6] TxGainAccum; reg [0:3] GainRamp_clockEn_counter; wire [0:3] gainRamp_TimeStep_safe; wire [0:3] gainRamp_GainStep_safe; //If user inputs are zero, force them to 1 to avoid stalling the logic below // To bypass/disable the ramp, use 254/255 for dly_GainRamp assign gainRamp_TimeStep_safe = (gainRamp_TimeStep == 0) ? 4'd1 : gainRamp_TimeStep; assign gainRamp_GainStep_safe = (gainRamp_GainStep == 0) ? 4'd1 : gainRamp_GainStep; //Start the gain ramp after the specified delay // A delay of 254 bypasses the ramp and holds the output gain at the target indefinitely // A delay of 255 disables the remp and holds the output gain at 0 assign GainRampEn = (((timing_counter > dly_GainRamp) || dly_GainRamp == 8'd254) && dly_GainRamp != 8'd255); //The output gain signal is the output of an accumulator, enabled after dly_RampGain clock cycles //This signal is the input to the accumulator register. TxGainAccum has one extra MSB to ease overflow detection assign NewTxGain = ( (TxGainAccum + gainRamp_GainStep_safe) > gainRamp_TxGainTarget) ? gainRamp_TxGainTarget : (TxGainAccum + gainRamp_GainStep_safe); //The hw_TxGain output, which eventually connects to the radio's parallel gain control bus, // gets the 6 LSB of the internal accumulator value assign gainRamp_TxGainOut = TxGainAccum[1:6]; //Instiantiates a counter which runs once the timing counter exceeds the threshold // for starting the ramping of Tx gains; the counter increments every (TxGain_rampTimeStep+1) cycles always @( posedge clk ) begin if(reset || (~sw_start) || (~GainRampEn)) TxGainAccum <= 0; else if( GainRampEn & (GainRamp_clockEn_counter == gainRamp_TimeStep_safe)) TxGainAccum <= NewTxGain; end //Instantiate a counter used to drive the clock enable of the gain ramp counter above always @( posedge clk ) begin if(reset || (~sw_start) || (~GainRampEn) || (GainRamp_clockEn_counter == gainRamp_TimeStep_safe)) GainRamp_clockEn_counter <= 0; else GainRamp_clockEn_counter <= GainRamp_clockEn_counter + 1; end endmodule