From 1575d4f53805f177474b5bb96daebede9b2dfb73 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 24 Feb 2021 23:45:58 +0000 Subject: base --- de1/fpga-bbc-pq/master/keyboard.patch | 787 ++++++++++++++++++++++++++++++++++ 1 file changed, 787 insertions(+) create mode 100644 de1/fpga-bbc-pq/master/keyboard.patch (limited to 'de1/fpga-bbc-pq/master/keyboard.patch') diff --git a/de1/fpga-bbc-pq/master/keyboard.patch b/de1/fpga-bbc-pq/master/keyboard.patch new file mode 100644 index 0000000..ffeefc3 --- /dev/null +++ b/de1/fpga-bbc-pq/master/keyboard.patch @@ -0,0 +1,787 @@ +diff --git a/bbc_micro_de1.vhd b/bbc_micro_de1.vhd +index 462e507..7de7276 100644 +--- a/bbc_micro_de1.vhd ++++ b/bbc_micro_de1.vhd +@@ -398,8 +398,8 @@ port ( + CLKEN_1MHZ : in std_logic; + + -- PS/2 interface +- PS2_CLK : in std_logic; +- PS2_DATA : in std_logic; ++ PS2_CLK : inout std_logic; ++ PS2_DATA : inout std_logic; + + -- If 1 then column is incremented automatically at + -- 1 MHz rate +@@ -416,7 +416,9 @@ port ( + BREAK_OUT : out std_logic; + + -- DIP switch inputs +- DIP_SWITCH : in std_logic_vector(7 downto 0) ++ DIP_SWITCH : in std_logic_vector(7 downto 0); ++ ++ DEBUG : out std_logic_vector(7 downto 0) + ); + end component; + +@@ -930,7 +932,8 @@ begin + keyb_out, + keyb_int, + keyb_break, +- SW(7 downto 0) ++ SW(7 downto 0), ++ LEDG + ); + + -- Sound generator (and drive logic for I2S codec) +diff --git a/keyboard.vhd b/keyboard.vhd +index cba4054..d3dd8f4 100644 +--- a/keyboard.vhd ++++ b/keyboard.vhd +@@ -50,8 +50,8 @@ port ( + CLKEN_1MHZ : in std_logic; + + -- PS/2 interface +- PS2_CLK : in std_logic; +- PS2_DATA : in std_logic; ++ PS2_CLK : inout std_logic; ++ PS2_DATA : inout std_logic; + + -- If 1 then column is incremented automatically at + -- 1 MHz rate +@@ -68,31 +68,57 @@ port ( + BREAK_OUT : out std_logic; + + -- DIP switch inputs +- DIP_SWITCH : in std_logic_vector(7 downto 0) ++ DIP_SWITCH : in std_logic_vector(7 downto 0); ++ DEBUG : out std_logic_vector(7 downto 0) + ); + end entity; + + architecture rtl of keyboard is + + -- PS/2 interface +-component ps2_intf is +-generic (filter_length : positive := 8); ++--component ps2_intf is ++--generic (filter_length : positive := 8); ++--port( ++-- CLK : in std_logic; ++-- nRESET : in std_logic; ++-- ++-- -- PS/2 interface (could be bi-dir) ++-- PS2_CLK : inout std_logic; ++-- PS2_DATA : inout std_logic; ++-- ++-- -- Byte-wide data interface - only valid for one clock ++-- -- so must be latched externally if required ++-- DATA : out std_logic_vector(7 downto 0); ++-- VALID : out std_logic; ++-- ERROR : out std_logic; ++-- DEBUG : out std_logic_vector(7 downto 0) ++-- ); ++--end component; ++ ++component ps2_keyboard is + port( + CLK : in std_logic; +- nRESET : in std_logic; +- +- -- PS/2 interface (could be bi-dir) +- PS2_CLK : in std_logic; +- PS2_DATA : in std_logic; +- +- -- Byte-wide data interface - only valid for one clock +- -- so must be latched externally if required +- DATA : out std_logic_vector(7 downto 0); +- VALID : out std_logic; +- ERROR : out std_logic +- ); ++ RESET : in std_logic; ++ PS2_CLK_O : out std_logic; ++ PS2_DATA_O : out std_logic; ++ PS2_CLK_I : in std_logic; ++ PS2_DATA_I : in std_logic; ++ RX_EXTENDED : out std_logic; ++ RX_RELEASED : out std_logic; ++ RX_SHIFT_KEY_ON : out std_logic; ++ RX_SCAN_CODE : out std_logic_vector(7 downto 0); ++ RX_ASCII : out std_logic_vector(7 downto 0); ++ RX_DATA_READY : out std_logic; ++ RX_READ : in std_logic; ++ TX_DATA : in std_logic_vector(7 downto 0); ++ TX_WRITE : in std_logic; ++ TX_WRITE_ACK_O : out std_logic; ++ TX_ERROR_NO_KEYBOARD_ACK : out std_logic; ++ TRANSLATE : in std_logic ++); + end component; + ++ + -- Interface to PS/2 block + signal keyb_data : std_logic_vector(7 downto 0); + signal keyb_valid : std_logic; +@@ -104,13 +130,46 @@ signal keys : key_matrix; + signal col : unsigned(3 downto 0); + signal release : std_logic; + signal extended : std_logic; ++ ++signal rx_extended : std_logic; ++signal rx_release : std_logic; ++signal rx_shift_key_on : std_logic; ++signal rx_ascii : std_logic_vector(7 downto 0); ++signal tx_write_ack : std_logic; ++signal tx_error : std_logic; ++ ++signal ps2_clk_o : std_logic; ++signal ps2_data_o: std_logic; ++signal tx_data : std_logic_vector(7 downto 0); ++signal tx_write : std_logic; + begin + +- ps2 : ps2_intf port map ( +- CLOCK, nRESET, +- PS2_CLK, PS2_DATA, +- keyb_data, keyb_valid, keyb_error +- ); ++ PS2_CLK <='0' when ps2_clk_o='0' else 'Z'; ++ PS2_DATA <='0' when ps2_data_o='0' else 'Z'; ++ ++ ++ ++ ps2 : ps2_keyboard port map ( ++ CLOCK, not nRESET, ++ ps2_clk_o,ps2_data_o, ++ PS2_CLK,PS2_DATA, ++ rx_extended,rx_release, ++ rx_shift_key_on, keyb_data,rx_ascii, ++ keyb_valid,keyb_valid,tx_data, ++ tx_write,tx_write_ack,tx_error,'0'); ++ ++ ++ process(CLOCK,nRESET,tx_write_ack) begin ++ if nRESET = '0' then ++ tx_write <= '1'; ++ tx_data <= to_stdlogicvector(x"F4"); ++ elsif rising_edge(CLOCK) then ++ if tx_write_ack='1' then ++ tx_write<='0'; ++ end if; ++ end if; ++ end process; ++ + + -- Column counts automatically when AUTOSCAN is enabled, otherwise + -- value is loaded from external input +@@ -188,6 +247,7 @@ begin + keys(9)(0) <= DIP_SWITCH(0); + + if keyb_valid = '1' then ++ DEBUG <= keyb_data; + -- Decode keyboard input + if keyb_data = X"e0" then + -- Extended key code follows +diff --git a/ps2_keyboard.v b/ps2_keyboard.v +new file mode 100644 +index 0000000..0f21c7c +--- /dev/null ++++ b/ps2_keyboard.v +@@ -0,0 +1,597 @@ ++//------------------------------------------------------------------------------------- ++ ++ ++`define TOTAL_BITS 11 ++`define EXTEND_CODE 16'hE0 ++`define RELEASE_CODE 16'hF0 ++`define LEFT_SHIFT 16'h12 ++`define RIGHT_SHIFT 16'h59 ++ ++ ++module ps2_keyboard ( ++ clk, ++ reset, ++ ps2_clk_o, ++ ps2_data_o, ++ ps2_clk_i, ++ ps2_data_i, ++ rx_extended, ++ rx_released, ++ rx_shift_key_on, ++ rx_scan_code, ++ rx_ascii, ++ rx_data_ready, // rx_read_o ++ rx_read, // rx_read_ack_i ++ tx_data, ++ tx_write, ++ tx_write_ack_o, ++ tx_error_no_keyboard_ack, ++ translate ++ ); ++ ++// Parameters ++ ++// The timer value can be up to (2^bits) inclusive. ++parameter TIMER_60USEC_VALUE_PP = 2950; // Number of sys_clks for 60usec. ++parameter TIMER_60USEC_BITS_PP = 12; // Number of bits needed for timer ++parameter TIMER_5USEC_VALUE_PP = 186; // Number of sys_clks for debounce ++parameter TIMER_5USEC_BITS_PP = 8; // Number of bits needed for timer ++parameter TRAP_SHIFT_KEYS_PP = 0; // Default: No shift key trap. ++ ++// State encodings, provided as parameters ++// for flexibility to the one instantiating the module. ++// In general, the default values need not be changed. ++ ++// State "m1_rx_clk_l" has been chosen on purpose. Since the input ++// synchronizing flip-flops initially contain zero, it takes one clk ++// for them to update to reflect the actual (idle = high) status of ++// the I/O lines from the keyboard. Therefore, choosing 0 for m1_rx_clk_l ++// allows the state machine to transition to m1_rx_clk_h when the true ++// values of the input signals become present at the outputs of the ++// synchronizing flip-flops. This initial transition is harmless, and it ++// eliminates the need for a "reset" pulse before the interface can operate. ++ ++parameter m1_rx_clk_h = 1; ++parameter m1_rx_clk_l = 0; ++parameter m1_rx_falling_edge_marker = 13; ++parameter m1_rx_rising_edge_marker = 14; ++parameter m1_tx_force_clk_l = 3; ++parameter m1_tx_first_wait_clk_h = 10; ++parameter m1_tx_first_wait_clk_l = 11; ++parameter m1_tx_reset_timer = 12; ++parameter m1_tx_wait_clk_h = 2; ++parameter m1_tx_clk_h = 4; ++parameter m1_tx_clk_l = 5; ++parameter m1_tx_wait_keyboard_ack = 6; ++parameter m1_tx_done_recovery = 7; ++parameter m1_tx_error_no_keyboard_ack = 8; ++parameter m1_tx_rising_edge_marker = 9; ++parameter m2_rx_data_ready = 1; ++parameter m2_rx_data_ready_ack = 0; ++ ++ ++// I/O declarations ++input clk; ++input reset; ++output ps2_clk_o ; ++output ps2_data_o ; ++input ps2_clk_i ; ++input ps2_data_i ; ++output rx_extended; ++output rx_released; ++output rx_shift_key_on; ++output [7:0] rx_scan_code; ++output [7:0] rx_ascii; ++output rx_data_ready; ++input rx_read; ++input [7:0] tx_data; ++input tx_write; ++output tx_write_ack_o; ++output tx_error_no_keyboard_ack; ++input translate ; ++ ++reg rx_extended; ++reg rx_released; ++reg [7:0] rx_scan_code; ++reg [7:0] rx_ascii; ++reg rx_data_ready; ++reg tx_error_no_keyboard_ack; ++ ++// Internal signal declarations ++wire timer_60usec_done; ++wire timer_5usec_done; ++wire extended; ++wire released; ++wire shift_key_on; ++ ++ // NOTE: These two signals used to be one. They ++ // were split into two signals because of ++ // shift key trapping. With shift key ++ // trapping, no event is generated externally, ++ // but the "hold" data must still be cleared ++ // anyway regardless, in preparation for the ++ // next scan codes. ++wire rx_output_event; // Used only to clear: hold_released, hold_extended ++wire rx_output_strobe; // Used to produce the actual output. ++ ++wire tx_parity_bit; ++wire rx_shifting_done; ++wire tx_shifting_done; ++wire [11:0] shift_key_plus_code; ++ ++reg [`TOTAL_BITS-1:0] q; ++reg [3:0] m1_state; ++reg [3:0] m1_next_state; ++reg m2_state; ++reg m2_next_state; ++reg [3:0] bit_count; ++reg enable_timer_60usec; ++reg enable_timer_5usec; ++reg [TIMER_60USEC_BITS_PP-1:0] timer_60usec_count; ++reg [TIMER_5USEC_BITS_PP-1:0] timer_5usec_count; ++reg [7:0] ascii; // "REG" type only because a case statement is used. ++reg left_shift_key; ++reg right_shift_key; ++reg hold_extended; // Holds prior value, cleared at rx_output_strobe ++reg hold_released; // Holds prior value, cleared at rx_output_strobe ++reg ps2_clk_s; // Synchronous version of this input ++reg ps2_data_s; // Synchronous version of this input ++reg ps2_clk_hi_z; // Without keyboard, high Z equals 1 due to pullups. ++reg ps2_data_hi_z; // Without keyboard, high Z equals 1 due to pullups. ++ ++//-------------------------------------------------------------------------- ++// Module code ++ ++assign ps2_clk_o = ps2_clk_hi_z ; ++assign ps2_data_o = ps2_data_hi_z ; ++ ++// Input "synchronizing" logic -- synchronizes the inputs to the state ++// machine clock, thus avoiding errors related to ++// spurious state machine transitions. ++always @(posedge clk) ++begin ++ ps2_clk_s <= ps2_clk_i; ++ ps2_data_s <= ps2_data_i; ++end ++ ++// State register ++always @(posedge clk) ++begin : m1_state_register ++ if (reset) m1_state <= m1_rx_clk_h; ++ else m1_state <= m1_next_state; ++end ++ ++// State transition logic ++always @(m1_state ++ or q ++ or tx_shifting_done ++ or tx_write ++ or ps2_clk_s ++ or ps2_data_s ++ or timer_60usec_done ++ or timer_5usec_done ++ ) ++begin : m1_state_logic ++ ++ // Output signals default to this value, unless changed in a state condition. ++ ps2_clk_hi_z <= 1; ++ ps2_data_hi_z <= 1; ++ tx_error_no_keyboard_ack <= 0; ++ enable_timer_60usec <= 0; ++ enable_timer_5usec <= 0; ++ ++ case (m1_state) ++ ++ m1_rx_clk_h : ++ begin ++ enable_timer_60usec <= 1; ++ if (tx_write) m1_next_state <= m1_tx_reset_timer; ++ else if (~ps2_clk_s) m1_next_state <= m1_rx_falling_edge_marker; ++ else m1_next_state <= m1_rx_clk_h; ++ end ++ ++ m1_rx_falling_edge_marker : ++ begin ++ enable_timer_60usec <= 0; ++ m1_next_state <= m1_rx_clk_l; ++ end ++ ++ m1_rx_rising_edge_marker : ++ begin ++ enable_timer_60usec <= 0; ++ m1_next_state <= m1_rx_clk_h; ++ end ++ ++ ++ m1_rx_clk_l : ++ begin ++ enable_timer_60usec <= 1; ++ if (tx_write) m1_next_state <= m1_tx_reset_timer; ++ else if (ps2_clk_s) m1_next_state <= m1_rx_rising_edge_marker; ++ else m1_next_state <= m1_rx_clk_l; ++ end ++ ++ m1_tx_reset_timer: ++ begin ++ enable_timer_60usec <= 0; ++ m1_next_state <= m1_tx_force_clk_l; ++ end ++ ++ m1_tx_force_clk_l : ++ begin ++ enable_timer_60usec <= 1; ++ ps2_clk_hi_z <= 0; // Force the ps2_clk line low. ++ if (timer_60usec_done) m1_next_state <= m1_tx_first_wait_clk_h; ++ else m1_next_state <= m1_tx_force_clk_l; ++ end ++ ++ m1_tx_first_wait_clk_h : ++ begin ++ enable_timer_5usec <= 1; ++ ps2_data_hi_z <= 0; // Start bit. ++ if (~ps2_clk_s && timer_5usec_done) ++ m1_next_state <= m1_tx_clk_l; ++ else ++ m1_next_state <= m1_tx_first_wait_clk_h; ++ end ++ ++ // This state must be included because the device might possibly ++ // delay for up to 10 milliseconds before beginning its clock pulses. ++ // During that waiting time, we cannot drive the data (q[0]) because it ++ // is possibly 1, which would cause the keyboard to abort its receive ++ // and the expected clocks would then never be generated. ++ m1_tx_first_wait_clk_l : ++ begin ++ ps2_data_hi_z <= 0; ++ if (~ps2_clk_s) m1_next_state <= m1_tx_clk_l; ++ else m1_next_state <= m1_tx_first_wait_clk_l; ++ end ++ ++ m1_tx_wait_clk_h : ++ begin ++ enable_timer_5usec <= 1; ++ ps2_data_hi_z <= q[0]; ++ if (ps2_clk_s && timer_5usec_done) ++ m1_next_state <= m1_tx_rising_edge_marker; ++ else ++ m1_next_state <= m1_tx_wait_clk_h; ++ end ++ ++ m1_tx_rising_edge_marker : ++ begin ++ ps2_data_hi_z <= q[0]; ++ m1_next_state <= m1_tx_clk_h; ++ end ++ ++ m1_tx_clk_h : ++ begin ++ ps2_data_hi_z <= q[0]; ++ if (tx_shifting_done) m1_next_state <= m1_tx_wait_keyboard_ack; ++ else if (~ps2_clk_s) m1_next_state <= m1_tx_clk_l; ++ else m1_next_state <= m1_tx_clk_h; ++ end ++ ++ m1_tx_clk_l : ++ begin ++ ps2_data_hi_z <= q[0]; ++ if (ps2_clk_s) m1_next_state <= m1_tx_wait_clk_h; ++ else m1_next_state <= m1_tx_clk_l; ++ end ++ ++ m1_tx_wait_keyboard_ack : ++ begin ++ if (~ps2_clk_s && ps2_data_s) ++ m1_next_state <= m1_tx_error_no_keyboard_ack; ++ else if (~ps2_clk_s && ~ps2_data_s) ++ m1_next_state <= m1_tx_done_recovery; ++ else m1_next_state <= m1_tx_wait_keyboard_ack; ++ end ++ ++ m1_tx_done_recovery : ++ begin ++ if (ps2_clk_s && ps2_data_s) m1_next_state <= m1_rx_clk_h; ++ else m1_next_state <= m1_tx_done_recovery; ++ end ++ ++ m1_tx_error_no_keyboard_ack : ++ begin ++ tx_error_no_keyboard_ack <= 1; ++ if (ps2_clk_s && ps2_data_s) m1_next_state <= m1_rx_clk_h; ++ else m1_next_state <= m1_tx_error_no_keyboard_ack; ++ end ++ ++ default : m1_next_state <= m1_rx_clk_h; ++ endcase ++end ++ ++// State register ++always @(posedge clk) ++begin : m2_state_register ++ if (reset) m2_state <= m2_rx_data_ready_ack; ++ else m2_state <= m2_next_state; ++end ++ ++// State transition logic ++always @(m2_state or rx_output_strobe or rx_read) ++begin : m2_state_logic ++ case (m2_state) ++ m2_rx_data_ready_ack: ++ begin ++ rx_data_ready <= 1'b0; ++ if (rx_output_strobe) m2_next_state <= m2_rx_data_ready; ++ else m2_next_state <= m2_rx_data_ready_ack; ++ end ++ m2_rx_data_ready: ++ begin ++ rx_data_ready <= 1'b1; ++ if (rx_read) m2_next_state <= m2_rx_data_ready_ack; ++ else m2_next_state <= m2_rx_data_ready; ++ end ++ default : m2_next_state <= m2_rx_data_ready_ack; ++ endcase ++end ++ ++// This is the bit counter ++always @(posedge clk) ++begin ++ if ( reset ++ || rx_shifting_done ++ || (m1_state == m1_tx_wait_keyboard_ack) // After tx is done. ++ ) bit_count <= 0; // normal reset ++ else if (timer_60usec_done ++ && (m1_state == m1_rx_clk_h) ++ && (ps2_clk_s) ++ ) bit_count <= 0; // rx watchdog timer reset ++ else if ( (m1_state == m1_rx_falling_edge_marker) // increment for rx ++ ||(m1_state == m1_tx_rising_edge_marker) // increment for tx ++ ) ++ bit_count <= bit_count + 1; ++end ++// This signal is high for one clock at the end of the timer count. ++assign rx_shifting_done = (bit_count == `TOTAL_BITS); ++assign tx_shifting_done = (bit_count == `TOTAL_BITS-1); ++ ++// This is the signal which enables loading of the shift register. ++// It also indicates "ack" to the device writing to the transmitter. ++assign tx_write_ack_o = ( (tx_write && (m1_state == m1_rx_clk_h)) ++ ||(tx_write && (m1_state == m1_rx_clk_l)) ++ ); ++ ++// This is the ODD parity bit for the transmitted word. ++assign tx_parity_bit = ~^tx_data; ++ ++// This is the shift register ++always @(posedge clk) ++begin ++ if (reset) q <= 0; ++ else if (tx_write_ack_o) q <= {1'b1,tx_parity_bit,tx_data,1'b0}; ++ else if ( (m1_state == m1_rx_falling_edge_marker) ++ ||(m1_state == m1_tx_rising_edge_marker) ) ++ q <= {ps2_data_s,q[`TOTAL_BITS-1:1]}; ++end ++ ++// This is the 60usec timer counter ++always @(posedge clk) ++begin ++ if (~enable_timer_60usec) timer_60usec_count <= 0; ++ else if (~timer_60usec_done) timer_60usec_count <= timer_60usec_count + 1; ++end ++assign timer_60usec_done = (timer_60usec_count == (TIMER_60USEC_VALUE_PP - 1)); ++ ++// This is the 5usec timer counter ++always @(posedge clk) ++begin ++ if (~enable_timer_5usec) timer_5usec_count <= 0; ++ else if (~timer_5usec_done) timer_5usec_count <= timer_5usec_count + 1; ++end ++assign timer_5usec_done = (timer_5usec_count == TIMER_5USEC_VALUE_PP - 1); ++ ++ ++// Create the signals which indicate special scan codes received. ++// These are the "unlatched versions." ++`ifdef PS2_TRAP_EXTENDED ++assign extended = (q[8:1] == `EXTEND_CODE) && rx_shifting_done && translate ; ++`else ++assign extended = 1'b0 ; ++`endif ++assign released = (q[8:1] == `RELEASE_CODE) && rx_shifting_done && translate ; ++ ++// Store the special scan code status bits ++// Not the final output, but an intermediate storage place, ++// until the entire set of output data can be assembled. ++always @(posedge clk) ++begin ++ if (reset || rx_output_event) ++ begin ++ hold_extended <= 0; ++ hold_released <= 0; ++ end ++ else ++ begin ++ if (rx_shifting_done && extended) hold_extended <= 1; ++ if (rx_shifting_done && released) hold_released <= 1; ++ end ++end ++ ++ ++// These bits contain the status of the two shift keys ++always @(posedge clk) ++begin ++ if (reset) left_shift_key <= 0; ++ else if ((q[8:1] == `LEFT_SHIFT) && rx_shifting_done && ~hold_released) ++ left_shift_key <= 1; ++ else if ((q[8:1] == `LEFT_SHIFT) && rx_shifting_done && hold_released) ++ left_shift_key <= 0; ++end ++ ++always @(posedge clk) ++begin ++ if (reset) right_shift_key <= 0; ++ else if ((q[8:1] == `RIGHT_SHIFT) && rx_shifting_done && ~hold_released) ++ right_shift_key <= 1; ++ else if ((q[8:1] == `RIGHT_SHIFT) && rx_shifting_done && hold_released) ++ right_shift_key <= 0; ++end ++ ++assign rx_shift_key_on = left_shift_key || right_shift_key; ++ ++// Output the special scan code flags, the scan code and the ascii ++always @(posedge clk) ++begin ++ if (reset) ++ begin ++ rx_extended <= 0; ++ rx_released <= 0; ++ rx_scan_code <= 0; ++ rx_ascii <= 0; ++ end ++ else if (rx_output_strobe) ++ begin ++ rx_extended <= hold_extended; ++ rx_released <= hold_released; ++ rx_scan_code <= q[8:1]; ++ rx_ascii <= ascii; ++ end ++end ++ ++// Store the final rx output data only when all extend and release codes ++// are received and the next (actual key) scan code is also ready. ++// (the presence of rx_extended or rx_released refers to the ++// the current latest scan code received, not the previously latched flags.) ++assign rx_output_event = (rx_shifting_done ++ && ~extended ++ && ~released ++ ); ++ ++assign rx_output_strobe = (rx_shifting_done ++ && ~extended ++ && ~released ++ && ( (TRAP_SHIFT_KEYS_PP == 0) ++ || ( (q[8:1] != `RIGHT_SHIFT) ++ &&(q[8:1] != `LEFT_SHIFT) ++ ) ++ ) ++ ); ++ ++// This part translates the scan code into an ASCII value... ++// Only the ASCII codes which I considered important have been included. ++// if you want more, just add the appropriate case statement lines... ++// (You will need to know the keyboard scan codes you wish to assign.) ++// The entries are listed in ascending order of ASCII value. ++assign shift_key_plus_code = {3'b0,rx_shift_key_on,q[8:1]}; ++always @(shift_key_plus_code) ++begin ++ casez (shift_key_plus_code) ++ 12'h?66 : ascii <= 8'h08; // Backspace ("backspace" key) ++ 12'h?0d : ascii <= 8'h09; // Horizontal Tab ++ 12'h?5a : ascii <= 8'h0d; // Carriage return ("enter" key) ++ 12'h?76 : ascii <= 8'h1b; // Escape ("esc" key) ++ 12'h?29 : ascii <= 8'h20; // Space ++ 12'h116 : ascii <= 8'h21; // ! ++ 12'h152 : ascii <= 8'h22; // " ++ 12'h126 : ascii <= 8'h23; // # ++ 12'h125 : ascii <= 8'h24; // $ ++ 12'h12e : ascii <= 8'h25; // % ++ 12'h13d : ascii <= 8'h26; // & ++ 12'h052 : ascii <= 8'h27; // ' ++ 12'h146 : ascii <= 8'h28; // ( ++ 12'h145 : ascii <= 8'h29; // ) ++ 12'h13e : ascii <= 8'h2a; // * ++ 12'h155 : ascii <= 8'h2b; // + ++ 12'h041 : ascii <= 8'h2c; // , ++ 12'h04e : ascii <= 8'h2d; // - ++ 12'h049 : ascii <= 8'h2e; // . ++ 12'h04a : ascii <= 8'h2f; // / ++ 12'h045 : ascii <= 8'h30; // 0 ++ 12'h016 : ascii <= 8'h31; // 1 ++ 12'h01e : ascii <= 8'h32; // 2 ++ 12'h026 : ascii <= 8'h33; // 3 ++ 12'h025 : ascii <= 8'h34; // 4 ++ 12'h02e : ascii <= 8'h35; // 5 ++ 12'h036 : ascii <= 8'h36; // 6 ++ 12'h03d : ascii <= 8'h37; // 7 ++ 12'h03e : ascii <= 8'h38; // 8 ++ 12'h046 : ascii <= 8'h39; // 9 ++ 12'h14c : ascii <= 8'h3a; // : ++ 12'h04c : ascii <= 8'h3b; // ; ++ 12'h141 : ascii <= 8'h3c; // < ++ 12'h055 : ascii <= 8'h3d; // = ++ 12'h149 : ascii <= 8'h3e; // > ++ 12'h14a : ascii <= 8'h3f; // ? ++ 12'h11e : ascii <= 8'h40; // @ ++ 12'h11c : ascii <= 8'h41; // A ++ 12'h132 : ascii <= 8'h42; // B ++ 12'h121 : ascii <= 8'h43; // C ++ 12'h123 : ascii <= 8'h44; // D ++ 12'h124 : ascii <= 8'h45; // E ++ 12'h12b : ascii <= 8'h46; // F ++ 12'h134 : ascii <= 8'h47; // G ++ 12'h133 : ascii <= 8'h48; // H ++ 12'h143 : ascii <= 8'h49; // I ++ 12'h13b : ascii <= 8'h4a; // J ++ 12'h142 : ascii <= 8'h4b; // K ++ 12'h14b : ascii <= 8'h4c; // L ++ 12'h13a : ascii <= 8'h4d; // M ++ 12'h131 : ascii <= 8'h4e; // N ++ 12'h144 : ascii <= 8'h4f; // O ++ 12'h14d : ascii <= 8'h50; // P ++ 12'h115 : ascii <= 8'h51; // Q ++ 12'h12d : ascii <= 8'h52; // R ++ 12'h11b : ascii <= 8'h53; // S ++ 12'h12c : ascii <= 8'h54; // T ++ 12'h13c : ascii <= 8'h55; // U ++ 12'h12a : ascii <= 8'h56; // V ++ 12'h11d : ascii <= 8'h57; // W ++ 12'h122 : ascii <= 8'h58; // X ++ 12'h135 : ascii <= 8'h59; // Y ++ 12'h11a : ascii <= 8'h5a; // Z ++ 12'h054 : ascii <= 8'h5b; // [ ++ 12'h05d : ascii <= 8'h5c; // \ ++ 12'h05b : ascii <= 8'h5d; // ] ++ 12'h136 : ascii <= 8'h5e; // ^ ++ 12'h14e : ascii <= 8'h5f; // _ ++ 12'h00e : ascii <= 8'h60; // ` ++ 12'h01c : ascii <= 8'h61; // a ++ 12'h032 : ascii <= 8'h62; // b ++ 12'h021 : ascii <= 8'h63; // c ++ 12'h023 : ascii <= 8'h64; // d ++ 12'h024 : ascii <= 8'h65; // e ++ 12'h02b : ascii <= 8'h66; // f ++ 12'h034 : ascii <= 8'h67; // g ++ 12'h033 : ascii <= 8'h68; // h ++ 12'h043 : ascii <= 8'h69; // i ++ 12'h03b : ascii <= 8'h6a; // j ++ 12'h042 : ascii <= 8'h6b; // k ++ 12'h04b : ascii <= 8'h6c; // l ++ 12'h03a : ascii <= 8'h6d; // m ++ 12'h031 : ascii <= 8'h6e; // n ++ 12'h044 : ascii <= 8'h6f; // o ++ 12'h04d : ascii <= 8'h70; // p ++ 12'h015 : ascii <= 8'h71; // q ++ 12'h02d : ascii <= 8'h72; // r ++ 12'h01b : ascii <= 8'h73; // s ++ 12'h02c : ascii <= 8'h74; // t ++ 12'h03c : ascii <= 8'h75; // u ++ 12'h02a : ascii <= 8'h76; // v ++ 12'h01d : ascii <= 8'h77; // w ++ 12'h022 : ascii <= 8'h78; // x ++ 12'h035 : ascii <= 8'h79; // y ++ 12'h01a : ascii <= 8'h7a; // z ++ 12'h154 : ascii <= 8'h7b; // { ++ 12'h15d : ascii <= 8'h7c; // | ++ 12'h15b : ascii <= 8'h7d; // } ++ 12'h10e : ascii <= 8'h7e; // ~ ++ 12'h?71 : ascii <= 8'h7f; // (Delete OR DEL on numeric keypad) ++ default : ascii <= 8'h2e; // '.' used for unlisted characters. ++ endcase ++end ++ ++ ++endmodule ++ ++//`undefine TOTAL_BITS ++//`undefine EXTEND_CODE ++//`undefine RELEASE_CODE ++//`undefine LEFT_SHIFT ++//`undefine RIGHT_SHIFT ++ -- cgit v1.2.3