`timescale 10ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer:       James C. Ahlstrom
// 
// Create Date:    12:31:22 4/4/2007
// Design Name:    CW Transmitter
// Module Name:    duc1cw
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////

module duc1cw(
	output wire signed [13:0] dac_data,	// parallel data to DAC
	output dac_clock,			// clock for DAC
	input clk,					// master clock
	input [7:0] in_data,		// 8-bit port from MCU
	input [1:0] in_addr,		// address bus from MCU
	input in_strobe,			// write strobe from MCU
	output wire red_led,		// red LED on front panel
	output wire green_led,		// green LED on front panel,
	input keying);				// 0 == key up; 1 == key down
	
	parameter max_amplitude = 20'd310000;	// maximum amplitude (can be +1 higher)
	parameter zero = 20'd0;		// imaginary part of amplitude
	reg [19:0] amplitude;				// current amplitude: 0 to max_amplitude
	reg ramp_change;					// lower speed clock
	reg ramp_enable, ramp_direction;	// for amplitude up/down counter
	reg [3:0] strobe_timer;				// timer for in_strobe
	reg [2:0] strobe_address;			// address for in_strobe data at in_addr == 2
	parameter strobe_timeout = 4'd12;	// record MCU data at this timeout
	
	reg [31:0] delta;		// CORDIC tuning word - 32 bits
	//parameter delta = 32'd334053012;	// 7MHz for 90 MHz clock

	assign red_led = keying;
	assign green_led = 1;

	assign dac_clock = ~clk;
	
	cordic1 cordic(dac_data, clk, delta, amplitude, zero);
			
	always @(posedge clk)
	begin
		////// Read in data from the MCU.
		// There may be ringing on in_strobe from the MCU.  Wait for strobe_timer
		// before accepting the data.
		if (in_strobe)
			begin
				if (~&strobe_timer)	// count up only to the maximum value
					begin
						if (strobe_timer == strobe_timeout)
							begin
								case (in_addr)				// look at address to see where to put data
								0: ;
								1:	begin					// commands - check in_data
									case (in_data)
										0: ;						// FPGA reset
										1: strobe_address <= 0;		// reset address for phase data
										default: ;
									endcase
									end
								2: begin
									case (strobe_address)	// read in two phase words, 4 bytes each
										0: delta[7:0] <= in_data;	// first four byte tuning word
										1: delta[15:8] <= in_data;
										2: delta[23:16] <= in_data;
										3: delta[31:24] <= in_data;
										// The next four bytes are the secondary tuning word; not used.
										default: ;
									endcase
									strobe_address <= strobe_address + 1'd1;
									end
								3: ;
								endcase
							end
						strobe_timer <= strobe_timer + 1'd1;
					end
			end
		else
			begin
				strobe_timer <= 0;	// zero the timer
			end
		////// Ramp the amplitude up or down
		ramp_change <= ramp_change + 1'd1;		// half speed clock
		// note that ramp_enable changes on the NEXT clock; so change to un-enable
		//   on two values of ramp amplitude.  For decrement, on 0 or 1.
		if (ramp_change)
			begin
				if (keying)
					begin
						ramp_direction <= 1'd1;		// count up
						if (amplitude[19:1] == max_amplitude[19:1])	// two values
							ramp_enable <= 1'd0;
						else
							ramp_enable <= 1'd1;
					end
				else
					begin
						ramp_direction <= 1'd0;		// count down
						if (amplitude[19:1] == 19'd0)	// amplitude 0 or 1
							ramp_enable <= 1'd0;
						else
							ramp_enable <= 1'd1;
					end
				if (ramp_enable)	// amplitude up/down counter
					begin
						if (ramp_direction)
							amplitude <= amplitude + 1'd1;
						else
							amplitude <= amplitude - 1'd1;
					end
			end
			
	end
endmodule
