// ============================================================================
// Copyright (c) 2010 by Terasic Technologies Inc. 
// ============================================================================
//
// Permission:
//
//   Terasic grants permission to use and modify this code for use
//   in synthesis for all Terasic Development Boards and Altera Development 
//   Kits made by Terasic.  Other use of this code, including the selling 
//   ,duplication, or modification of any portion is strictly prohibited.
//
// Disclaimer:
//
//   This VHDL/Verilog or C/C++ source code is intended as a design reference
//   which illustrates how these types of functions can be implemented.
//   It is the user's responsibility to verify their design for
//   consistency and functionality through the use of formal
//   verification methods.  Terasic provides no warranty regarding the use 
//   or functionality of this code.
//
// ============================================================================
//           
//                     Terasic Technologies Inc
//                     356 Fu-Shin E. Rd Sec. 1. JhuBei City,
//                     HsinChu County, Taiwan
//                     302
//
//                     web: http://www.terasic.com/
//                     email: support@terasic.com
//
// ============================================================================
// Major Functions/Design Description:
//
//   Please refer to DE4_UserManual.pdf in DE4 system CD.
//
// ============================================================================
// Revision History:
// ============================================================================
//   Ver.: |Author:   |Mod. Date:    |Changes Made:
//   V1.0  |Richard   |10/06/30      |
// ============================================================================

module TERAISC_PWM(
	clk,
	reset_n,
	//
	s_cs,
	s_address,
	s_write,
	s_writedata,
	s_read,
	s_readdata,
	
	//
	PWM
);

`define REG_TOTAL_DUR	0
`define REG_HIGH_DUR	1

input 				clk;
input				reset_n;

input				s_cs;
input				s_address;
input				s_read;
output	reg	[31:0]	s_readdata;
input				s_write;
input		[31:0]	s_writedata;

output		PWM;

reg			[31:0]	total_dur;
reg			[31:0]	high_dur;
reg	[31:0]	tick;


always @ (posedge clk or negedge reset_n)
begin
	if (~reset_n)
	begin
		high_dur <= 0;
		total_dur <= 0;
	end
	else if (s_cs & s_write)
	begin
		if (s_address == `REG_TOTAL_DUR)
			total_dur <= s_writedata;
		else if (s_address == `REG_HIGH_DUR)
			high_dur <= s_writedata;
	end
	else if (s_cs & s_read)
	begin
		if (s_address == `REG_TOTAL_DUR)
			s_readdata <= total_dur;
		else if (s_address == `REG_HIGH_DUR)
			s_readdata <= high_dur;
	end
		
end

always @ (posedge clk or negedge reset_n)
begin
	if (~reset_n)
	begin
		tick <= 0;
	end
	else if (tick >= total_dur)
	begin
		tick <= 0;
	end
	else
		tick <= tick + 1;
end

assign PWM = (tick < high_dur)?1'b1:1'b0;

endmodule
