`timescale 1ns/1ns

module dpress (	
	// Multiplexed AD bus from MSP430 GPIO pins
	input		bsmclk_ipad,
	input		baclk_ipad,
	inout [7:0]	ad_iopad,
	input		bus_reset_n_ipad,
	input		as_n_ipad,
	input		rd_n_ipad,
	input		wr_n_ipad,	
	
	// "Sand in the vaseline" faults
	input		water_in_air_n_ipad,
	input		water_in_oil_n_ipad,  

	// Pressure switch inputs
	input		local_empty_comp_1_ipad,
	input		local_empty_comp_2_ipad,
	input		local_empty_comp_3_ipad,

	input		local_burst_comp_1_ipad,
	input		local_burst_comp_2_ipad,
	input		local_burst_comp_3_ipad,

	input		local_squeeze_comp_1_ipad,
	input		local_squeeze_comp_2_ipad,
	input		local_squeeze_comp_3_ipad,
	
	// Remote pressure switch inputs
	input		remote_burst_ipad,
	input		remote_squeeze_ipad,
	input		remote_empty_ipad,
	
	// Pressure switch outputs to remote Dwarf
	output		local_burst_opad,
	output		local_squeeze_opad,
	output		local_empty_opad,	
	
	// Micelleanous outputs from command register
	output 		pressure_sensor_select_opad,
	output 		pressure_sensor_enable_n_opad,
	output		water_alarm_enable_n_opad, 	 
	
	// Outputs to the Dwarf Core's forward limit, 
	// reverse limit and home inputs	   
	output		ch0_fls_n_opad,
	output		ch0_rls_n_opad,
	output		ch0_home_n_opad,
	output		ch1_fls_n_opad,
	output		ch1_rls_n_opad,
	output		ch1_home_n_opad
);	

wire		synced_reset;
wire		synced_reset_wrt_aclk;	  

wire		remote_burst;
wire		remote_squeeze;		  
wire		remote_empty;

wire		water_in_air;
wire		water_in_oil;	

wire [1:0]	local_empty_switch_status; 
wire		local_empty_warning;
wire		local_empty;

wire [1:0]	local_burst_switch_status; 
wire		local_burst_warning;
wire		local_burst; 

wire [1:0]	local_squeeze_switch_status; 
wire		local_squeeze_warning;
wire		local_squeeze;	 

wire		sample_pump_fls;
wire		sample_pump_rls;
wire		sample_pump_home;	  

wire		high_pressure_pump_fls;
wire		high_pressure_pump_rls;	
wire		high_pressure_pump_home;

wire		intake_exhaust_pump_fls;
wire		intake_exhaust_pump_rls;
wire		intake_exhaust_pump_home; 

wire		ch0_fls;
wire		ch0_rls;
wire		ch0_home;

wire		ch1_fls;
wire		ch1_rls;
wire		ch1_home;	   

wire[7:0]	faults;	 
wire[5:0]	sample_faults;
wire[5:0]	resample_faults;
wire[2:0]	warnings;
wire[5:0]	switches;	
wire		water_faults;

wire[7:0]	incoming_data;
wire[7:0]	outgoing_data;
wire		drive_bus;	

wire		motors_disabled;
wire		resample;
wire		home_configuration;	 
wire		water_alarm_enable;	
wire		pressure_sensor_enable;	 

wire[2:0]	emptys;
wire[2:0]	squeezes;
wire[2:0]	bursts;	 

wire[5:0]	latched_faults;	
wire		latched_high_pressure_pump_fls; 
wire		latched_high_pressure_pump_rls; 
wire		latched_intake_exhaust_pump_fls; 
wire		latched_intake_exhaust_pump_rls;
wire		latched_sample_pump_fls;
wire		latched_sample_pump_rls;


// Reset Synchronizers, one for ACLK and another for SMCLK
// Asserts synced_reset asynchronously, negates it synchronously WRT bsmclk_ipad		   

reset_synchronizer smclk_reset_synch (
	.clock_i(bsmclk_ipad),
	.async_reset_i(~synced_reset_wrt_aclk),
	.sync_reset_o(synced_reset)
);		   

reset_synchronizer aclk_reset_synch (
	.clock_i(baclk_ipad),
	.async_reset_i(bus_reset_n_ipad),
	.sync_reset_o(synced_reset_wrt_aclk)
);
			
low_pass_filter lpf_remote_burst( 
	.clock_i(baclk_ipad),
	.reset_i(synced_reset_wrt_aclk),
	.raw_i(remote_burst_ipad),
	.clean_o(remote_burst)
);		

low_pass_filter lpf_remote_squeeze( 
	.clock_i(baclk_ipad),
	.reset_i(synced_reset_wrt_aclk),
	.raw_i(remote_squeeze_ipad),
	.clean_o(remote_squeeze)
);

low_pass_filter lpf_remote_empty( 
	.clock_i(baclk_ipad),
	.reset_i(synced_reset_wrt_aclk),
	.raw_i(remote_empty_ipad),
	.clean_o(remote_empty)
);	

low_pass_filter lpf_water_in_air ( 
	.clock_i(baclk_ipad),
	.reset_i(synced_reset_wrt_aclk),
	.raw_i(~water_in_air_n_ipad),
	.clean_o(water_in_air)
);		

low_pass_filter lpf_water_in_oil ( 
	.clock_i(baclk_ipad),
	.reset_i(synced_reset_wrt_aclk),
	.raw_i(~water_in_oil_n_ipad),
	.clean_o(water_in_oil)
);

warning_logic burst (	
	.aclk_i(baclk_ipad),
	.smclk_i(bsmclk_ipad),
	.reset_wrt_smclk_i(synced_reset),
	.reset_wrt_aclk_i(synced_reset_wrt_aclk),
	.raw_comparator_1_i(local_burst_comp_1_ipad),
	.raw_comparator_2_i(local_burst_comp_2_ipad),
	.raw_comparator_3_i(local_burst_comp_3_ipad),	   
	.status_o(local_burst_switch_status),
	.warning_o(local_burst_warning),
	.position_o(local_burst)
);

warning_logic squeeze (	
	.aclk_i(baclk_ipad),
	.smclk_i(bsmclk_ipad),
	.reset_wrt_smclk_i(synced_reset),
	.reset_wrt_aclk_i(synced_reset_wrt_aclk),
	.raw_comparator_1_i(local_squeeze_comp_1_ipad),
	.raw_comparator_2_i(local_squeeze_comp_2_ipad),
	.raw_comparator_3_i(local_squeeze_comp_3_ipad),	   
	.status_o(local_squeeze_switch_status),
	.warning_o(local_squeeze_warning),
	.position_o(local_squeeze)
);

warning_logic empty (	
	.aclk_i(baclk_ipad),
	.smclk_i(bsmclk_ipad),
	.reset_wrt_smclk_i(synced_reset),
	.reset_wrt_aclk_i(synced_reset_wrt_aclk),
	.raw_comparator_1_i(local_empty_comp_1_ipad),
	.raw_comparator_2_i(local_empty_comp_2_ipad),
	.raw_comparator_3_i(local_empty_comp_3_ipad),	   
	.status_o(local_empty_switch_status),
	.warning_o(local_empty_warning),
	.position_o(local_empty)
);				

assign emptys = {local_empty_comp_1_ipad, local_empty_comp_2_ipad, local_empty_comp_3_ipad };
assign squeezes = {local_squeeze_comp_1_ipad, local_squeeze_comp_2_ipad, local_squeeze_comp_3_ipad };
assign bursts = {local_burst_comp_1_ipad, local_burst_comp_2_ipad, local_burst_comp_3_ipad };

cpu_interface msp430_io
(	
	.clock_i(bsmclk_ipad),
	.reset_i(synced_reset),
	.as_n_i(as_n_ipad),
	.rd_n_i(rd_n_ipad),
	.wr_n_i(wr_n_ipad),	
	.remote_burst_i(remote_burst), 
	.remote_squeeze_i(remote_squeeze), 
	.remote_empty_i(remote_empty),
	.incoming_data_i(incoming_data),
	.switches_i(switches),
	.faults_i(faults),	
	.warnings_i(warnings),
	.emptys_i(emptys),
	.bursts_i(bursts),
	.squeezes_i(squeezes),
	.outgoing_data_o(outgoing_data), 
	.motors_disabled_o(motors_disabled), 
	.resample_o(resample), 
	.home_configuration_o(home_configuration),	
	.water_alarm_enable_o(water_alarm_enable),
	.pressure_sensor_enable_o(pressure_sensor_enable),
	.pressure_sensor_select_o(pressure_sensor_select_opad),	  
	.drive_bus_o(drive_bus), 
	.faults_o(latched_faults),
	.water_faults_o(water_faults)
); 

assign	sample_pump_fls					= local_squeeze	| remote_burst;
assign	sample_pump_rls					= local_burst	| remote_squeeze;
assign	sample_pump_home				= (home_configuration) ? 
												(local_empty | remote_empty) : (local_empty & remote_empty);	  

assign	high_pressure_pump_fls			= local_burst 	| remote_burst;
assign	high_pressure_pump_rls			= local_burst 	| remote_burst;	
assign	high_pressure_pump_home			= 1'b0;

assign	intake_exhaust_pump_fls			= local_burst	| remote_burst;
assign	intake_exhaust_pump_rls			= local_squeeze	| remote_squeeze;
assign	intake_exhaust_pump_home		= (home_configuration) ? 
											(local_empty | remote_empty) : (local_empty & remote_empty);  

assign	latched_high_pressure_pump_fls	= latched_faults[5]; 
assign	latched_high_pressure_pump_rls	= latched_faults[4]; 
assign	latched_intake_exhaust_pump_fls	= latched_faults[3];  
assign	latched_intake_exhaust_pump_rls	= latched_faults[2]; 
assign	latched_sample_pump_fls			= latched_faults[1]; 
assign	latched_sample_pump_rls			= latched_faults[0]; 

assign	ch0_fls							= (resample) ? latched_high_pressure_pump_fls	: latched_sample_pump_fls;
assign	ch0_rls							= (resample) ? latched_high_pressure_pump_rls	: latched_sample_pump_rls;
assign	ch0_home						= (resample) ? high_pressure_pump_home	: sample_pump_home;

assign	ch1_fls							= (resample) ? latched_intake_exhaust_pump_fls	: 1'b0;
assign	ch1_rls							= (resample) ? latched_intake_exhaust_pump_rls	: 1'b0;
assign	ch1_home						= (resample) ? intake_exhaust_pump_home	: 1'b0;

assign	ch0_fls_n_opad					= ~(ch0_fls  | water_faults | motors_disabled);
assign	ch0_rls_n_opad					= ~(ch0_rls  | water_faults | motors_disabled);
assign	ch0_home_n_opad					= ~ch0_home;

assign	ch1_fls_n_opad					= ~(ch1_fls  | water_faults | motors_disabled);
assign	ch1_rls_n_opad					= ~(ch1_rls  | water_faults | motors_disabled);
assign	ch1_home_n_opad					= ~ch1_home;	

assign	local_burst_opad				= local_burst;
assign	local_squeeze_opad				= local_squeeze;
assign	local_empty_opad				= local_empty;	 

assign faults[7]						= water_in_air;
assign faults[6]						= water_in_oil;

assign	sample_faults					= { 4'b0000,
											sample_pump_fls,
											sample_pump_rls };

assign	resample_faults					= { high_pressure_pump_fls, 
											high_pressure_pump_rls, 
					    					intake_exhaust_pump_fls, 
											intake_exhaust_pump_rls, 
											2'b00 };
											
assign faults[5:0]						= (resample) ? resample_faults : sample_faults;

assign warnings							= { local_burst_warning, 
											local_squeeze_warning, 
											local_empty_warning };		

assign switches							= { local_burst_switch_status, 
											local_squeeze_switch_status, 
											local_empty_switch_status };	  

// Grab the write data from the CPLD AD[7:0] pins no matter what
assign incoming_data 					= ad_iopad;
assign ad_iopad 						= (drive_bus) ? outgoing_data : 8'bz; 

// Connect the write only register bits to the pins
assign	water_alarm_enable_n_opad		= ~water_alarm_enable;
assign	pressure_sensor_enable_n_opad	= ~pressure_sensor_enable;
			
endmodule