// This file is part of the Universal Laboratory (uLab)
//
// © 2007 - 2019 Raptor Engineering, LLC
// All Rights Reserved
//
// Licensed under the terms of the AGPL v3

module guest_fpga_top(clk, reset, four_bit_input, four_bit_output, eight_bit_input, eight_bit_output, sixteen_bit_input, sixteen_bit_output, lcd_data_in_address, lcd_data_in_data, lcd_data_in_enable, led_segment_bus, led_digit_select);
	input clk;
	input reset;
	
	input [3:0] four_bit_input;
	output reg [3:0] four_bit_output;
	input [7:0] eight_bit_input;
	output reg [7:0] eight_bit_output;
	input [15:0] sixteen_bit_input;
	output reg [15:0] sixteen_bit_output;
	
	output reg [5:0] lcd_data_in_address;
	output reg [7:0] lcd_data_in_data;
	output reg lcd_data_in_enable;

	output reg [7:0] led_segment_bus;
	output reg [3:0] led_digit_select;

	reg [7:0] lcd_sample_counter = 48;							// Create a sample LCD display counter register
	reg [31:0] lcd_character_change_timer = 0;						// Wait a certain number of cycles before loading a new character
	reg [5:0] lcd_current_character = 0;							// The current character's address
	
	always @(posedge clk) begin
		four_bit_output = four_bit_input;						// Loopback
		eight_bit_output = eight_bit_input[3:0] + eight_bit_input[7:4];			// Sample adder
		sixteen_bit_output = sixteen_bit_input[15:8] * sixteen_bit_input[7:0];		// Sample multiplier
		
		// Sample LCD display routine		
		lcd_data_in_address = lcd_current_character;					// Character location on the LCD display
		lcd_data_in_data = lcd_sample_counter;						// Character code to display
		lcd_data_in_enable = 1;								// Enable data transmission
		
		// Cycle through all character positions
		lcd_current_character = lcd_current_character + 1;
		if (lcd_current_character > 31) begin
			lcd_current_character = 16;
		end
		
		// Cycle through the numbers 0 to 9 at one second intervals
		lcd_character_change_timer = lcd_character_change_timer + 1;
		if (lcd_character_change_timer > 6000000) begin					// Wait one second in between character changes
			lcd_character_change_timer = 0;
			lcd_sample_counter = lcd_sample_counter + 1;
			if (lcd_sample_counter > 57) begin					// Character code for the digit 9
				lcd_sample_counter = 48;					// Character code for the digit 0
			end
		end
	end

	// 7-segment LED display driver clock generator
	reg sseg_clock;
	reg [10:0] sseg_clock_counter;

	always @(posedge clk) begin
		sseg_clock_counter = sseg_clock_counter + 1;
		if (sseg_clock_counter > 1023) begin
			sseg_clock_counter = 0;
			sseg_clock = ~sseg_clock;
		end
	end

	// 7-segment LED display driver
	// led_segment_bus and led_digit_select are active low
	// The bit sequence, MSB to LSB, is dp a b c d e f g
	// Segment letters are taken from ug130.pdf page 15

	// 0: 8'b10000001
	// 1: 8'b11001111
	// 2: 8'b10010010
	// 3: 8'b10000110
	reg [2:0] current_anode;
	always @(posedge sseg_clock) begin
		current_anode = current_anode + 1;
		if (current_anode > 3) begin
			current_anode = 0;
		end

		case (current_anode)
			0: begin
				led_digit_select = 4'b1110;
				led_segment_bus = 8'b10000001;
			end
			1: begin
				led_digit_select = 4'b1101;
				led_segment_bus = 8'b11001111;
			end
			2: begin
				led_digit_select = 4'b1011;
				led_segment_bus = 8'b10010010;
			end
			3: begin
				led_digit_select = 4'b0111;
				led_segment_bus = 8'b10000110;
			end
		endcase
	end
endmodule
