summaryrefslogtreecommitdiffstats
path: root/fpga
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2012-05-14 18:15:16 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2012-05-14 18:15:16 -0500
commitdb7e77be8f42046c69a833321e2b6608f9cad4b7 (patch)
treeea63171b09cb565986776c801a386ac38af35393 /fpga
parent408e828f4732c9bb4aa3673c87d85109e06c08e1 (diff)
downloadulab-db7e77be8f42046c69a833321e2b6608f9cad4b7.tar.gz
ulab-db7e77be8f42046c69a833321e2b6608f9cad4b7.zip
Add public domain FPGA files for Xilinx s3/s3e
Diffstat (limited to 'fpga')
-rw-r--r--fpga/xilinx/digilent/spartan_3/remote_access.v1180
-rw-r--r--fpga/xilinx/digilent/spartan_3e/remote_access.v1184
2 files changed, 2364 insertions, 0 deletions
diff --git a/fpga/xilinx/digilent/spartan_3/remote_access.v b/fpga/xilinx/digilent/spartan_3/remote_access.v
new file mode 100644
index 0000000..4a42a61
--- /dev/null
+++ b/fpga/xilinx/digilent/spartan_3/remote_access.v
@@ -0,0 +1,1180 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company: Pearson Computing
+// Engineer: Timothy Pearson
+//
+// Create Date: 11:58:21 07/07/2007
+// Design Name: Remote Access Driver
+// Module Name: remote_access
+// Project Name: Remote Access Driver
+// Target Devices: Digilent Spartan 3E Development Board
+// Tool versions: Xilinx ISE v9.1 SP3
+// Description: Serial remote access driver and LCD display driver
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments: Released into the Public Domain
+//
+//////////////////////////////////////////////////////////////////////////////////
+module remote_access(
+ input main_fifty_clock, // 50MHz clock in
+ input [3:0] remote_access_4_bit_output, // 4 bit output from the user program to remote access client
+ output [3:0] remote_access_4_bit_input, // 4 bit input from the remote access client to user program
+ input [7:0] remote_access_8_bit_output, // 8 bit output from the user program to remote access client
+ output [7:0] remote_access_8_bit_input, // 8 bit input from the remote access client to user program
+ input [15:0] remote_access_16_bit_output, // 16 bit output from the user program to the remote access client
+ output [15:0] remote_access_16_bit_input, // 16 bit input from the remote access client to the user program
+ input serial_port_receiver,
+ output serial_port_transmitter,
+ input remote_access_input_enable,
+ input [7:0] local_input,
+ input seize_serial_tx,
+ input [7:0] serial_tx_data,
+ input serial_tx_strobe,
+ output [7:0] serial_rx_data,
+ output serial_rx_strobe,
+ input [5:0] lcd_data_in_address,
+ input [7:0] lcd_data_in_data,
+ input lcd_data_in_enable,
+ input sram_wren_in,
+ input sram_clock_in,
+ input [7:0] sram_data_in,
+ input [13:0] sram_address_in,
+ output [7:0] sram_data_out,
+ output sram_available,
+ input sram_processing_done,
+ input [7:0] led_segment_bus,
+ input [3:0] led_digit_select);
+
+ reg [7:0] remote_access_4_bit_input_reg;
+ reg [7:0] remote_access_8_bit_input_reg;
+ reg [15:0] remote_access_16_bit_input_reg;
+ reg [3:0] remote_access_lcd_data_out_reg;
+ reg remote_access_lcd_rs_out_reg;
+ reg remote_access_lcd_rw_out_reg;
+ reg remote_access_lcd_enable_out_reg;
+ reg [7:0] serial_rx_data_reg;
+ reg serial_rx_strobe_reg;
+ reg sram_available_reg;
+ reg startup_needed = 1;
+
+ assign remote_access_4_bit_input = remote_access_4_bit_input_reg;
+ assign remote_access_8_bit_input = remote_access_8_bit_input_reg;
+ assign remote_access_16_bit_input = remote_access_16_bit_input_reg;
+ assign remote_access_lcd_data_out = remote_access_lcd_data_out_reg;
+ assign remote_access_lcd_rs_out = remote_access_lcd_rs_out_reg;
+ assign remote_access_lcd_rw_out = remote_access_lcd_rw_out_reg;
+ assign remote_access_lcd_enable_out = remote_access_lcd_enable_out_reg;
+ assign serial_rx_data = serial_rx_data_reg;
+ assign serial_rx_strobe = serial_rx_strobe_reg;
+ assign sram_available = sram_available_reg;
+
+ //-----------------------------------------------------------------------------------
+ //
+ // Create a 4.16MHz clock for the LCD display driver and a 25MHz clock
+ // for the serial receiver.
+ //
+ //-----------------------------------------------------------------------------------
+
+ reg four_mhz_clk;
+ reg clk_div_by_two;
+ reg clk_div_by_four;
+ reg clk_div_by_eight;
+ reg [3:0] fifty_clock_divider = 0;
+
+ always @(posedge main_fifty_clock) begin
+ fifty_clock_divider = fifty_clock_divider + 1;
+ if (fifty_clock_divider > 12) begin
+ four_mhz_clk = !four_mhz_clk;
+ fifty_clock_divider = 0;
+ end
+ end
+
+ always @(posedge main_fifty_clock) begin
+ clk_div_by_two = !clk_div_by_two;
+ end
+
+ always @(posedge clk_div_by_two) begin
+ clk_div_by_four = !clk_div_by_four;
+ end
+
+ always @(posedge clk_div_by_four) begin
+ clk_div_by_eight = !clk_div_by_eight;
+ end
+
+ //-----------------------------------------------------------------------------------
+ //
+ // Keep track of what is on the LED display
+ //
+ //-----------------------------------------------------------------------------------
+
+ reg [7:0] led_display_bytes [3:0];
+ reg [4:0] digit_blanker_1 = 0;
+ reg [4:0] digit_blanker_2 = 0;
+ reg [4:0] digit_blanker_3 = 0;
+ reg [4:0] digit_blanker_4 = 0;
+
+ always @(negedge clk_div_by_eight) begin
+ if (led_digit_select[0] == 0) begin
+ led_display_bytes[0] = led_segment_bus;
+ digit_blanker_1 = 0;
+ end
+
+ if (led_digit_select[1] == 0) begin
+ led_display_bytes[1] = led_segment_bus;
+ digit_blanker_2 = 0;
+ end
+
+ if (led_digit_select[2] == 0) begin
+ led_display_bytes[2] = led_segment_bus;
+ digit_blanker_3 = 0;
+ end
+
+ if (led_digit_select[3] == 0) begin
+ led_display_bytes[3] = led_segment_bus;
+ digit_blanker_4 = 0;
+ end
+
+ if (digit_blanker_1 > 30) begin
+ led_display_bytes[0] = 255;
+ end
+
+ if (digit_blanker_2 > 30) begin
+ led_display_bytes[1] = 255;
+ end
+
+ if (digit_blanker_3 > 30) begin
+ led_display_bytes[2] = 255;
+ end
+
+ if (digit_blanker_4 > 30) begin
+ led_display_bytes[3] = 255;
+ end
+ end
+
+ //-----------------------------------------------------------------------------------
+ //
+ // Instantiate the data storage RAM for signal processing
+ //
+ //-----------------------------------------------------------------------------------
+
+ reg data_storage_remote_enable = 0;
+ wire data_storage_clka;
+ wire [7:0] data_storage_dina;
+ wire [13:0] data_storage_addra;
+ wire data_storage_write_enable;
+ wire [7:0] data_storage_data_out;
+
+ reg [7:0] data_storage_dina_reg;
+ reg [13:0] data_storage_addra_reg;
+ reg data_storage_write_enable_reg;
+
+ data_storage data_storage(.clka(data_storage_clka), .dina(data_storage_dina), .addra(data_storage_addra),
+ .wea(data_storage_write_enable), .douta(data_storage_data_out));
+
+ assign data_storage_clka = (data_storage_remote_enable) ? main_fifty_clock : sram_clock_in;
+ assign data_storage_dina = (data_storage_remote_enable) ? data_storage_dina_reg : sram_data_in;
+ assign data_storage_addra = (data_storage_remote_enable) ? data_storage_addra_reg : sram_address_in;
+ assign data_storage_write_enable = (data_storage_remote_enable) ? data_storage_write_enable_reg : sram_wren_in;
+
+ assign sram_data_out = data_storage_data_out;
+
+ // -----------------------------------------------------------------------------------------------
+ //
+ // Here is the serial receiver and transmitter
+ //
+ // -----------------------------------------------------------------------------------------------
+
+ reg [7:0] transmit_all_data_state = 0;
+
+ wire RxD_data_ready;
+ wire [7:0] RxD_data;
+ wire RxD_endofpacket;
+ wire RxD_idle;
+
+ reg TxD_start;
+ reg [7:0] TxD_data;
+ wire TxD_busy;
+ wire [4:0] state;
+
+ reg [7:0] transmitter_4_bit_state = 0;
+ reg [7:0] transmitter_8_bit_state = 0;
+ reg [15:0] transmitter_16_bit_state = 0;
+ reg [7:0] transmitter_main_state = 0;
+ reg [7:0] transmitter_input_state = 0;
+
+ async_transmit asyncTX(.clk(clk_div_by_two), .TxD_start(TxD_start), .TxD_data(TxD_data), .TxD(serial_port_transmitter), .TxD_busy(TxD_busy), .state(state));
+ async_receiver asyncRX(.clk(clk_div_by_two), .RxD(serial_port_receiver), .RxD_data_ready(RxD_data_ready), .RxD_data(RxD_data), .RxD_endofpacket(RxD_endofpacket), .RxD_idle(RxD_idle));
+
+ reg tx_toggle = 0;
+
+ reg transmit_4_bit_status = 0;
+ reg transmit_4_bit_status_done = 0;
+
+ reg transmit_8_bit_status = 0;
+ reg transmit_8_bit_status_done = 0;
+
+ reg transmit_16_bit_status = 0;
+ reg transmit_16_bit_pass_two = 0;
+ reg transmit_16_bit_status_done = 0;
+
+ reg transmit_main_status = 0;
+ reg transmit_main_status_done = 0;
+
+ reg transmit_input_status = 0;
+ reg transmit_input_status_done = 0;
+
+ reg transmit_lcd_status = 0;
+ reg transmit_lcd_status_done = 0;
+ reg [7:0] transmit_lcd_status_counter = 0;
+
+ reg enable_remote_access_input = 1;
+ reg remote_access_input_enable_prev = 0;
+ reg prev_was_carriage_return = 0;
+
+ reg [7:0] lcd_display_string [31:0];
+
+ reg transmit_dsp_status = 0;
+ reg transmit_dsp_status_done = 0;
+ reg transmit_dsp_status_holdoff = 0;
+ reg [15:0] transmit_dsp_status_counter = 0;
+
+ reg transmit_led_status = 0;
+ reg transmit_led_status_done = 0;
+ reg [7:0] transmit_led_status_counter = 0;
+
+ // Transmit!
+ always @(posedge clk_div_by_two) begin
+ transmitter_4_bit_state = remote_access_4_bit_output;
+ transmitter_8_bit_state = remote_access_8_bit_output;
+ transmitter_16_bit_state = remote_access_16_bit_output;
+
+ transmitter_main_state = 0;
+ transmitter_main_state[0] = enable_remote_access_input;
+
+ transmitter_input_state = local_input;
+
+ if (seize_serial_tx == 1) begin
+ TxD_start = serial_tx_strobe;
+ TxD_data = serial_tx_data;
+ end else begin
+ if (tx_toggle == 0) begin
+ if ((transmit_4_bit_status == 1) && (transmit_4_bit_status_done == 0)) begin
+ TxD_data = transmitter_4_bit_state;
+
+ TxD_start = 1;
+ tx_toggle = 1;
+
+ transmit_4_bit_status_done = 1;
+ end
+
+ if ((transmit_8_bit_status == 1) && (transmit_8_bit_status_done == 0)) begin
+ TxD_data = transmitter_8_bit_state;
+
+ TxD_start = 1;
+ tx_toggle = 1;
+
+ transmit_8_bit_status_done = 1;
+ end
+
+ if ((transmit_16_bit_status == 1) && (transmit_16_bit_status_done == 0)) begin
+ if (transmit_16_bit_pass_two == 0) begin
+ TxD_data = transmitter_16_bit_state[15:8];
+
+ TxD_start = 1;
+ tx_toggle = 1;
+
+ transmit_16_bit_pass_two = 1;
+ end else begin
+ TxD_data = transmitter_16_bit_state[7:0];
+
+ TxD_start = 1;
+ tx_toggle = 1;
+
+ transmit_16_bit_status_done = 1;
+ end
+ end
+
+ if ((transmit_main_status == 1) && (transmit_main_status_done == 0)) begin
+ TxD_data = transmitter_main_state;
+
+ TxD_start = 1;
+ tx_toggle = 1;
+
+ transmit_main_status_done = 1;
+ end
+
+ if ((transmit_input_status == 1) && (transmit_input_status_done == 0)) begin
+ TxD_data = transmitter_input_state;
+
+ TxD_start = 1;
+ tx_toggle = 1;
+
+ transmit_input_status_done = 1;
+ end
+
+ if ((transmit_lcd_status == 1) && (transmit_lcd_status_done == 0)) begin
+ TxD_data = lcd_display_string[transmit_lcd_status_counter];
+
+ TxD_start = 1;
+ tx_toggle = 1;
+
+ transmit_lcd_status_counter = transmit_lcd_status_counter + 1;
+ if (transmit_lcd_status_counter > 31) begin
+ transmit_lcd_status_done = 1;
+ end
+ end
+
+ if ((transmit_led_status == 1) && (transmit_led_status_done == 0)) begin
+ TxD_data = led_display_bytes[transmit_led_status_counter];
+
+ TxD_start = 1;
+ tx_toggle = 1;
+
+ transmit_led_status_counter = transmit_led_status_counter + 1;
+ if (transmit_led_status_counter > 3) begin
+ transmit_led_status_done = 1;
+ end
+ end
+
+ if ((transmit_dsp_status == 1) && (transmit_dsp_status_done == 0)) begin
+ if (transmit_dsp_status_holdoff == 0) begin
+ transmit_dsp_status_holdoff = 1;
+ data_storage_write_enable_reg = 0;
+ data_storage_addra_reg = 0; // Initial data value
+ end else begin
+ data_storage_write_enable_reg = 0;
+ TxD_data = data_storage_data_out;
+
+ TxD_start = 1;
+ tx_toggle = 1;
+
+ transmit_dsp_status_counter = transmit_dsp_status_counter + 1;
+ data_storage_addra_reg = transmit_dsp_status_counter;
+ if (transmit_dsp_status_counter > 16384) begin
+ transmit_dsp_status_done = 1;
+ data_storage_write_enable_reg = 1'bz;
+ data_storage_addra_reg = 14'bz;
+ end
+ end
+ end
+ end else begin
+ if (state == 5'b10000) begin // Wait for transmission of byte to complete
+ TxD_start = 0;
+ tx_toggle = 0;
+ end
+ end
+ end
+
+ if (transmit_4_bit_status == 0) begin
+ transmit_4_bit_status_done = 0;
+ end
+
+ if (transmit_8_bit_status == 0) begin
+ transmit_8_bit_status_done = 0;
+ end
+
+ if (transmit_16_bit_status == 0) begin
+ transmit_16_bit_pass_two = 0;
+ transmit_16_bit_status_done = 0;
+ end
+
+ if (transmit_main_status == 0) begin
+ transmit_main_status_done = 0;
+ end
+
+ if (transmit_input_status == 0) begin
+ transmit_input_status_done = 0;
+ end
+
+ if (transmit_lcd_status == 0) begin
+ transmit_lcd_status_done = 0;
+ transmit_lcd_status_counter = 0;
+ end
+
+ if (transmit_led_status == 0) begin
+ transmit_led_status_done = 0;
+ transmit_led_status_counter = 0;
+ end
+
+ if (transmit_dsp_status == 0) begin
+ transmit_dsp_status_done = 0;
+ transmit_dsp_status_holdoff = 0;
+ transmit_dsp_status_counter = 0;
+ end
+ end
+
+ reg [7:0] lcd_display_initialization_state = 0;
+ reg serial_character_received = 0;
+ reg [7:0] serial_receiver_toggler = 0;
+ reg [7:0] serial_command_buffer = 0;
+ reg [2:0] next_byte_is_command = 0;
+ reg [7:0] next_byte_is_command_prev_command = 0;
+ reg [7:0] serial_command_timer = 0;
+ reg update_lcd_display = 0;
+ reg [7:0] serial_update_counter = 0;
+ reg [15:0] dsp_update_counter = 0;
+ reg [7:0] received_lcd_display_string [31:0];
+ reg data_write_timer = 0;
+ reg waiting_on_dsp_processing = 0;
+
+ // Receive serial commands
+ always @(posedge clk_div_by_two) begin
+ if (startup_needed == 1) begin
+ startup_needed = 0;
+ transmit_dsp_status = 1;
+ end
+
+ if (lcd_data_in_enable == 1) begin
+ received_lcd_display_string[lcd_data_in_address] = lcd_data_in_data;
+ update_lcd_display = 1;
+ serial_command_timer = 255;
+ end
+
+ if ((remote_access_input_enable == 1) && (remote_access_input_enable_prev == 0)) begin
+ enable_remote_access_input = !enable_remote_access_input;
+ end
+ remote_access_input_enable_prev = remote_access_input_enable;
+
+ if (enable_remote_access_input == 0) begin
+ // Enable local input
+ remote_access_8_bit_input_reg = local_input;
+ end
+
+ if (serial_command_timer > 0) begin
+ serial_command_timer = serial_command_timer - 1;
+ end else begin
+ update_lcd_display = 0;
+ end
+
+ if (transmit_4_bit_status_done == 1) begin
+ transmit_4_bit_status = 0;
+ if (transmit_all_data_state == 1) begin
+ transmit_8_bit_status = 1;
+ end
+ end
+
+ if (transmit_8_bit_status_done == 1) begin
+ transmit_8_bit_status = 0;
+ if (transmit_all_data_state == 1) begin
+ transmit_16_bit_status = 1;
+ end
+ end
+
+ if (transmit_16_bit_status_done == 1) begin
+ transmit_16_bit_status = 0;
+ if (transmit_all_data_state == 1) begin
+ transmit_led_status = 1;
+ end
+ end
+
+ if (transmit_led_status_done == 1) begin
+ transmit_led_status = 0;
+ if (transmit_all_data_state == 1) begin
+ transmit_all_data_state = 0;
+ end
+ end
+
+ if (transmit_main_status_done == 1) begin
+ transmit_main_status = 0;
+ if (transmit_all_data_state == 1) begin
+ transmit_4_bit_status = 1;
+ end
+ end
+
+ if (transmit_input_status_done == 1) begin
+ transmit_input_status = 0;
+ end
+
+ if (transmit_lcd_status_done == 1) begin
+ transmit_lcd_status = 0;
+ if (transmit_all_data_state == 1) begin
+ transmit_main_status = 1;
+ end
+ end
+
+ if (transmit_dsp_status_done == 1) begin
+ transmit_dsp_status = 0;
+ data_storage_remote_enable = 0;
+ end
+
+ if (transmit_dsp_status == 1) begin
+ data_storage_remote_enable = 1;
+ end
+
+ if (data_write_timer > 1) begin
+ data_write_timer = data_write_timer - 1;
+ end else begin
+ if (data_write_timer == 1) begin
+ data_storage_write_enable_reg = 0;
+ data_write_timer = 0;
+ end
+ end
+
+ if ((waiting_on_dsp_processing == 1) && (sram_processing_done == 1)) begin
+ waiting_on_dsp_processing = 0;
+ transmit_dsp_status = 1;
+ end
+
+ serial_rx_strobe_reg = 0; // Make sure that this get reset!
+
+ if ((sram_processing_done == 1) && (sram_available_reg == 1)) begin
+ sram_available_reg = 0;
+ transmit_dsp_status = 1;
+ end
+
+ if (RxD_data_ready == 1) begin
+ if (serial_character_received == 0) begin
+ serial_rx_data_reg = RxD_data;
+ serial_rx_strobe_reg = 1; // Signal new data...
+ if (seize_serial_tx == 0) begin
+ // Parse the command and see what it is
+ serial_character_received = 1;
+ if (RxD_data == 13) begin
+ // Carriage Return! The serial_command_buffer holds the command! Parse it!
+ if (next_byte_is_command == 0) begin
+ if (serial_command_buffer == 65) begin
+ // Display update requested
+ next_byte_is_command = 1;
+ serial_update_counter = 0;
+ next_byte_is_command_prev_command = 65;
+ end
+
+ if (serial_command_buffer == 66) begin
+ // 8 bit input update
+ if (enable_remote_access_input == 1) begin
+ next_byte_is_command = 1;
+ serial_update_counter = 0;
+ next_byte_is_command_prev_command = 66;
+ end
+ end
+
+ if (serial_command_buffer == 67) begin
+ // 16 bit input update
+ next_byte_is_command = 1;
+ serial_update_counter = 0;
+ next_byte_is_command_prev_command = 67;
+ end
+
+ if (serial_command_buffer == 68) begin
+ // 8 bit output status
+ transmit_8_bit_status = 1;
+ end
+
+ if (serial_command_buffer == 69) begin
+ // 16 bit output status
+ transmit_16_bit_status = 1;
+ end
+
+ if (serial_command_buffer == 70) begin
+ // System status
+ transmit_main_status = 1;
+ end
+
+ if (serial_command_buffer == 71) begin
+ // Simulate center button press
+ enable_remote_access_input = !enable_remote_access_input;
+ end
+
+ if (serial_command_buffer == 72) begin
+ // Local input status
+ transmit_input_status = 1;
+ end
+
+ if (serial_command_buffer == 73) begin
+ // 4 bit input update
+ if (enable_remote_access_input == 1) begin
+ next_byte_is_command = 1;
+ serial_update_counter = 0;
+ next_byte_is_command_prev_command = 73;
+ end
+ end
+
+ if (serial_command_buffer == 74) begin
+ // 4 bit output status
+ transmit_4_bit_status = 1;
+ end
+
+ if (serial_command_buffer == 75) begin
+ // Transmit the contents of the LCD...
+ transmit_lcd_status = 1;
+ end
+
+ if (serial_command_buffer == 76) begin
+ // Transmit the contents of the LCD...
+ transmit_all_data_state = 1;
+ transmit_lcd_status = 1;
+ end
+
+ if (serial_command_buffer == 77) begin
+ // Receive offline DSP data
+ next_byte_is_command = 1;
+ dsp_update_counter = 0;
+ next_byte_is_command_prev_command = 77;
+ end
+
+ if (serial_command_buffer == 78) begin
+ // Transmit the contents of RAM...
+ transmit_dsp_status = 1;
+ end
+ end else begin
+ if (next_byte_is_command == 1) begin
+ // The previous byte was the command--now load in the data!
+ if (next_byte_is_command_prev_command == 65) begin
+ if (serial_update_counter < 32) begin
+ received_lcd_display_string[serial_update_counter] = serial_command_buffer;
+ serial_update_counter = serial_update_counter + 1;
+ end else begin
+ update_lcd_display = 1;
+ serial_command_timer = 255;
+ next_byte_is_command = 0;
+ end
+ end
+
+ // 4 bit input update
+ if (next_byte_is_command_prev_command == 73) begin
+ remote_access_4_bit_input_reg = serial_command_buffer;
+ next_byte_is_command = 0;
+ end
+
+ // 8 bit input update
+ if (next_byte_is_command_prev_command == 66) begin
+ remote_access_8_bit_input_reg = serial_command_buffer;
+ next_byte_is_command = 0;
+ end
+
+ // 16 bit input update
+ if (next_byte_is_command_prev_command == 67) begin
+ if (serial_update_counter == 0) begin
+ remote_access_16_bit_input_reg[15:8] = serial_command_buffer;
+ serial_update_counter = 1;
+ end else begin
+ remote_access_16_bit_input_reg[7:0] = serial_command_buffer;
+ next_byte_is_command = 0;
+ end
+ end
+
+ // DSP input data
+ if (next_byte_is_command_prev_command == 77) begin
+ if (dsp_update_counter < 16384) begin
+ data_storage_remote_enable = 1;
+ data_storage_addra_reg = dsp_update_counter;
+ data_storage_dina_reg = serial_command_buffer;
+ data_storage_write_enable_reg = 1;
+ data_write_timer = 3;
+ dsp_update_counter = dsp_update_counter + 1;
+
+ // TESTING ONLY!!!
+ //if (dsp_update_counter < 17) begin
+ // received_lcd_display_string[dsp_update_counter - 1] = serial_command_buffer;
+ //end
+ end else begin
+ next_byte_is_command = 0;
+ data_storage_write_enable_reg = 0;
+ data_storage_remote_enable = 0;
+ sram_available_reg = 1;
+ data_storage_write_enable_reg = 1'bz;
+ data_storage_addra_reg = 14'bz;
+ waiting_on_dsp_processing = 1;
+
+ // TESTING ONLY!!!
+ //transmit_dsp_status = 1;
+ end
+ end
+ end
+ end
+ end
+ end
+
+ //if (RxD_data != 10) begin // Ignore linefeeds
+ serial_command_buffer = RxD_data;
+ //end
+
+ if (RxD_data == 13) begin
+ prev_was_carriage_return = 1;
+ end else begin
+ prev_was_carriage_return = 0;
+ end
+
+ serial_receiver_toggler = serial_receiver_toggler + 1;
+ end
+ end
+
+ if (RxD_data_ready == 0) begin
+ serial_character_received = 0;
+ end
+ end
+
+ //-----------------------------------------------------------------------------------
+ //
+ // This routine will display the contents of lcd_display_string on the LCD display
+ //
+ //-----------------------------------------------------------------------------------
+
+ reg [15:0] lcd_display_wait_counter = 0;
+ reg [7:0] lcd_display_current_character = 0;
+ reg lcd_display_line_two = 0; // Are we trying to write to line two?
+
+ always @(posedge four_mhz_clk) begin
+ case (lcd_display_initialization_state)
+ // Initialize the display according to the reference manual
+ 0:begin
+ // Set up the default display...
+ lcd_display_string[0] = 73; // I
+ lcd_display_string[1] = 110; // n
+ lcd_display_string[2] = 105; // i
+ lcd_display_string[3] = 116; // t
+ lcd_display_string[4] = 105; // i
+ lcd_display_string[5] = 97; // a
+ lcd_display_string[6] = 108; // l
+ lcd_display_string[7] = 105; // i
+ lcd_display_string[8] = 122; // z
+ lcd_display_string[9] = 97; // a
+ lcd_display_string[10] = 116; // t
+ lcd_display_string[11] = 105; // i
+ lcd_display_string[12] = 111; // o
+ lcd_display_string[13] = 110; // n
+ lcd_display_string[14] = 32; // <blank>
+ lcd_display_string[15] = 32; // <blank>
+ lcd_display_string[16] = 79; // O
+ lcd_display_string[17] = 75; // k
+ lcd_display_string[18] = 32; // <blank>
+ lcd_display_string[19] = 32; // <blank>
+ lcd_display_string[20] = 32; // <blank>
+ lcd_display_string[21] = 32; // <blank>
+ lcd_display_string[22] = 32; // <blank>
+ lcd_display_string[23] = 32; // <blank>
+ lcd_display_string[24] = 32; // <blank>
+ lcd_display_string[25] = 32; // <blank>
+ lcd_display_string[26] = 32; // <blank>
+ lcd_display_string[27] = 32; // <blank>
+ lcd_display_string[28] = 32; // <blank>
+ lcd_display_string[29] = 32; // <blank>
+ lcd_display_string[30] = 32; // <blank>
+ lcd_display_string[31] = 32; // <blank>
+
+ lcd_display_current_character = 0;
+
+ lcd_display_line_two = 0;
+ remote_access_lcd_data_out_reg = 3;
+ remote_access_lcd_enable_out_reg = 1;
+ remote_access_lcd_rs_out_reg = 0;
+ remote_access_lcd_rw_out_reg = 0;
+ lcd_display_wait_counter = 17083; // Wait 15mS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 1:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 2:begin
+ remote_access_lcd_data_out_reg = 3;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 417; // Wait 100uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 3:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 4:begin
+ remote_access_lcd_data_out_reg = 3;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 167; // Wait 40uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 5:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 6:begin
+ remote_access_lcd_data_out_reg = 2;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 167; // Wait 40uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 7:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ // Display is now initialized
+
+ // Send Function Set command
+ 8:begin
+ remote_access_lcd_data_out_reg = 2;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 5; // Wait 1uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 9:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 10:begin
+ remote_access_lcd_data_out_reg = 8;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 167; // Wait 40uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 11:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+
+ // Send Entry Mode Set command
+ 12:begin
+ remote_access_lcd_data_out_reg = 0;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 5; // Wait 1uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 13:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 14:begin
+ remote_access_lcd_data_out_reg = 6;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 167; // Wait 40uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 15:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+
+ // Send Display On command and disable cursors and blinking
+ 16:begin
+ remote_access_lcd_data_out_reg = 0;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 5; // Wait 1uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 17:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 18:begin
+ remote_access_lcd_data_out_reg = 12;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 167; // Wait 40uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 19:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+
+ // Send Clear Display command
+ 20:begin
+ remote_access_lcd_data_out_reg = 0;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 5; // Wait 1uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 21:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 22:begin
+ remote_access_lcd_data_out_reg = 1;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 6833; // Wait 1.64uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 23:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+
+ // Set DD RAM Address to 0 if lcd_display_line_two is 0, or 0x40 if it is 1
+ 24:begin
+ remote_access_lcd_rs_out_reg = 0;
+ if (lcd_display_line_two == 0) begin
+ remote_access_lcd_data_out_reg = 8;
+ end
+ if (lcd_display_line_two == 1) begin
+ remote_access_lcd_data_out_reg = 12;
+ end
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 5; // Wait 1uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 25:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 26:begin
+ remote_access_lcd_data_out_reg = 0;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 167; // Wait 40uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 27:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+
+ // Display the characters
+ 28:begin
+ remote_access_lcd_data_out_reg = lcd_display_string[lcd_display_current_character][7:4];
+ remote_access_lcd_rs_out_reg = 1;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 5; // Wait 1uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 29:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 30:begin
+ remote_access_lcd_data_out_reg = lcd_display_string[lcd_display_current_character][3:0];
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 167; // Wait 40uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 31:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 32:begin
+ lcd_display_current_character = lcd_display_current_character + 1;
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ if (lcd_display_current_character < 32) begin
+ lcd_display_initialization_state = 28;
+ end
+ if (lcd_display_current_character == 16) begin
+ if (lcd_display_line_two == 0) begin
+ lcd_display_line_two = 1;
+ lcd_display_initialization_state = 24;
+ end
+ end
+ end
+ 33:begin
+ // End!
+ remote_access_lcd_rs_out_reg = 0;
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_line_two = 0;
+ lcd_display_current_character = 0;
+ if (update_lcd_display == 1) begin
+ lcd_display_line_two = 0;
+ lcd_display_current_character = 0;
+ lcd_display_initialization_state = 24;
+ lcd_display_string[0] = received_lcd_display_string[0];
+ lcd_display_string[1] = received_lcd_display_string[1];
+ lcd_display_string[2] = received_lcd_display_string[2];
+ lcd_display_string[3] = received_lcd_display_string[3];
+ lcd_display_string[4] = received_lcd_display_string[4];
+ lcd_display_string[5] = received_lcd_display_string[5];
+ lcd_display_string[6] = received_lcd_display_string[6];
+ lcd_display_string[7] = received_lcd_display_string[7];
+ lcd_display_string[8] = received_lcd_display_string[8];
+ lcd_display_string[9] = received_lcd_display_string[9];
+ lcd_display_string[10] = received_lcd_display_string[10];
+ lcd_display_string[11] = received_lcd_display_string[11];
+ lcd_display_string[12] = received_lcd_display_string[12];
+ lcd_display_string[13] = received_lcd_display_string[13];
+ lcd_display_string[14] = received_lcd_display_string[14];
+ lcd_display_string[15] = received_lcd_display_string[15];
+ lcd_display_string[16] = received_lcd_display_string[16];
+ lcd_display_string[17] = received_lcd_display_string[17];
+ lcd_display_string[18] = received_lcd_display_string[18];
+ lcd_display_string[19] = received_lcd_display_string[19];
+ lcd_display_string[20] = received_lcd_display_string[20];
+ lcd_display_string[21] = received_lcd_display_string[21];
+ lcd_display_string[22] = received_lcd_display_string[22];
+ lcd_display_string[23] = received_lcd_display_string[23];
+ lcd_display_string[24] = received_lcd_display_string[24];
+ lcd_display_string[25] = received_lcd_display_string[25];
+ lcd_display_string[26] = received_lcd_display_string[26];
+ lcd_display_string[27] = received_lcd_display_string[27];
+ lcd_display_string[28] = received_lcd_display_string[28];
+ lcd_display_string[29] = received_lcd_display_string[29];
+ lcd_display_string[30] = received_lcd_display_string[30];
+ lcd_display_string[31] = received_lcd_display_string[31];
+ end
+ end
+ endcase
+ end
+endmodule
+
+module async_receiver(clk, RxD, RxD_data_ready, RxD_data, RxD_endofpacket, RxD_idle);
+ input clk, RxD;
+ output RxD_data_ready; // onc clock pulse when RxD_data is valid
+ output [7:0] RxD_data;
+
+ parameter ClkFrequency = 25000000; // 25MHz
+ parameter Baud = 115200;
+
+ // We also detect if a gap occurs in the received stream of characters
+ // That can be useful if multiple characters are sent in burst
+ // so that multiple characters can be treated as a "packet"
+ output RxD_endofpacket; // one clock pulse, when no more data is received (RxD_idle is going high)
+ output RxD_idle; // no data is being received
+
+ // Baud generator (we use 8 times oversampling)
+ parameter Baud8 = Baud*8;
+ parameter Baud8GeneratorAccWidth = 16;
+ wire [Baud8GeneratorAccWidth:0] Baud8GeneratorInc = ((Baud8<<(Baud8GeneratorAccWidth-7))+(ClkFrequency>>8))/(ClkFrequency>>7);
+ reg [Baud8GeneratorAccWidth:0] Baud8GeneratorAcc;
+ always @(posedge clk) Baud8GeneratorAcc <= Baud8GeneratorAcc[Baud8GeneratorAccWidth-1:0] + Baud8GeneratorInc;
+ wire Baud8Tick = Baud8GeneratorAcc[Baud8GeneratorAccWidth];
+
+ ////////////////////////////
+ reg [1:0] RxD_sync_inv;
+ always @(posedge clk) if(Baud8Tick) RxD_sync_inv <= {RxD_sync_inv[0], ~RxD};
+ // we invert RxD, so that the idle becomes "0", to prevent a phantom character to be received at startup
+
+ reg [1:0] RxD_cnt_inv;
+ reg RxD_bit_inv;
+
+ always @(posedge clk)
+ if(Baud8Tick)
+ begin
+ if( RxD_sync_inv[1] && RxD_cnt_inv!=2'b11) RxD_cnt_inv <= RxD_cnt_inv + 2'h1;
+ else
+ if(~RxD_sync_inv[1] && RxD_cnt_inv!=2'b00) RxD_cnt_inv <= RxD_cnt_inv - 2'h1;
+
+ if(RxD_cnt_inv==2'b00) RxD_bit_inv <= 1'b0;
+ else
+ if(RxD_cnt_inv==2'b11) RxD_bit_inv <= 1'b1;
+ end
+
+ reg [3:0] state;
+ reg [3:0] bit_spacing;
+
+ // "next_bit" controls when the data sampling occurs
+ // depending on how noisy the RxD is, different values might work better
+ // with a clean connection, values from 8 to 11 work
+ wire next_bit = (bit_spacing==4'd10);
+
+ always @(posedge clk)
+ if(state==0)
+ bit_spacing <= 4'b0000;
+ else
+ if(Baud8Tick)
+ bit_spacing <= {bit_spacing[2:0] + 4'b0001} | {bit_spacing[3], 3'b000};
+
+ always @(posedge clk)
+ if(Baud8Tick)
+ case(state)
+ 4'b0000: if(RxD_bit_inv) state <= 4'b1000; // start bit found?
+ 4'b1000: if(next_bit) state <= 4'b1001; // bit 0
+ 4'b1001: if(next_bit) state <= 4'b1010; // bit 1
+ 4'b1010: if(next_bit) state <= 4'b1011; // bit 2
+ 4'b1011: if(next_bit) state <= 4'b1100; // bit 3
+ 4'b1100: if(next_bit) state <= 4'b1101; // bit 4
+ 4'b1101: if(next_bit) state <= 4'b1110; // bit 5
+ 4'b1110: if(next_bit) state <= 4'b1111; // bit 6
+ 4'b1111: if(next_bit) state <= 4'b0001; // bit 7
+ 4'b0001: if(next_bit) state <= 4'b0000; // stop bit
+ default: state <= 4'b0000;
+ endcase
+
+ reg [7:0] RxD_data;
+ always @(posedge clk)
+ if(Baud8Tick && next_bit && state[3]) RxD_data <= {~RxD_bit_inv, RxD_data[7:1]};
+
+ reg RxD_data_ready;
+ always @(posedge clk)
+ begin
+ RxD_data_ready <= (Baud8Tick && next_bit && state==4'b0001 && ~RxD_bit_inv); // ready only if the stop bit is received
+ end
+
+ reg [4:0] gap_count;
+ always @(posedge clk) if (state!=0) gap_count<=5'h00; else if(Baud8Tick & ~gap_count[4]) gap_count <= gap_count + 5'h01;
+ assign RxD_idle = gap_count[4];
+ reg RxD_endofpacket; always @(posedge clk) RxD_endofpacket <= Baud8Tick & (gap_count==5'h0F);
+endmodule
+
+module async_transmit(clk, TxD_start, TxD_data, TxD, TxD_busy, state);
+ input clk, TxD_start;
+ input [7:0] TxD_data;
+ output TxD, TxD_busy;
+ output [4:0] state;
+ parameter ClkFrequency = 25000000; // 25MHz
+ //parameter ClkFrequency = 50000000; // 50MHz
+ parameter Baud = 115200;
+ parameter RegisterInputData = 1; // in RegisterInputData mode, the input doesn't have to stay valid while the character is been transmitted
+
+ // Baud generator
+ parameter BaudGeneratorAccWidth = 16;
+ reg [BaudGeneratorAccWidth:0] BaudGeneratorAcc;
+ `ifdef DEBUG
+ wire [BaudGeneratorAccWidth:0] BaudGeneratorInc = 17'h10000;
+ `else
+ wire [BaudGeneratorAccWidth:0] BaudGeneratorInc = ((Baud<<(BaudGeneratorAccWidth-4))+(ClkFrequency>>5))/(ClkFrequency>>4);
+ `endif
+
+ wire BaudTick = BaudGeneratorAcc[BaudGeneratorAccWidth];
+ wire TxD_busy;
+ always @(posedge clk) if(TxD_busy) BaudGeneratorAcc <= BaudGeneratorAcc[BaudGeneratorAccWidth-1:0] + BaudGeneratorInc;
+
+ // Transmitter state machine
+ reg [4:0] state;
+ wire TxD_ready = (state==0);
+ assign TxD_busy = ~TxD_ready;
+
+ reg [7:0] TxD_dataReg;
+ always @(posedge clk) if(TxD_ready & TxD_start) TxD_dataReg <= TxD_data;
+ wire [7:0] TxD_dataD = RegisterInputData ? TxD_dataReg : TxD_data;
+
+ always @(posedge clk) begin
+ if (TxD_start == 0) state <= 5'b00000;
+
+ case(state)
+ 5'b00000: if(TxD_start) state <= 5'b00001;
+ 5'b00001: if(BaudTick) state <= 5'b00100;
+ 5'b00100: if(BaudTick) state <= 5'b01000; // start
+ 5'b01000: if(BaudTick) state <= 5'b01001; // bit 0
+ 5'b01001: if(BaudTick) state <= 5'b01010; // bit 1
+ 5'b01010: if(BaudTick) state <= 5'b01011; // bit 2
+ 5'b01011: if(BaudTick) state <= 5'b01100; // bit 3
+ 5'b01100: if(BaudTick) state <= 5'b01101; // bit 4
+ 5'b01101: if(BaudTick) state <= 5'b01110; // bit 5
+ 5'b01110: if(BaudTick) state <= 5'b01111; // bit 6
+ 5'b01111: if(BaudTick) state <= 5'b00010; // bit 7
+ 5'b00010: if(BaudTick) state <= 5'b00011; // stop1
+ //4'b0011: if(BaudTick) state <= 4'b0000; // stop2
+ 5'b00011: if(BaudTick) state <= 5'b10000; // stop2
+ //default: if(BaudTick) state <= 4'b0000;
+ endcase
+ end
+
+ // Output mux
+ reg muxbit;
+ always @( * )
+ case(state[2:0])
+ 3'd0: muxbit <= TxD_dataD[0];
+ 3'd1: muxbit <= TxD_dataD[1];
+ 3'd2: muxbit <= TxD_dataD[2];
+ 3'd3: muxbit <= TxD_dataD[3];
+ 3'd4: muxbit <= TxD_dataD[4];
+ 3'd5: muxbit <= TxD_dataD[5];
+ 3'd6: muxbit <= TxD_dataD[6];
+ 3'd7: muxbit <= TxD_dataD[7];
+ endcase
+
+ // Put together the start, data and stop bits
+ reg TxD;
+ always @(posedge clk) TxD <= (state<4) | (state[3] & muxbit) | state[4]; // register the output to make it glitch free
+
+endmodule
diff --git a/fpga/xilinx/digilent/spartan_3e/remote_access.v b/fpga/xilinx/digilent/spartan_3e/remote_access.v
new file mode 100644
index 0000000..154478e
--- /dev/null
+++ b/fpga/xilinx/digilent/spartan_3e/remote_access.v
@@ -0,0 +1,1184 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company: Pearson Computing
+// Engineer: Timothy Pearson
+//
+// Create Date: 11:58:21 07/07/2007
+// Design Name: Remote Access Driver
+// Module Name: remote_access
+// Project Name: Remote Access Driver
+// Target Devices: Digilent Spartan 3E Development Board
+// Tool versions: Xilinx ISE v9.1 SP3
+// Description: Serial remote access driver and LCD display driver
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments: Released into the Public Domain
+//
+//////////////////////////////////////////////////////////////////////////////////
+module remote_access(
+ input main_fifty_clock, // 50MHz clock in
+ input [3:0] remote_access_4_bit_output, // 4 bit output from the user program to remote access client
+ output [3:0] remote_access_4_bit_input, // 4 bit input from the remote access client to user program
+ input [7:0] remote_access_8_bit_output, // 8 bit output from the user program to remote access client
+ output [7:0] remote_access_8_bit_input, // 8 bit input from the remote access client to user program
+ input [15:0] remote_access_16_bit_output, // 16 bit output from the user program to the remote access client
+ output [15:0] remote_access_16_bit_input, // 16 bit input from the remote access client to the user program
+ output [3:0] remote_access_lcd_data_out,
+ output remote_access_lcd_rs_out,
+ output remote_access_lcd_rw_out,
+ output remote_access_lcd_enable_out,
+ input serial_port_receiver,
+ output serial_port_transmitter,
+ input remote_access_input_enable,
+ input [7:0] local_input,
+ input seize_serial_tx,
+ input [7:0] serial_tx_data,
+ input serial_tx_strobe,
+ output [7:0] serial_rx_data,
+ output serial_rx_strobe,
+ input [5:0] lcd_data_in_address,
+ input [7:0] lcd_data_in_data,
+ input lcd_data_in_enable,
+ input sram_wren_in,
+ input sram_clock_in,
+ input [7:0] sram_data_in,
+ input [13:0] sram_address_in,
+ output [7:0] sram_data_out,
+ output sram_available,
+ input sram_processing_done,
+ input [7:0] led_segment_bus,
+ input [3:0] led_digit_select);
+
+ reg [7:0] remote_access_4_bit_input_reg;
+ reg [7:0] remote_access_8_bit_input_reg;
+ reg [15:0] remote_access_16_bit_input_reg;
+ reg [3:0] remote_access_lcd_data_out_reg;
+ reg remote_access_lcd_rs_out_reg;
+ reg remote_access_lcd_rw_out_reg;
+ reg remote_access_lcd_enable_out_reg;
+ reg [7:0] serial_rx_data_reg;
+ reg serial_rx_strobe_reg;
+ reg sram_available_reg;
+ reg startup_needed = 1;
+
+ assign remote_access_4_bit_input = remote_access_4_bit_input_reg;
+ assign remote_access_8_bit_input = remote_access_8_bit_input_reg;
+ assign remote_access_16_bit_input = remote_access_16_bit_input_reg;
+ assign remote_access_lcd_data_out = remote_access_lcd_data_out_reg;
+ assign remote_access_lcd_rs_out = remote_access_lcd_rs_out_reg;
+ assign remote_access_lcd_rw_out = remote_access_lcd_rw_out_reg;
+ assign remote_access_lcd_enable_out = remote_access_lcd_enable_out_reg;
+ assign serial_rx_data = serial_rx_data_reg;
+ assign serial_rx_strobe = serial_rx_strobe_reg;
+ assign sram_available = sram_available_reg;
+
+ //-----------------------------------------------------------------------------------
+ //
+ // Create a 4.16MHz clock for the LCD display driver and a 25MHz clock
+ // for the serial receiver.
+ //
+ //-----------------------------------------------------------------------------------
+
+ reg four_mhz_clk;
+ reg clk_div_by_two;
+ reg clk_div_by_four;
+ reg clk_div_by_eight;
+ reg [3:0] fifty_clock_divider = 0;
+
+ always @(posedge main_fifty_clock) begin
+ fifty_clock_divider = fifty_clock_divider + 1;
+ if (fifty_clock_divider > 12) begin
+ four_mhz_clk = !four_mhz_clk;
+ fifty_clock_divider = 0;
+ end
+ end
+
+ always @(posedge main_fifty_clock) begin
+ clk_div_by_two = !clk_div_by_two;
+ end
+
+ always @(posedge clk_div_by_two) begin
+ clk_div_by_four = !clk_div_by_four;
+ end
+
+ always @(posedge clk_div_by_four) begin
+ clk_div_by_eight = !clk_div_by_eight;
+ end
+
+ //-----------------------------------------------------------------------------------
+ //
+ // Keep track of what is on the LED display
+ //
+ //-----------------------------------------------------------------------------------
+
+ reg [7:0] led_display_bytes [3:0];
+ reg [4:0] digit_blanker_1 = 0;
+ reg [4:0] digit_blanker_2 = 0;
+ reg [4:0] digit_blanker_3 = 0;
+ reg [4:0] digit_blanker_4 = 0;
+
+ always @(negedge clk_div_by_eight) begin
+ if (led_digit_select[0] == 0) begin
+ led_display_bytes[0] = led_segment_bus;
+ digit_blanker_1 = 0;
+ end
+
+ if (led_digit_select[1] == 0) begin
+ led_display_bytes[1] = led_segment_bus;
+ digit_blanker_2 = 0;
+ end
+
+ if (led_digit_select[2] == 0) begin
+ led_display_bytes[2] = led_segment_bus;
+ digit_blanker_3 = 0;
+ end
+
+ if (led_digit_select[3] == 0) begin
+ led_display_bytes[3] = led_segment_bus;
+ digit_blanker_4 = 0;
+ end
+
+ if (digit_blanker_1 > 30) begin
+ led_display_bytes[0] = 255;
+ end
+
+ if (digit_blanker_2 > 30) begin
+ led_display_bytes[1] = 255;
+ end
+
+ if (digit_blanker_3 > 30) begin
+ led_display_bytes[2] = 255;
+ end
+
+ if (digit_blanker_4 > 30) begin
+ led_display_bytes[3] = 255;
+ end
+ end
+
+ //-----------------------------------------------------------------------------------
+ //
+ // Instantiate the data storage RAM for signal processing
+ //
+ //-----------------------------------------------------------------------------------
+
+ reg data_storage_remote_enable = 0;
+ wire data_storage_clka;
+ wire [7:0] data_storage_dina;
+ wire [13:0] data_storage_addra;
+ wire data_storage_write_enable;
+ wire [7:0] data_storage_data_out;
+
+ reg [7:0] data_storage_dina_reg;
+ reg [13:0] data_storage_addra_reg;
+ reg data_storage_write_enable_reg;
+
+ data_storage data_storage(.clka(data_storage_clka), .dina(data_storage_dina), .addra(data_storage_addra),
+ .wea(data_storage_write_enable), .douta(data_storage_data_out));
+
+ assign data_storage_clka = (data_storage_remote_enable) ? main_fifty_clock : sram_clock_in;
+ assign data_storage_dina = (data_storage_remote_enable) ? data_storage_dina_reg : sram_data_in;
+ assign data_storage_addra = (data_storage_remote_enable) ? data_storage_addra_reg : sram_address_in;
+ assign data_storage_write_enable = (data_storage_remote_enable) ? data_storage_write_enable_reg : sram_wren_in;
+
+ assign sram_data_out = data_storage_data_out;
+
+ // -----------------------------------------------------------------------------------------------
+ //
+ // Here is the serial receiver and transmitter
+ //
+ // -----------------------------------------------------------------------------------------------
+
+ reg [7:0] transmit_all_data_state = 0;
+
+ wire RxD_data_ready;
+ wire [7:0] RxD_data;
+ wire RxD_endofpacket;
+ wire RxD_idle;
+
+ reg TxD_start;
+ reg [7:0] TxD_data;
+ wire TxD_busy;
+ wire [4:0] state;
+
+ reg [7:0] transmitter_4_bit_state = 0;
+ reg [7:0] transmitter_8_bit_state = 0;
+ reg [15:0] transmitter_16_bit_state = 0;
+ reg [7:0] transmitter_main_state = 0;
+ reg [7:0] transmitter_input_state = 0;
+
+ async_transmit asyncTX(.clk(clk_div_by_two), .TxD_start(TxD_start), .TxD_data(TxD_data), .TxD(serial_port_transmitter), .TxD_busy(TxD_busy), .state(state));
+ async_receiver asyncRX(.clk(clk_div_by_two), .RxD(serial_port_receiver), .RxD_data_ready(RxD_data_ready), .RxD_data(RxD_data), .RxD_endofpacket(RxD_endofpacket), .RxD_idle(RxD_idle));
+
+ reg tx_toggle = 0;
+
+ reg transmit_4_bit_status = 0;
+ reg transmit_4_bit_status_done = 0;
+
+ reg transmit_8_bit_status = 0;
+ reg transmit_8_bit_status_done = 0;
+
+ reg transmit_16_bit_status = 0;
+ reg transmit_16_bit_pass_two = 0;
+ reg transmit_16_bit_status_done = 0;
+
+ reg transmit_main_status = 0;
+ reg transmit_main_status_done = 0;
+
+ reg transmit_input_status = 0;
+ reg transmit_input_status_done = 0;
+
+ reg transmit_lcd_status = 0;
+ reg transmit_lcd_status_done = 0;
+ reg [7:0] transmit_lcd_status_counter = 0;
+
+ reg enable_remote_access_input = 1;
+ reg remote_access_input_enable_prev = 0;
+ reg prev_was_carriage_return = 0;
+
+ reg [7:0] lcd_display_string [31:0];
+
+ reg transmit_dsp_status = 0;
+ reg transmit_dsp_status_done = 0;
+ reg transmit_dsp_status_holdoff = 0;
+ reg [15:0] transmit_dsp_status_counter = 0;
+
+ reg transmit_led_status = 0;
+ reg transmit_led_status_done = 0;
+ reg [7:0] transmit_led_status_counter = 0;
+
+ // Transmit!
+ always @(posedge clk_div_by_two) begin
+ transmitter_4_bit_state = remote_access_4_bit_output;
+ transmitter_8_bit_state = remote_access_8_bit_output;
+ transmitter_16_bit_state = remote_access_16_bit_output;
+
+ transmitter_main_state = 0;
+ transmitter_main_state[0] = enable_remote_access_input;
+
+ transmitter_input_state = local_input;
+
+ if (seize_serial_tx == 1) begin
+ TxD_start = serial_tx_strobe;
+ TxD_data = serial_tx_data;
+ end else begin
+ if (tx_toggle == 0) begin
+ if ((transmit_4_bit_status == 1) && (transmit_4_bit_status_done == 0)) begin
+ TxD_data = transmitter_4_bit_state;
+
+ TxD_start = 1;
+ tx_toggle = 1;
+
+ transmit_4_bit_status_done = 1;
+ end
+
+ if ((transmit_8_bit_status == 1) && (transmit_8_bit_status_done == 0)) begin
+ TxD_data = transmitter_8_bit_state;
+
+ TxD_start = 1;
+ tx_toggle = 1;
+
+ transmit_8_bit_status_done = 1;
+ end
+
+ if ((transmit_16_bit_status == 1) && (transmit_16_bit_status_done == 0)) begin
+ if (transmit_16_bit_pass_two == 0) begin
+ TxD_data = transmitter_16_bit_state[15:8];
+
+ TxD_start = 1;
+ tx_toggle = 1;
+
+ transmit_16_bit_pass_two = 1;
+ end else begin
+ TxD_data = transmitter_16_bit_state[7:0];
+
+ TxD_start = 1;
+ tx_toggle = 1;
+
+ transmit_16_bit_status_done = 1;
+ end
+ end
+
+ if ((transmit_main_status == 1) && (transmit_main_status_done == 0)) begin
+ TxD_data = transmitter_main_state;
+
+ TxD_start = 1;
+ tx_toggle = 1;
+
+ transmit_main_status_done = 1;
+ end
+
+ if ((transmit_input_status == 1) && (transmit_input_status_done == 0)) begin
+ TxD_data = transmitter_input_state;
+
+ TxD_start = 1;
+ tx_toggle = 1;
+
+ transmit_input_status_done = 1;
+ end
+
+ if ((transmit_lcd_status == 1) && (transmit_lcd_status_done == 0)) begin
+ TxD_data = lcd_display_string[transmit_lcd_status_counter];
+
+ TxD_start = 1;
+ tx_toggle = 1;
+
+ transmit_lcd_status_counter = transmit_lcd_status_counter + 1;
+ if (transmit_lcd_status_counter > 31) begin
+ transmit_lcd_status_done = 1;
+ end
+ end
+
+ if ((transmit_led_status == 1) && (transmit_led_status_done == 0)) begin
+ TxD_data = led_display_bytes[transmit_led_status_counter];
+
+ TxD_start = 1;
+ tx_toggle = 1;
+
+ transmit_led_status_counter = transmit_led_status_counter + 1;
+ if (transmit_led_status_counter > 3) begin
+ transmit_led_status_done = 1;
+ end
+ end
+
+ if ((transmit_dsp_status == 1) && (transmit_dsp_status_done == 0)) begin
+ if (transmit_dsp_status_holdoff == 0) begin
+ transmit_dsp_status_holdoff = 1;
+ data_storage_write_enable_reg = 0;
+ data_storage_addra_reg = 0; // Initial data value
+ end else begin
+ data_storage_write_enable_reg = 0;
+ TxD_data = data_storage_data_out;
+
+ TxD_start = 1;
+ tx_toggle = 1;
+
+ transmit_dsp_status_counter = transmit_dsp_status_counter + 1;
+ data_storage_addra_reg = transmit_dsp_status_counter;
+ if (transmit_dsp_status_counter > 16384) begin
+ transmit_dsp_status_done = 1;
+ data_storage_write_enable_reg = 1'bz;
+ data_storage_addra_reg = 14'bz;
+ end
+ end
+ end
+ end else begin
+ if (state == 5'b10000) begin // Wait for transmission of byte to complete
+ TxD_start = 0;
+ tx_toggle = 0;
+ end
+ end
+ end
+
+ if (transmit_4_bit_status == 0) begin
+ transmit_4_bit_status_done = 0;
+ end
+
+ if (transmit_8_bit_status == 0) begin
+ transmit_8_bit_status_done = 0;
+ end
+
+ if (transmit_16_bit_status == 0) begin
+ transmit_16_bit_pass_two = 0;
+ transmit_16_bit_status_done = 0;
+ end
+
+ if (transmit_main_status == 0) begin
+ transmit_main_status_done = 0;
+ end
+
+ if (transmit_input_status == 0) begin
+ transmit_input_status_done = 0;
+ end
+
+ if (transmit_lcd_status == 0) begin
+ transmit_lcd_status_done = 0;
+ transmit_lcd_status_counter = 0;
+ end
+
+ if (transmit_led_status == 0) begin
+ transmit_led_status_done = 0;
+ transmit_led_status_counter = 0;
+ end
+
+ if (transmit_dsp_status == 0) begin
+ transmit_dsp_status_done = 0;
+ transmit_dsp_status_holdoff = 0;
+ transmit_dsp_status_counter = 0;
+ end
+ end
+
+ reg [7:0] lcd_display_initialization_state = 0;
+ reg serial_character_received = 0;
+ reg [7:0] serial_receiver_toggler = 0;
+ reg [7:0] serial_command_buffer = 0;
+ reg [2:0] next_byte_is_command = 0;
+ reg [7:0] next_byte_is_command_prev_command = 0;
+ reg [7:0] serial_command_timer = 0;
+ reg update_lcd_display = 0;
+ reg [7:0] serial_update_counter = 0;
+ reg [15:0] dsp_update_counter = 0;
+ reg [7:0] received_lcd_display_string [31:0];
+ reg data_write_timer = 0;
+ reg waiting_on_dsp_processing = 0;
+
+ // Receive serial commands
+ always @(posedge clk_div_by_two) begin
+ if (startup_needed == 1) begin
+ startup_needed = 0;
+ transmit_dsp_status = 1;
+ end
+
+ if (lcd_data_in_enable == 1) begin
+ received_lcd_display_string[lcd_data_in_address] = lcd_data_in_data;
+ update_lcd_display = 1;
+ serial_command_timer = 255;
+ end
+
+ if ((remote_access_input_enable == 1) && (remote_access_input_enable_prev == 0)) begin
+ enable_remote_access_input = !enable_remote_access_input;
+ end
+ remote_access_input_enable_prev = remote_access_input_enable;
+
+ if (enable_remote_access_input == 0) begin
+ // Enable local input
+ remote_access_8_bit_input_reg = local_input;
+ end
+
+ if (serial_command_timer > 0) begin
+ serial_command_timer = serial_command_timer - 1;
+ end else begin
+ update_lcd_display = 0;
+ end
+
+ if (transmit_4_bit_status_done == 1) begin
+ transmit_4_bit_status = 0;
+ if (transmit_all_data_state == 1) begin
+ transmit_8_bit_status = 1;
+ end
+ end
+
+ if (transmit_8_bit_status_done == 1) begin
+ transmit_8_bit_status = 0;
+ if (transmit_all_data_state == 1) begin
+ transmit_16_bit_status = 1;
+ end
+ end
+
+ if (transmit_16_bit_status_done == 1) begin
+ transmit_16_bit_status = 0;
+ if (transmit_all_data_state == 1) begin
+ transmit_led_status = 1;
+ end
+ end
+
+ if (transmit_led_status_done == 1) begin
+ transmit_led_status = 0;
+ if (transmit_all_data_state == 1) begin
+ transmit_all_data_state = 0;
+ end
+ end
+
+ if (transmit_main_status_done == 1) begin
+ transmit_main_status = 0;
+ if (transmit_all_data_state == 1) begin
+ transmit_4_bit_status = 1;
+ end
+ end
+
+ if (transmit_input_status_done == 1) begin
+ transmit_input_status = 0;
+ end
+
+ if (transmit_lcd_status_done == 1) begin
+ transmit_lcd_status = 0;
+ if (transmit_all_data_state == 1) begin
+ transmit_main_status = 1;
+ end
+ end
+
+ if (transmit_dsp_status_done == 1) begin
+ transmit_dsp_status = 0;
+ data_storage_remote_enable = 0;
+ end
+
+ if (transmit_dsp_status == 1) begin
+ data_storage_remote_enable = 1;
+ end
+
+ if (data_write_timer > 1) begin
+ data_write_timer = data_write_timer - 1;
+ end else begin
+ if (data_write_timer == 1) begin
+ data_storage_write_enable_reg = 0;
+ data_write_timer = 0;
+ end
+ end
+
+ if ((waiting_on_dsp_processing == 1) && (sram_processing_done == 1)) begin
+ waiting_on_dsp_processing = 0;
+ transmit_dsp_status = 1;
+ end
+
+ serial_rx_strobe_reg = 0; // Make sure that this get reset!
+
+ if ((sram_processing_done == 1) && (sram_available_reg == 1)) begin
+ sram_available_reg = 0;
+ transmit_dsp_status = 1;
+ end
+
+ if (RxD_data_ready == 1) begin
+ if (serial_character_received == 0) begin
+ serial_rx_data_reg = RxD_data;
+ serial_rx_strobe_reg = 1; // Signal new data...
+ if (seize_serial_tx == 0) begin
+ // Parse the command and see what it is
+ serial_character_received = 1;
+ if (RxD_data == 13) begin
+ // Carriage Return! The serial_command_buffer holds the command! Parse it!
+ if (next_byte_is_command == 0) begin
+ if (serial_command_buffer == 65) begin
+ // Display update requested
+ next_byte_is_command = 1;
+ serial_update_counter = 0;
+ next_byte_is_command_prev_command = 65;
+ end
+
+ if (serial_command_buffer == 66) begin
+ // 8 bit input update
+ if (enable_remote_access_input == 1) begin
+ next_byte_is_command = 1;
+ serial_update_counter = 0;
+ next_byte_is_command_prev_command = 66;
+ end
+ end
+
+ if (serial_command_buffer == 67) begin
+ // 16 bit input update
+ next_byte_is_command = 1;
+ serial_update_counter = 0;
+ next_byte_is_command_prev_command = 67;
+ end
+
+ if (serial_command_buffer == 68) begin
+ // 8 bit output status
+ transmit_8_bit_status = 1;
+ end
+
+ if (serial_command_buffer == 69) begin
+ // 16 bit output status
+ transmit_16_bit_status = 1;
+ end
+
+ if (serial_command_buffer == 70) begin
+ // System status
+ transmit_main_status = 1;
+ end
+
+ if (serial_command_buffer == 71) begin
+ // Simulate center button press
+ enable_remote_access_input = !enable_remote_access_input;
+ end
+
+ if (serial_command_buffer == 72) begin
+ // Local input status
+ transmit_input_status = 1;
+ end
+
+ if (serial_command_buffer == 73) begin
+ // 4 bit input update
+ if (enable_remote_access_input == 1) begin
+ next_byte_is_command = 1;
+ serial_update_counter = 0;
+ next_byte_is_command_prev_command = 73;
+ end
+ end
+
+ if (serial_command_buffer == 74) begin
+ // 4 bit output status
+ transmit_4_bit_status = 1;
+ end
+
+ if (serial_command_buffer == 75) begin
+ // Transmit the contents of the LCD...
+ transmit_lcd_status = 1;
+ end
+
+ if (serial_command_buffer == 76) begin
+ // Transmit the contents of the LCD...
+ transmit_all_data_state = 1;
+ transmit_lcd_status = 1;
+ end
+
+ if (serial_command_buffer == 77) begin
+ // Receive offline DSP data
+ next_byte_is_command = 1;
+ dsp_update_counter = 0;
+ next_byte_is_command_prev_command = 77;
+ end
+
+ if (serial_command_buffer == 78) begin
+ // Transmit the contents of RAM...
+ transmit_dsp_status = 1;
+ end
+ end else begin
+ if (next_byte_is_command == 1) begin
+ // The previous byte was the command--now load in the data!
+ if (next_byte_is_command_prev_command == 65) begin
+ if (serial_update_counter < 32) begin
+ received_lcd_display_string[serial_update_counter] = serial_command_buffer;
+ serial_update_counter = serial_update_counter + 1;
+ end else begin
+ update_lcd_display = 1;
+ serial_command_timer = 255;
+ next_byte_is_command = 0;
+ end
+ end
+
+ // 4 bit input update
+ if (next_byte_is_command_prev_command == 73) begin
+ remote_access_4_bit_input_reg = serial_command_buffer;
+ next_byte_is_command = 0;
+ end
+
+ // 8 bit input update
+ if (next_byte_is_command_prev_command == 66) begin
+ remote_access_8_bit_input_reg = serial_command_buffer;
+ next_byte_is_command = 0;
+ end
+
+ // 16 bit input update
+ if (next_byte_is_command_prev_command == 67) begin
+ if (serial_update_counter == 0) begin
+ remote_access_16_bit_input_reg[15:8] = serial_command_buffer;
+ serial_update_counter = 1;
+ end else begin
+ remote_access_16_bit_input_reg[7:0] = serial_command_buffer;
+ next_byte_is_command = 0;
+ end
+ end
+
+ // DSP input data
+ if (next_byte_is_command_prev_command == 77) begin
+ if (dsp_update_counter < 16384) begin
+ data_storage_remote_enable = 1;
+ data_storage_addra_reg = dsp_update_counter;
+ data_storage_dina_reg = serial_command_buffer;
+ data_storage_write_enable_reg = 1;
+ data_write_timer = 3;
+ dsp_update_counter = dsp_update_counter + 1;
+
+ // TESTING ONLY!!!
+ //if (dsp_update_counter < 17) begin
+ // received_lcd_display_string[dsp_update_counter - 1] = serial_command_buffer;
+ //end
+ end else begin
+ next_byte_is_command = 0;
+ data_storage_write_enable_reg = 0;
+ data_storage_remote_enable = 0;
+ sram_available_reg = 1;
+ data_storage_write_enable_reg = 1'bz;
+ data_storage_addra_reg = 14'bz;
+ waiting_on_dsp_processing = 1;
+
+ // TESTING ONLY!!!
+ //transmit_dsp_status = 1;
+ end
+ end
+ end
+ end
+ end
+ end
+
+ //if (RxD_data != 10) begin // Ignore linefeeds
+ serial_command_buffer = RxD_data;
+ //end
+
+ if (RxD_data == 13) begin
+ prev_was_carriage_return = 1;
+ end else begin
+ prev_was_carriage_return = 0;
+ end
+
+ serial_receiver_toggler = serial_receiver_toggler + 1;
+ end
+ end
+
+ if (RxD_data_ready == 0) begin
+ serial_character_received = 0;
+ end
+ end
+
+ //-----------------------------------------------------------------------------------
+ //
+ // This routine will display the contents of lcd_display_string on the LCD display
+ //
+ //-----------------------------------------------------------------------------------
+
+ reg [15:0] lcd_display_wait_counter = 0;
+ reg [7:0] lcd_display_current_character = 0;
+ reg lcd_display_line_two = 0; // Are we trying to write to line two?
+
+ always @(posedge four_mhz_clk) begin
+ case (lcd_display_initialization_state)
+ // Initialize the display according to the reference manual
+ 0:begin
+ // Set up the default display...
+ lcd_display_string[0] = 73; // I
+ lcd_display_string[1] = 110; // n
+ lcd_display_string[2] = 105; // i
+ lcd_display_string[3] = 116; // t
+ lcd_display_string[4] = 105; // i
+ lcd_display_string[5] = 97; // a
+ lcd_display_string[6] = 108; // l
+ lcd_display_string[7] = 105; // i
+ lcd_display_string[8] = 122; // z
+ lcd_display_string[9] = 97; // a
+ lcd_display_string[10] = 116; // t
+ lcd_display_string[11] = 105; // i
+ lcd_display_string[12] = 111; // o
+ lcd_display_string[13] = 110; // n
+ lcd_display_string[14] = 32; // <blank>
+ lcd_display_string[15] = 32; // <blank>
+ lcd_display_string[16] = 79; // O
+ lcd_display_string[17] = 75; // k
+ lcd_display_string[18] = 32; // <blank>
+ lcd_display_string[19] = 32; // <blank>
+ lcd_display_string[20] = 32; // <blank>
+ lcd_display_string[21] = 32; // <blank>
+ lcd_display_string[22] = 32; // <blank>
+ lcd_display_string[23] = 32; // <blank>
+ lcd_display_string[24] = 32; // <blank>
+ lcd_display_string[25] = 32; // <blank>
+ lcd_display_string[26] = 32; // <blank>
+ lcd_display_string[27] = 32; // <blank>
+ lcd_display_string[28] = 32; // <blank>
+ lcd_display_string[29] = 32; // <blank>
+ lcd_display_string[30] = 32; // <blank>
+ lcd_display_string[31] = 32; // <blank>
+
+ lcd_display_current_character = 0;
+
+ lcd_display_line_two = 0;
+ remote_access_lcd_data_out_reg = 3;
+ remote_access_lcd_enable_out_reg = 1;
+ remote_access_lcd_rs_out_reg = 0;
+ remote_access_lcd_rw_out_reg = 0;
+ lcd_display_wait_counter = 17083; // Wait 15mS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 1:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 2:begin
+ remote_access_lcd_data_out_reg = 3;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 417; // Wait 100uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 3:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 4:begin
+ remote_access_lcd_data_out_reg = 3;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 167; // Wait 40uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 5:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 6:begin
+ remote_access_lcd_data_out_reg = 2;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 167; // Wait 40uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 7:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ // Display is now initialized
+
+ // Send Function Set command
+ 8:begin
+ remote_access_lcd_data_out_reg = 2;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 5; // Wait 1uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 9:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 10:begin
+ remote_access_lcd_data_out_reg = 8;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 167; // Wait 40uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 11:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+
+ // Send Entry Mode Set command
+ 12:begin
+ remote_access_lcd_data_out_reg = 0;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 5; // Wait 1uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 13:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 14:begin
+ remote_access_lcd_data_out_reg = 6;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 167; // Wait 40uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 15:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+
+ // Send Display On command and disable cursors and blinking
+ 16:begin
+ remote_access_lcd_data_out_reg = 0;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 5; // Wait 1uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 17:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 18:begin
+ remote_access_lcd_data_out_reg = 12;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 167; // Wait 40uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 19:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+
+ // Send Clear Display command
+ 20:begin
+ remote_access_lcd_data_out_reg = 0;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 5; // Wait 1uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 21:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 22:begin
+ remote_access_lcd_data_out_reg = 1;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 6833; // Wait 1.64uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 23:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+
+ // Set DD RAM Address to 0 if lcd_display_line_two is 0, or 0x40 if it is 1
+ 24:begin
+ remote_access_lcd_rs_out_reg = 0;
+ if (lcd_display_line_two == 0) begin
+ remote_access_lcd_data_out_reg = 8;
+ end
+ if (lcd_display_line_two == 1) begin
+ remote_access_lcd_data_out_reg = 12;
+ end
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 5; // Wait 1uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 25:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 26:begin
+ remote_access_lcd_data_out_reg = 0;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 167; // Wait 40uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 27:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+
+ // Display the characters
+ 28:begin
+ remote_access_lcd_data_out_reg = lcd_display_string[lcd_display_current_character][7:4];
+ remote_access_lcd_rs_out_reg = 1;
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 5; // Wait 1uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 29:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 30:begin
+ remote_access_lcd_data_out_reg = lcd_display_string[lcd_display_current_character][3:0];
+ remote_access_lcd_enable_out_reg = 1;
+ lcd_display_wait_counter = 167; // Wait 40uS
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 31:begin
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_wait_counter = lcd_display_wait_counter - 1;
+ if (lcd_display_wait_counter == 0) lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ end
+ 32:begin
+ lcd_display_current_character = lcd_display_current_character + 1;
+ lcd_display_initialization_state = lcd_display_initialization_state + 1;
+ if (lcd_display_current_character < 32) begin
+ lcd_display_initialization_state = 28;
+ end
+ if (lcd_display_current_character == 16) begin
+ if (lcd_display_line_two == 0) begin
+ lcd_display_line_two = 1;
+ lcd_display_initialization_state = 24;
+ end
+ end
+ end
+ 33:begin
+ // End!
+ remote_access_lcd_rs_out_reg = 0;
+ remote_access_lcd_enable_out_reg = 0;
+ lcd_display_line_two = 0;
+ lcd_display_current_character = 0;
+ if (update_lcd_display == 1) begin
+ lcd_display_line_two = 0;
+ lcd_display_current_character = 0;
+ lcd_display_initialization_state = 24;
+ lcd_display_string[0] = received_lcd_display_string[0];
+ lcd_display_string[1] = received_lcd_display_string[1];
+ lcd_display_string[2] = received_lcd_display_string[2];
+ lcd_display_string[3] = received_lcd_display_string[3];
+ lcd_display_string[4] = received_lcd_display_string[4];
+ lcd_display_string[5] = received_lcd_display_string[5];
+ lcd_display_string[6] = received_lcd_display_string[6];
+ lcd_display_string[7] = received_lcd_display_string[7];
+ lcd_display_string[8] = received_lcd_display_string[8];
+ lcd_display_string[9] = received_lcd_display_string[9];
+ lcd_display_string[10] = received_lcd_display_string[10];
+ lcd_display_string[11] = received_lcd_display_string[11];
+ lcd_display_string[12] = received_lcd_display_string[12];
+ lcd_display_string[13] = received_lcd_display_string[13];
+ lcd_display_string[14] = received_lcd_display_string[14];
+ lcd_display_string[15] = received_lcd_display_string[15];
+ lcd_display_string[16] = received_lcd_display_string[16];
+ lcd_display_string[17] = received_lcd_display_string[17];
+ lcd_display_string[18] = received_lcd_display_string[18];
+ lcd_display_string[19] = received_lcd_display_string[19];
+ lcd_display_string[20] = received_lcd_display_string[20];
+ lcd_display_string[21] = received_lcd_display_string[21];
+ lcd_display_string[22] = received_lcd_display_string[22];
+ lcd_display_string[23] = received_lcd_display_string[23];
+ lcd_display_string[24] = received_lcd_display_string[24];
+ lcd_display_string[25] = received_lcd_display_string[25];
+ lcd_display_string[26] = received_lcd_display_string[26];
+ lcd_display_string[27] = received_lcd_display_string[27];
+ lcd_display_string[28] = received_lcd_display_string[28];
+ lcd_display_string[29] = received_lcd_display_string[29];
+ lcd_display_string[30] = received_lcd_display_string[30];
+ lcd_display_string[31] = received_lcd_display_string[31];
+ end
+ end
+ endcase
+ end
+endmodule
+
+module async_receiver(clk, RxD, RxD_data_ready, RxD_data, RxD_endofpacket, RxD_idle);
+ input clk, RxD;
+ output RxD_data_ready; // onc clock pulse when RxD_data is valid
+ output [7:0] RxD_data;
+
+ parameter ClkFrequency = 25000000; // 25MHz
+ parameter Baud = 115200;
+
+ // We also detect if a gap occurs in the received stream of characters
+ // That can be useful if multiple characters are sent in burst
+ // so that multiple characters can be treated as a "packet"
+ output RxD_endofpacket; // one clock pulse, when no more data is received (RxD_idle is going high)
+ output RxD_idle; // no data is being received
+
+ // Baud generator (we use 8 times oversampling)
+ parameter Baud8 = Baud*8;
+ parameter Baud8GeneratorAccWidth = 16;
+ wire [Baud8GeneratorAccWidth:0] Baud8GeneratorInc = ((Baud8<<(Baud8GeneratorAccWidth-7))+(ClkFrequency>>8))/(ClkFrequency>>7);
+ reg [Baud8GeneratorAccWidth:0] Baud8GeneratorAcc;
+ always @(posedge clk) Baud8GeneratorAcc <= Baud8GeneratorAcc[Baud8GeneratorAccWidth-1:0] + Baud8GeneratorInc;
+ wire Baud8Tick = Baud8GeneratorAcc[Baud8GeneratorAccWidth];
+
+ ////////////////////////////
+ reg [1:0] RxD_sync_inv;
+ always @(posedge clk) if(Baud8Tick) RxD_sync_inv <= {RxD_sync_inv[0], ~RxD};
+ // we invert RxD, so that the idle becomes "0", to prevent a phantom character to be received at startup
+
+ reg [1:0] RxD_cnt_inv;
+ reg RxD_bit_inv;
+
+ always @(posedge clk)
+ if(Baud8Tick)
+ begin
+ if( RxD_sync_inv[1] && RxD_cnt_inv!=2'b11) RxD_cnt_inv <= RxD_cnt_inv + 2'h1;
+ else
+ if(~RxD_sync_inv[1] && RxD_cnt_inv!=2'b00) RxD_cnt_inv <= RxD_cnt_inv - 2'h1;
+
+ if(RxD_cnt_inv==2'b00) RxD_bit_inv <= 1'b0;
+ else
+ if(RxD_cnt_inv==2'b11) RxD_bit_inv <= 1'b1;
+ end
+
+ reg [3:0] state;
+ reg [3:0] bit_spacing;
+
+ // "next_bit" controls when the data sampling occurs
+ // depending on how noisy the RxD is, different values might work better
+ // with a clean connection, values from 8 to 11 work
+ wire next_bit = (bit_spacing==4'd10);
+
+ always @(posedge clk)
+ if(state==0)
+ bit_spacing <= 4'b0000;
+ else
+ if(Baud8Tick)
+ bit_spacing <= {bit_spacing[2:0] + 4'b0001} | {bit_spacing[3], 3'b000};
+
+ always @(posedge clk)
+ if(Baud8Tick)
+ case(state)
+ 4'b0000: if(RxD_bit_inv) state <= 4'b1000; // start bit found?
+ 4'b1000: if(next_bit) state <= 4'b1001; // bit 0
+ 4'b1001: if(next_bit) state <= 4'b1010; // bit 1
+ 4'b1010: if(next_bit) state <= 4'b1011; // bit 2
+ 4'b1011: if(next_bit) state <= 4'b1100; // bit 3
+ 4'b1100: if(next_bit) state <= 4'b1101; // bit 4
+ 4'b1101: if(next_bit) state <= 4'b1110; // bit 5
+ 4'b1110: if(next_bit) state <= 4'b1111; // bit 6
+ 4'b1111: if(next_bit) state <= 4'b0001; // bit 7
+ 4'b0001: if(next_bit) state <= 4'b0000; // stop bit
+ default: state <= 4'b0000;
+ endcase
+
+ reg [7:0] RxD_data;
+ always @(posedge clk)
+ if(Baud8Tick && next_bit && state[3]) RxD_data <= {~RxD_bit_inv, RxD_data[7:1]};
+
+ reg RxD_data_ready;
+ always @(posedge clk)
+ begin
+ RxD_data_ready <= (Baud8Tick && next_bit && state==4'b0001 && ~RxD_bit_inv); // ready only if the stop bit is received
+ end
+
+ reg [4:0] gap_count;
+ always @(posedge clk) if (state!=0) gap_count<=5'h00; else if(Baud8Tick & ~gap_count[4]) gap_count <= gap_count + 5'h01;
+ assign RxD_idle = gap_count[4];
+ reg RxD_endofpacket; always @(posedge clk) RxD_endofpacket <= Baud8Tick & (gap_count==5'h0F);
+endmodule
+
+module async_transmit(clk, TxD_start, TxD_data, TxD, TxD_busy, state);
+ input clk, TxD_start;
+ input [7:0] TxD_data;
+ output TxD, TxD_busy;
+ output [4:0] state;
+ parameter ClkFrequency = 25000000; // 25MHz
+ //parameter ClkFrequency = 50000000; // 50MHz
+ parameter Baud = 115200;
+ parameter RegisterInputData = 1; // in RegisterInputData mode, the input doesn't have to stay valid while the character is been transmitted
+
+ // Baud generator
+ parameter BaudGeneratorAccWidth = 16;
+ reg [BaudGeneratorAccWidth:0] BaudGeneratorAcc;
+ `ifdef DEBUG
+ wire [BaudGeneratorAccWidth:0] BaudGeneratorInc = 17'h10000;
+ `else
+ wire [BaudGeneratorAccWidth:0] BaudGeneratorInc = ((Baud<<(BaudGeneratorAccWidth-4))+(ClkFrequency>>5))/(ClkFrequency>>4);
+ `endif
+
+ wire BaudTick = BaudGeneratorAcc[BaudGeneratorAccWidth];
+ wire TxD_busy;
+ always @(posedge clk) if(TxD_busy) BaudGeneratorAcc <= BaudGeneratorAcc[BaudGeneratorAccWidth-1:0] + BaudGeneratorInc;
+
+ // Transmitter state machine
+ reg [4:0] state;
+ wire TxD_ready = (state==0);
+ assign TxD_busy = ~TxD_ready;
+
+ reg [7:0] TxD_dataReg;
+ always @(posedge clk) if(TxD_ready & TxD_start) TxD_dataReg <= TxD_data;
+ wire [7:0] TxD_dataD = RegisterInputData ? TxD_dataReg : TxD_data;
+
+ always @(posedge clk) begin
+ if (TxD_start == 0) state <= 5'b00000;
+
+ case(state)
+ 5'b00000: if(TxD_start) state <= 5'b00001;
+ 5'b00001: if(BaudTick) state <= 5'b00100;
+ 5'b00100: if(BaudTick) state <= 5'b01000; // start
+ 5'b01000: if(BaudTick) state <= 5'b01001; // bit 0
+ 5'b01001: if(BaudTick) state <= 5'b01010; // bit 1
+ 5'b01010: if(BaudTick) state <= 5'b01011; // bit 2
+ 5'b01011: if(BaudTick) state <= 5'b01100; // bit 3
+ 5'b01100: if(BaudTick) state <= 5'b01101; // bit 4
+ 5'b01101: if(BaudTick) state <= 5'b01110; // bit 5
+ 5'b01110: if(BaudTick) state <= 5'b01111; // bit 6
+ 5'b01111: if(BaudTick) state <= 5'b00010; // bit 7
+ 5'b00010: if(BaudTick) state <= 5'b00011; // stop1
+ //4'b0011: if(BaudTick) state <= 4'b0000; // stop2
+ 5'b00011: if(BaudTick) state <= 5'b10000; // stop2
+ //default: if(BaudTick) state <= 4'b0000;
+ endcase
+ end
+
+ // Output mux
+ reg muxbit;
+ always @( * )
+ case(state[2:0])
+ 3'd0: muxbit <= TxD_dataD[0];
+ 3'd1: muxbit <= TxD_dataD[1];
+ 3'd2: muxbit <= TxD_dataD[2];
+ 3'd3: muxbit <= TxD_dataD[3];
+ 3'd4: muxbit <= TxD_dataD[4];
+ 3'd5: muxbit <= TxD_dataD[5];
+ 3'd6: muxbit <= TxD_dataD[6];
+ 3'd7: muxbit <= TxD_dataD[7];
+ endcase
+
+ // Put together the start, data and stop bits
+ reg TxD;
+ always @(posedge clk) TxD <= (state<4) | (state[3] & muxbit) | state[4]; // register the output to make it glitch free
+
+endmodule