`timescale 1ns/1ns	

module msp430_bfm_tb;

wire        mclk;		// 4 MHz
wire		aclk;		// 4 KHz
wire		reset_n;
tri  [7:0]	data; 
wire		as_n;
wire		rd_n;
wire		wr_n; 	   

wire		local_empty_comp_1;
wire		local_empty_comp_2;
wire		local_empty_comp_3;

wire		local_burst_comp_1;
wire		local_burst_comp_2;
wire		local_burst_comp_3;

wire		local_squeeze_comp_1;  
wire		local_squeeze_comp_2;
wire		local_squeeze_comp_3;	  

wire		local_burst;
wire		local_squeeze;
wire		local_empty;	   

wire		remote_burst_n;
wire		remote_squeeze_n;
wire		remote_empty_n;

wire		pressure_sensor_select;
wire		pressure_sensor_enable_n;
wire		water_alarm_enable_n;	

wire		ch0_fls_n;
wire		ch0_rls_n;
wire		ch0_home_n;
wire		ch1_fls_n;
wire		ch1_rls_n;
wire		ch1_home_n;	

// Simulate SMCLK from the MSP430
oscillator #(.HALF_PERIOD(125)) fast_clock (
	.clock_o(mclk)
);	   

// Simulate ACLK from the MSP430
oscillator #(.HALF_PERIOD(125000)) slow_clock (
	.clock_o(aclk)
);

msp430_bfm msp430(
	.clock_i(mclk),
	.ad_io(data),
	.reset_n_o(reset_n),
	.as_n_o(as_n),
	.rd_n_o(rd_n),
	.wr_n_o(wr_n)
);		

local_switch 	empty ( 
	.clock_i(aclk),
	.comparator_3_o(local_empty_comp_3),
	.comparator_2_o(local_empty_comp_2),
	.comparator_1_o(local_empty_comp_1)
);	 

local_switch 	burst (	
	.clock_i(aclk),
	.comparator_3_o(local_burst_comp_3),
	.comparator_2_o(local_burst_comp_2),
	.comparator_1_o(local_burst_comp_1)
);

local_switch	squeeze (	
	.clock_i(aclk),
	.comparator_3_o(local_squeeze_comp_3),
	.comparator_2_o(local_squeeze_comp_2),
	.comparator_1_o(local_squeeze_comp_1)
); 

remote_switches remote (  
	.remote_burst_n_o(remote_burst_n),
	.remote_squeeze_n_o(remote_squeeze_n),
	.remote_empty_n_o(remote_empty_n)
);

dpress dwsm(   
	// Multiplexed AD bus from MSP430 GPIO pins
	.bsmclk_ipad(mclk),
	.baclk_ipad(aclk),
	.ad_iopad(data),
	.bus_reset_n_ipad(reset_n),
	.as_n_ipad(as_n),
	.rd_n_ipad(rd_n),
	.wr_n_ipad(wr_n),	
	
	// "Sand in the vaseline" faults
	.water_in_air_n_ipad(1'b1),
	.water_in_oil_n_ipad(1'b1),  

	// Pressure switch inputs
	.local_empty_comp_1_ipad(local_empty_comp_1),
	.local_empty_comp_2_ipad(local_empty_comp_2),
	.local_empty_comp_3_ipad(local_empty_comp_3),	

	.local_burst_comp_1_ipad(local_burst_comp_1),
	.local_burst_comp_2_ipad(local_burst_comp_2),
	.local_burst_comp_3_ipad(local_burst_comp_3),

	.local_squeeze_comp_1_ipad(local_squeeze_comp_1),
	.local_squeeze_comp_2_ipad(local_squeeze_comp_2),
	.local_squeeze_comp_3_ipad(local_squeeze_comp_3),
	
	// Remote pressure switch inputs
	.remote_burst_ipad(1'b0),
	.remote_squeeze_ipad(1'b0),
	.remote_empty_ipad(1'b0),
	
	// Pressure switch outputs to remote Dwarf 
	.local_burst_opad(local_burst),
	.local_squeeze_opad(local_squeeze),
	.local_empty_opad(local_empty),		   
	
	// Micelleanous outputs from command register	
	.pressure_sensor_select_opad(pressure_sensor_select),
	.pressure_sensor_enable_n_opad(pressure_sensor_enable_n),
	.water_alarm_enable_n_opad(water_alarm_enable_n),
	
	// Outputs to the Dwarf Core's forward limit, 
	// reverse limit and home inputs	   
	.ch0_fls_n_opad(ch0_fls_n),
	.ch0_rls_n_opad(ch0_rls_n),
	.ch0_home_n_opad(ch0_home_n),
	.ch1_fls_n_opad(ch1_fls_n),
	.ch1_rls_n_opad(ch1_rls_n),
	.ch1_home_n_opad(ch1_home_n)				 
);

task power_on;
begin	 
	msp430.reset;
	empty.opened;
	burst.opened;
	squeeze.opened;
	@(negedge aclk);
	@(negedge aclk);  
	@(negedge aclk);
	remote.indicate_normal;
	// Reset the Processor
end
endtask

task execute;
begin  	 
	`include "tests\test_diagnostic_register.vh"	   
	//  Enable the "motors" and warnings by writing the command register	
	msp430.read_dwarf_and_check(8'h1C, 8'h00);	 
	// No warnings or faults should be indicated
	msp430.read_dwarf_and_check(8'h1D, 8'h00);
	msp430.read_dwarf_and_check(8'h1E, 8'h00); 
	// Enable warnings
	msp430.write_dwarf(8'h1C, 8'h00); 
	// Test the operation of the empty switch
	`include "tests\empty_switch_warning_tests.vh"	 
	// Test the operation of the burst switch
	`include "tests\burst_switch_warning_tests.vh" 
	// Test the operation of the squeeze switch
	`include "tests\squeeze_switch_warning_tests.vh"
	msp430.idle;
end	
endtask

initial begin 
	// Initialize the state of the local switches 
	power_on;
	execute;
	$finish;
end

endmodule