OpenCores
URL https://opencores.org/ocsvn/keyboardcontroller/keyboardcontroller/trunk

Subversion Repositories keyboardcontroller

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 2 to Rev 3
    Reverse comparison

Rev 2 → Rev 3

/tags/KEYB_CON_0_01/summery.txt
0,0 → 1,16
Device utilization summary:
---------------------------
 
Selected Device : 3s1000ft256-4
 
Number of Slices: 2407 out of 7680 31%
Number of Slice Flip Flops: 2109 out of 15360 13%
Number of 4 input LUTs: 3188 out of 15360 20%
Number of bonded IOBs: 95 out of 173 54%
Number of BRAMs: 10 out of 24 41%
Number of MULT18X18s: 3 out of 24 12%
Number of GCLKs: 2 out of 8 25%
Number of DCMs: 1 out of 4 25%
 
 
=========================================================================
/tags/KEYB_CON_0_01/wouter_keyb.vhd
0,0 → 1,432
------------------------------------------------------------------------------
-- wouter_keyb.vhd - entity/architecture pair
------------------------------------------------------------------------------
-- IMPORTANT:
-- DO NOT MODIFY THIS FILE EXCEPT IN THE DESIGNATED SECTIONS.
--
-- SEARCH FOR --USER TO DETERMINE WHERE CHANGES ARE ALLOWED.
--
-- TYPICALLY, THE ONLY ACCEPTABLE CHANGES INVOLVE ADDING NEW
-- PORTS AND GENERICS THAT GET PASSED THROUGH TO THE INSTANTIATION
-- OF THE USER_LOGIC ENTITY.
------------------------------------------------------------------------------
--
-- ***************************************************************************
-- ** Copyright (c) 1995-2004 Xilinx, Inc. All rights reserved. **
-- ** **
-- ** Xilinx, Inc. **
-- ** XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" **
-- ** AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND **
-- ** SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, **
-- ** OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, **
-- ** APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION **
-- ** THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, **
-- ** AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE **
-- ** FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY **
-- ** WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE **
-- ** IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR **
-- ** REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF **
-- ** INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS **
-- ** FOR A PARTICULAR PURPOSE. **
-- ** **
-- ** YOU MAY COPY AND MODIFY THESE FILES FOR YOUR OWN INTERNAL USE SOLELY **
-- ** WITH XILINX PROGRAMMABLE LOGIC DEVICES AND XILINX EDK SYSTEM OR **
-- ** CREATE IP MODULES SOLELY FOR XILINX PROGRAMMABLE LOGIC DEVICES AND **
-- ** XILINX EDK SYSTEM. NO RIGHTS ARE GRANTED TO DISTRIBUTE ANY FILES **
-- ** UNLESS THEY ARE DISTRIBUTED IN XILINX PROGRAMMABLE LOGIC DEVICES. **
-- ** **
-- ***************************************************************************
--
------------------------------------------------------------------------------
-- Filename: wouter_keyb.vhd
-- Version: 1.00.a
-- Description: Top level design, instantiates IPIF and user logic.
-- Date: Wed Jun 15 10:21:28 2005 (by Create and Import Peripheral Wizard)
-- VHDL-Standard: VHDL'93
------------------------------------------------------------------------------
-- Naming Conventions:
-- active low signals: "*_n"
-- clock signals: "clk", "clk_div#", "clk_#x"
-- reset signals: "rst", "rst_n"
-- generics: "C_*"
-- user defined types: "*_TYPE"
-- state machine next state: "*_ns"
-- state machine current state: "*_cs"
-- combinatorial signals: "*_com"
-- pipelined or register delay signals: "*_d#"
-- counter signals: "*cnt*"
-- clock enable signals: "*_ce"
-- internal version of output port: "*_i"
-- device pins: "*_pin"
-- ports: "- Names begin with Uppercase"
-- processes: "*_PROCESS"
-- component instantiations: "<ENTITY_>I_<#|FUNC>"
------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
 
library proc_common_v2_00_a;
use proc_common_v2_00_a.proc_common_pkg.all;
use proc_common_v2_00_a.ipif_pkg.all;
 
library opb_ipif_v3_01_a;
use opb_ipif_v3_01_a.all;
 
--library wouter_keyb_v1_00_a;
--use wouter_keyb_v1_00_a.all;
library work;
use work.Constants.all;
 
------------------------------------------------------------------------------
-- Definition of Generics:
-- C_BASEADDR -- User logic base address
-- C_HIGHADDR -- User logic high address
-- C_OPB_AWIDTH -- OPB address bus width
-- C_OPB_DWIDTH -- OPB data bus width
-- C_FAMILY -- Target FPGA architecture
--
-- Definition of Ports:
-- OPB_Clk -- OPB Clock
-- OPB_Rst -- OPB Reset
-- Sl_DBus -- Slave data bus
-- Sl_errAck -- Slave error acknowledge
-- Sl_retry -- Slave retry
-- Sl_toutSup -- Slave timeout suppress
-- Sl_xferAck -- Slave transfer acknowledge
-- OPB_ABus -- OPB address bus
-- OPB_BE -- OPB byte enable
-- OPB_DBus -- OPB data bus
-- OPB_RNW -- OPB read/not write
-- OPB_select -- OPB select
-- OPB_seqAddr -- OPB sequential address
--
--------------------------------------------------------------------------------
-- Entity section
--------------------------------------------------------------------------------
 
entity wouter_keyb is
generic
(
-- ADD USER GENERICS BELOW THIS LINE ---------------
--USER generics added here
-- ADD USER GENERICS ABOVE THIS LINE ---------------
 
-- DO NOT EDIT BELOW THIS LINE ---------------------
-- Bus protocol parameters, do not add to or delete
C_BASEADDR : std_logic_vector := X"00000000";
C_HIGHADDR : std_logic_vector := X"0000FFFF";
C_OPB_AWIDTH : integer := 32;
C_OPB_DWIDTH : integer := 32;
C_FAMILY : string := "virtex2p"
-- DO NOT EDIT ABOVE THIS LINE ---------------------
);
port
(
-- ADD USER PORTS BELOW THIS LINE ------------------
keyb_interrupt : out std_logic;
keyb_clk_out : out std_logic;
keyb_cols : in col;
keyb_rows : out row;
keyb_up : out std_logic;
 
-- ADD USER PORTS ABOVE THIS LINE ------------------
 
-- DO NOT EDIT BELOW THIS LINE ---------------------
-- Bus protocol ports, do not add to or delete
OPB_Clk : in std_logic;
OPB_Rst : in std_logic;
Sl_DBus : out std_logic_vector(0 to C_OPB_DWIDTH-1);
Sl_errAck : out std_logic;
Sl_retry : out std_logic;
Sl_toutSup : out std_logic;
Sl_xferAck : out std_logic;
OPB_ABus : in std_logic_vector(0 to C_OPB_AWIDTH-1);
OPB_BE : in std_logic_vector(0 to C_OPB_DWIDTH/8-1);
OPB_DBus : in std_logic_vector(0 to C_OPB_DWIDTH-1);
OPB_RNW : in std_logic;
OPB_select : in std_logic;
OPB_seqAddr : in std_logic
-- DO NOT EDIT ABOVE THIS LINE ---------------------
);
 
attribute MIN_SIZE : string;
attribute MIN_SIZE of C_BASEADDR : constant is "0x100";
 
attribute SIGIS : string;
attribute SIGIS of OPB_Clk : signal is "Clk";
attribute SIGIS of OPB_Rst : signal is "Rst";
 
end entity wouter_keyb;
 
--------------------------------------------------------------------------------
-- Architecture section
--------------------------------------------------------------------------------
 
architecture IMP of wouter_keyb is
 
----------------------------------------
-- Constant: array of address range identifiers
----------------------------------------
constant ARD_ID_ARRAY : INTEGER_ARRAY_TYPE :=
(
0 => USER_00 -- user logic S/W register address space
);
 
----------------------------------------
-- Constant: array of address pairs for each address range
----------------------------------------
constant ZERO_ADDR_PAD : std_logic_vector(0 to 64-C_OPB_AWIDTH-1) := (others => '0');
 
constant USER_BASEADDR : std_logic_vector := C_BASEADDR;
constant USER_HIGHADDR : std_logic_vector := C_HIGHADDR;
 
constant ARD_ADDR_RANGE_ARRAY : SLV64_ARRAY_TYPE :=
(
ZERO_ADDR_PAD & USER_BASEADDR, -- user logic base address
ZERO_ADDR_PAD & USER_HIGHADDR -- user logic high address
);
 
----------------------------------------
-- Constant: array of data widths for each target address range
----------------------------------------
constant USER_DWIDTH : integer := 32;
 
constant ARD_DWIDTH_ARRAY : INTEGER_ARRAY_TYPE :=
(
0 => USER_DWIDTH -- user logic data width
);
 
----------------------------------------
-- Constant: array of desired number of chip enables for each address range
----------------------------------------
constant USER_NUM_CE : integer := 1;
 
constant ARD_NUM_CE_ARRAY : INTEGER_ARRAY_TYPE :=
(
0 => pad_power2(USER_NUM_CE) -- user logic number of CEs
);
 
----------------------------------------
-- Constant: array of unique properties for each address range
----------------------------------------
constant ARD_DEPENDENT_PROPS_ARRAY : DEPENDENT_PROPS_ARRAY_TYPE :=
(
0 => (others => 0) -- user logic slave space dependent properties (none defined)
);
 
----------------------------------------
-- Constant: pipeline mode
-- 1 = include OPB-In pipeline registers
-- 2 = include IP pipeline registers
-- 3 = include OPB-In and IP pipeline registers
-- 4 = include OPB-Out pipeline registers
-- 5 = include OPB-In and OPB-Out pipeline registers
-- 6 = include IP and OPB-Out pipeline registers
-- 7 = include OPB-In, IP, and OPB-Out pipeline registers
-- Note:
-- only mode 4, 5, 7 are supported for this release
----------------------------------------
constant PIPELINE_MODEL : integer := 5;
 
----------------------------------------
-- Constant: user core ID code
----------------------------------------
constant DEV_BLK_ID : integer := 0;
 
----------------------------------------
-- Constant: enable MIR/Reset register
----------------------------------------
constant DEV_MIR_ENABLE : integer := 0;
 
----------------------------------------
-- Constant: array of IP interrupt mode
-- 1 = Active-high interrupt condition
-- 2 = Active-low interrupt condition
-- 3 = Active-high pulse interrupt event
-- 4 = Active-low pulse interrupt event
-- 5 = Positive-edge interrupt event
-- 6 = Negative-edge interrupt event
----------------------------------------
constant IP_INTR_MODE_ARRAY : INTEGER_ARRAY_TYPE :=
(
0 => 0 -- not used
);
 
----------------------------------------
-- Constant: enable device burst
----------------------------------------
constant DEV_BURST_ENABLE : integer := 0;
 
----------------------------------------
-- Constant: include address counter for burst transfers
----------------------------------------
constant INCLUDE_ADDR_CNTR : integer := 0;
 
----------------------------------------
-- Constant: include write buffer that decouples OPB and IPIC write transactions
----------------------------------------
constant INCLUDE_WR_BUF : integer := 0;
 
----------------------------------------
-- Constant: index for CS/CE
----------------------------------------
constant USER00_CS_INDEX : integer := get_id_index(ARD_ID_ARRAY, USER_00);
 
constant USER00_CE_INDEX : integer := calc_start_ce_index(ARD_NUM_CE_ARRAY, USER00_CS_INDEX);
 
----------------------------------------
-- IP Interconnect (IPIC) signal declarations -- do not delete
----------------------------------------
signal iBus2IP_RdCE : std_logic_vector(0 to calc_num_ce(ARD_NUM_CE_ARRAY)-1);
signal iBus2IP_WrCE : std_logic_vector(0 to calc_num_ce(ARD_NUM_CE_ARRAY)-1);
signal iBus2IP_Data : std_logic_vector(0 to C_OPB_DWIDTH-1);
signal iBus2IP_BE : std_logic_vector(0 to C_OPB_DWIDTH/8-1);
signal iIP2Bus_Data : std_logic_vector(0 to C_OPB_DWIDTH-1) := (others => '0');
signal iIP2Bus_Ack : std_logic := '0';
signal iIP2Bus_Error : std_logic := '0';
signal iIP2Bus_Retry : std_logic := '0';
signal iIP2Bus_ToutSup : std_logic := '0';
signal ZERO_IP2Bus_PostedWrInh : std_logic_vector(0 to ARD_ID_ARRAY'length-1) := (others => '0'); -- work around for XST not taking (others => '0') in port mapping
signal ZERO_IP2RFIFO_Data : std_logic_vector(0 to 31) := (others => '0'); -- work around for XST not taking (others => '0') in port mapping
signal ZERO_WFIFO2IP_Data : std_logic_vector(0 to 31) := (others => '0'); -- work around for XST not taking (others => '0') in port mapping
signal ZERO_IP2Bus_IntrEvent : std_logic_vector(0 to IP_INTR_MODE_ARRAY'length-1) := (others => '0'); -- work around for XST not taking (others => '0') in port mapping
signal iBus2IP_Clk : std_logic;
signal iBus2IP_Reset : std_logic;
signal uBus2IP_Data : std_logic_vector(0 to USER_DWIDTH-1);
signal uBus2IP_BE : std_logic_vector(0 to USER_DWIDTH/8-1);
signal uBus2IP_RdCE : std_logic_vector(0 to USER_NUM_CE-1);
signal uBus2IP_WrCE : std_logic_vector(0 to USER_NUM_CE-1);
signal uIP2Bus_Data : std_logic_vector(0 to USER_DWIDTH-1);
 
begin
 
----------------------------------------
-- instantiate the OPB IPIF
----------------------------------------
OPB_IPIF_I : entity opb_ipif_v3_01_a.opb_ipif
generic map
(
C_ARD_ID_ARRAY => ARD_ID_ARRAY,
C_ARD_ADDR_RANGE_ARRAY => ARD_ADDR_RANGE_ARRAY,
C_ARD_DWIDTH_ARRAY => ARD_DWIDTH_ARRAY,
C_ARD_NUM_CE_ARRAY => ARD_NUM_CE_ARRAY,
C_ARD_DEPENDENT_PROPS_ARRAY => ARD_DEPENDENT_PROPS_ARRAY,
C_PIPELINE_MODEL => PIPELINE_MODEL,
C_DEV_BLK_ID => DEV_BLK_ID,
C_DEV_MIR_ENABLE => DEV_MIR_ENABLE,
C_OPB_AWIDTH => C_OPB_AWIDTH,
C_OPB_DWIDTH => C_OPB_DWIDTH,
C_FAMILY => C_FAMILY,
C_IP_INTR_MODE_ARRAY => IP_INTR_MODE_ARRAY,
C_DEV_BURST_ENABLE => DEV_BURST_ENABLE,
C_INCLUDE_ADDR_CNTR => INCLUDE_ADDR_CNTR,
C_INCLUDE_WR_BUF => INCLUDE_WR_BUF
)
port map
(
OPB_select => OPB_select,
OPB_DBus => OPB_DBus,
OPB_ABus => OPB_ABus,
OPB_BE => OPB_BE,
OPB_RNW => OPB_RNW,
OPB_seqAddr => OPB_seqAddr,
Sln_DBus => Sl_DBus,
Sln_xferAck => Sl_xferAck,
Sln_errAck => Sl_errAck,
Sln_retry => Sl_retry,
Sln_toutSup => Sl_toutSup,
Bus2IP_CS => open,
Bus2IP_CE => open,
Bus2IP_RdCE => iBus2IP_RdCE,
Bus2IP_WrCE => iBus2IP_WrCE,
Bus2IP_Data => iBus2IP_Data,
Bus2IP_Addr => open,
Bus2IP_AddrValid => open,
Bus2IP_BE => iBus2IP_BE,
Bus2IP_RNW => open,
Bus2IP_Burst => open,
IP2Bus_Data => iIP2Bus_Data,
IP2Bus_Ack => iIP2Bus_Ack,
IP2Bus_AddrAck => '0',
IP2Bus_Error => iIP2Bus_Error,
IP2Bus_Retry => iIP2Bus_Retry,
IP2Bus_ToutSup => iIP2Bus_ToutSup,
IP2Bus_PostedWrInh => ZERO_IP2Bus_PostedWrInh,
IP2RFIFO_Data => ZERO_IP2RFIFO_Data,
IP2RFIFO_WrMark => '0',
IP2RFIFO_WrRelease => '0',
IP2RFIFO_WrReq => '0',
IP2RFIFO_WrRestore => '0',
RFIFO2IP_AlmostFull => open,
RFIFO2IP_Full => open,
RFIFO2IP_Vacancy => open,
RFIFO2IP_WrAck => open,
IP2WFIFO_RdMark => '0',
IP2WFIFO_RdRelease => '0',
IP2WFIFO_RdReq => '0',
IP2WFIFO_RdRestore => '0',
WFIFO2IP_AlmostEmpty => open,
WFIFO2IP_Data => ZERO_WFIFO2IP_Data,
WFIFO2IP_Empty => open,
WFIFO2IP_Occupancy => open,
WFIFO2IP_RdAck => open,
IP2Bus_IntrEvent => ZERO_IP2Bus_IntrEvent,
IP2INTC_Irpt => open,
Freeze => '0',
Bus2IP_Freeze => open,
OPB_Clk => OPB_Clk,
Bus2IP_Clk => iBus2IP_Clk,
IP2Bus_Clk => '0',
Reset => OPB_Rst,
Bus2IP_Reset => iBus2IP_Reset
);
 
----------------------------------------
-- instantiate the User Logic
----------------------------------------
USER_LOGIC_I : entity wouter_keyb_v1_00_a.user_logic
generic map
(
-- MAP USER GENERICS BELOW THIS LINE ---------------
--USER generics mapped here
-- MAP USER GENERICS ABOVE THIS LINE ---------------
 
C_DWIDTH => USER_DWIDTH,
C_NUM_CE => USER_NUM_CE
)
port map
(
-- MAP USER PORTS BELOW THIS LINE ------------------
keyb_interrupt,
keyb_clk_out,
keyb_cols,
keyb_rows,
keyb_up,
-- MAP USER PORTS ABOVE THIS LINE ------------------
 
Bus2IP_Clk => iBus2IP_Clk,
Bus2IP_Reset => iBus2IP_Reset,
Bus2IP_Data => uBus2IP_Data,
Bus2IP_BE => uBus2IP_BE,
Bus2IP_RdCE => uBus2IP_RdCE,
Bus2IP_WrCE => uBus2IP_WrCE,
IP2Bus_Data => uIP2Bus_Data,
IP2Bus_Ack => iIP2Bus_Ack,
IP2Bus_Retry => iIP2Bus_Retry,
IP2Bus_Error => iIP2Bus_Error,
IP2Bus_ToutSup => iIP2Bus_ToutSup
);
 
----------------------------------------
-- hooking up signal slicing
----------------------------------------
uBus2IP_BE <= iBus2IP_BE(0 to USER_DWIDTH/8-1);
uBus2IP_Data <= iBus2IP_Data(0 to USER_DWIDTH-1);
uBus2IP_RdCE <= iBus2IP_RdCE(USER00_CE_INDEX to USER00_CE_INDEX+USER_NUM_CE-1);
uBus2IP_WrCE <= iBus2IP_WrCE(USER00_CE_INDEX to USER00_CE_INDEX+USER_NUM_CE-1);
iIP2Bus_Data(0 to USER_DWIDTH-1) <= uIP2Bus_Data;
 
end IMP;
/tags/KEYB_CON_0_01/Strober.vhd
0,0 → 1,67
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.Constants.all;
entity Strober is
port (reset, clk : in std_logic;
strobe : in std_logic;
sample : in std_logic;
env_col : in col;
env_row : out row;
sample_col : out col; --rows and cols to be analysed
sample_row_number : out row_number
);
end Strober;
 
architecture Strober_arc of Strober is
 
function decode_row(inp: row_number) return row is
variable rowstrobe : row;
begin
case inp is
when 11 => rowstrobe := "011111111111";
when 10 => rowstrobe := "101111111111";
when 9 => rowstrobe := "110111111111";
when 8 => rowstrobe := "111011111111";
when 7 => rowstrobe := "111101111111";
when 6 => rowstrobe := "111110111111";
when 5 => rowstrobe := "111111011111";
when 4 => rowstrobe := "111111101111";
when 3 => rowstrobe := "111111110111";
when 2 => rowstrobe := "111111111011";
when 1 => rowstrobe := "111111111101";
when 0 => rowstrobe := "111111111110";
when others => rowstrobe := "111111111111";
end case;
return rowstrobe;
end decode_row;
begin
strober: process
variable row_counter : integer;
begin
wait until rising_edge(clk);
if (reset = '1') then
env_row <= "111111111111";
row_counter := 0;
elsif (strobe = '1') then
if (row_counter < number_of_cols-1) then
row_counter := row_counter + 1;
elsif(row_counter = number_of_cols-1)then
row_counter := 0;
end if;
env_row <= decode_row(row_counter);
elsif (sample ='1') then --first sample
sample_row_number <= row_counter;
sample_col <= not env_col;
end if;
end process;
end strober_arc;
 
 
/tags/KEYB_CON_0_01/Keyboard_controller.vhd
0,0 → 1,125
-----------------------------------------------------------------------------------------------
--
-- Keyboard controller entity
--
-- The controller scans the columns, cols, by making a different column logic-0
-- therefor the inputs have to be pull-up high. It processes the input, rows, and
-- the pressed key to a corresponding scancode and giving an interrupt
--
-- Author: Wouter Wiggers
-- Mail: w.a.wiggers@student.utwente.nl
--
------------------------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
use work.Constants.all;
entity Keyboard_controller is
port (reset, clk_in : in std_logic;
clk_out : out std_logic;
cols : in col;
rows : out row;
scan : out scancode;
interrupt : out std_logic
);
end Keyboard_controller;
 
architecture structure of Keyboard_controller is
component Strober
port (reset, clk : in std_logic;
strobe : in std_logic;
sample : in std_logic;
env_col : in col;
env_row : out row;
sample_col : out col;
sample_row_number : out row_number
);
end component;
component Analyser
port (reset, clk : in std_logic;
analyse : in std_logic;
store : in std_logic;
debounced : out std_logic;
keychanged : out std_logic;
released : out std_logic;
sample_col: in col;
sample_row_number : in row_number;
conv_col : out col_number;
conv_row : out row_number
);
end component;
component Producer
port (reset, clk: in std_logic;
produce : in std_logic;
released : in std_logic;
conv_col : in col_number;
conv_row : in row_number;
scanc : out scancode;
interrupt : out std_logic
);
end component;
component FSM
port (reset, clk : in std_logic;
strobe : out std_logic;
sample : out std_logic;
analyse : out std_logic;
store : out std_logic;
produce : out std_logic;
release : out std_logic;
debounced : in std_logic;
keychanged : in std_logic; --keychange found
keyreleased : in std_logic
);
end component;
 
signal stb: std_logic;
signal str: std_logic;
signal sam: std_logic;
signal ana: std_logic;
signal pro: std_logic;
signal rel: std_logic;
signal deb: std_logic;
signal keyc: std_logic;
signal keyr: std_logic;
signal col_sample : col;
signal row_sample_number : row_number;
signal col_conv : col_number;
signal row_conv : row_number;
 
signal clk : std_logic;
begin
-- divide by 512
clockdiv: process
variable count : std_logic_vector(8 downto 0);
begin
wait until rising_edge(clk_in);
count := std_logic_vector(to_unsigned( (to_integer(unsigned(count)) + 1),9 ));
clk <= count(8);
end process;
 
clk_out <= clk;
strb: Strober port map (reset, clk, stb, sam, cols, rows, col_sample, row_sample_number);
 
analys: Analyser port map (reset, clk, ana, str, deb, keyc, keyr, col_sample, row_sample_number, col_conv, row_conv);
 
prod: Producer port map (reset, clk, pro, rel, col_conv, row_conv, scan, interrupt);
 
finsm: FSM port map (reset, clk, stb, sam, ana, str, pro, rel , deb, keyc, keyr);
 
end structure;
/tags/KEYB_CON_0_01/Producer.vhd
0,0 → 1,59
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_arith.sxt;
use work.Constants.all;
entity Producer is
port (reset, clk: in std_logic;
produce : in std_logic;
released : in std_logic;
conv_col : in col_number;
conv_row : in row_number;
scanc : out scancode;
interrupt : out std_logic
);
end Producer;
 
architecture Producer_arc of Producer is
 
signal next_scanc: std_logic_vector(scancode_width-1 downto 0);
 
begin
process(released, conv_row, conv_col)
variable index: natural range 0 to 93;
variable tmp : std_logic_vector(6 downto 0);
begin
--make address out of col and row number of the pressed/released key
tmp := std_logic_vector(to_unsigned(conv_row,4)) & std_logic_vector(to_unsigned(conv_col,3));
index := to_integer(unsigned(tmp));
--look-up scancode
next_scanc <= set1_scancodes_lut(index);
if (released='1') then
next_scanc(scancode_width-1)<='1'; --add 0x80 for keyrelease scancode
end if;
end process;
--put values in registers on next rising edge
process
begin
wait until rising_edge(clk);
if (reset='1') then
scanc <= "00000000";
interrupt <= '0';
elsif(produce = '1') then
scanc <= next_scanc;
interrupt <= '1';
else
interrupt <= '0';
end if;
end process;
end Producer_arc;
/tags/KEYB_CON_0_01/FSM.vhd
0,0 → 1,78
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.Constants.all;
entity FSM is
port (reset, clk : in std_logic;
strobe : out std_logic;
sample : out std_logic;
analyse : out std_logic;
store : out std_logic;
produce : out std_logic;
release : out std_logic;
debounced : in std_logic;
keychanged : in std_logic; --keychange found
keyreleased : in std_logic
);
end FSM;
 
architecture FSM_arc of FSM is
signal nState, cState : states;
begin
 
process
begin
wait until rising_edge(clk);
if( reset = '1' ) then
cState <= idle;
else
cState <= nState;
end if;
end process;
 
process(cState, debounced, keychanged, keyreleased)
begin
case cState is
 
when idle => nState <= strobing;
 
when strobing => nState <= sampling;
when sampling => nState <= analysing;
when analysing => if (debounced='1') then
nState <= storing;
else
nState <= analysing;
end if;
 
when storing => nState <= storing_stage2;
when storing_stage2 => if (keychanged='1' and keyreleased='0') then
nState <= producenormal;
elsif(keychanged='1' and keyreleased='1') then
nState <= producerelease;
elsif (keychanged='0') then
nState <= strobing;
end if;
when producenormal => nState <= strobing;
when producerelease => nState <= strobing;
when others => nState <= idle;
end case;
 
end process;
 
strobe <= cState(6);
sample <= cState(5);
analyse <= cState(4);
store <= cState(3);
produce <= cState(2);
release <= cState(1);
end FSM_arc;
/tags/KEYB_CON_0_01/user_logic.vhd
0,0 → 1,230
------------------------------------------------------------------------------
-- user_logic.vhd - entity/architecture pair
------------------------------------------------------------------------------
--
-- ***************************************************************************
-- ** Copyright (c) 1995-2004 Xilinx, Inc. All rights reserved. **
-- ** **
-- ** Xilinx, Inc. **
-- ** XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" **
-- ** AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND **
-- ** SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, **
-- ** OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, **
-- ** APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION **
-- ** THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, **
-- ** AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE **
-- ** FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY **
-- ** WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE **
-- ** IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR **
-- ** REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF **
-- ** INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS **
-- ** FOR A PARTICULAR PURPOSE. **
-- ** **
-- ** YOU MAY COPY AND MODIFY THESE FILES FOR YOUR OWN INTERNAL USE SOLELY **
-- ** WITH XILINX PROGRAMMABLE LOGIC DEVICES AND XILINX EDK SYSTEM OR **
-- ** CREATE IP MODULES SOLELY FOR XILINX PROGRAMMABLE LOGIC DEVICES AND **
-- ** XILINX EDK SYSTEM. NO RIGHTS ARE GRANTED TO DISTRIBUTE ANY FILES **
-- ** UNLESS THEY ARE DISTRIBUTED IN XILINX PROGRAMMABLE LOGIC DEVICES. **
-- ** **
-- ***************************************************************************
--
------------------------------------------------------------------------------
-- Filename: user_logic.vhd
-- Version: 1.00.a
-- Description: User logic module.
-- Date: Wed Jun 15 10:21:28 2005 (by Create and Import Peripheral Wizard)
-- VHDL-Standard: VHDL'93
------------------------------------------------------------------------------
-- Naming Conventions:
-- active low signals: "*_n"
-- clock signals: "clk", "clk_div#", "clk_#x"
-- reset signals: "rst", "rst_n"
-- generics: "C_*"
-- user defined types: "*_TYPE"
-- state machine next state: "*_ns"
-- state machine current state: "*_cs"
-- combinatorial signals: "*_com"
-- pipelined or register delay signals: "*_d#"
-- counter signals: "*cnt*"
-- clock enable signals: "*_ce"
-- internal version of output port: "*_i"
-- device pins: "*_pin"
-- ports: "- Names begin with Uppercase"
-- processes: "*_PROCESS"
-- component instantiations: "<ENTITY_>I_<#|FUNC>"
------------------------------------------------------------------------------
 
-- DO NOT EDIT BELOW THIS LINE --------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
 
 
library proc_common_v2_00_a;
use proc_common_v2_00_a.proc_common_pkg.all;
 
-- DO NOT EDIT ABOVE THIS LINE --------------------
 
--USER libraries added here
library wouter_keyb_v1_00_a;
use Constants.all;
--use Keyboard_controller;
------------------------------------------------------------------------------
-- Definition of Generics:
-- C_DWIDTH -- User logic data bus width
-- C_NUM_CE -- User logic chip enable bus width
--
-- Definition of Ports:
-- Bus2IP_Clk -- Bus to IP clock
-- Bus2IP_Reset -- Bus to IP reset
-- Bus2IP_Data -- Bus to IP data bus for user logic
-- Bus2IP_BE -- Bus to IP byte enables for user logic
-- Bus2IP_RdCE -- Bus to IP read chip enable for user logic
-- Bus2IP_WrCE -- Bus to IP write chip enable for user logic
-- IP2Bus_Data -- IP to Bus data bus for user logic
-- IP2Bus_Ack -- IP to Bus acknowledgement
-- IP2Bus_Retry -- IP to Bus retry response
-- IP2Bus_Error -- IP to Bus error response
-- IP2Bus_ToutSup -- IP to Bus timeout suppress
--
--------------------------------------------------------------------------------
-- Entity section
--------------------------------------------------------------------------------
 
entity user_logic is
generic
(
-- ADD USER GENERICS BELOW THIS LINE ---------------
--USER generics added here
-- ADD USER GENERICS ABOVE THIS LINE ---------------
 
-- DO NOT EDIT BELOW THIS LINE ---------------------
-- Bus protocol parameters, do not add to or delete
C_DWIDTH : integer := 32;
C_NUM_CE : integer := 1
-- DO NOT EDIT ABOVE THIS LINE ---------------------
);
port
(
-- ADD USER PORTS BELOW THIS LINE ------------------
keyb_interrupt : out std_logic;
keyb_clk_out : out std_logic;
keyb_cols : in col;
keyb_rows : out row;
keyb_up : out std_logic;
-- ADD USER PORTS ABOVE THIS LINE ------------------
 
-- DO NOT EDIT BELOW THIS LINE ---------------------
-- Bus protocol ports, do not add to or delete
Bus2IP_Clk : in std_logic;
Bus2IP_Reset : in std_logic;
Bus2IP_Data : in std_logic_vector(0 to C_DWIDTH-1);
Bus2IP_BE : in std_logic_vector(0 to C_DWIDTH/8-1);
Bus2IP_RdCE : in std_logic_vector(0 to C_NUM_CE-1);
Bus2IP_WrCE : in std_logic_vector(0 to C_NUM_CE-1);
IP2Bus_Data : out std_logic_vector(0 to C_DWIDTH-1);
IP2Bus_Ack : out std_logic;
IP2Bus_Retry : out std_logic;
IP2Bus_Error : out std_logic;
IP2Bus_ToutSup : out std_logic
-- DO NOT EDIT ABOVE THIS LINE ---------------------
);
end entity user_logic;
 
--------------------------------------------------------------------------------
-- Architecture section
--------------------------------------------------------------------------------
 
architecture IMP of user_logic is
 
--USER signal declarations added here, as needed for user logic
signal keyb_scan : scancode;
----------------------------------------
-- Signals for user logic slave model s/w accessible register example
----------------------------------------
signal slv_reg_write_select : std_logic_vector(0 to 0);
signal slv_reg_read_select : std_logic_vector(0 to 0);
signal slv_ip2bus_data : std_logic_vector(0 to C_DWIDTH-1);
signal slv_read_ack : std_logic;
signal slv_write_ack : std_logic;
signal bus_reset : std_logic;
 
component Keyboard_controller
port (reset, clk_in : in std_logic;
clk_out : out std_logic;
cols: in col;
rows: out row;
scan : out scancode;
interrupt : out std_logic
);
end component;
 
begin
keyb: Keyboard_controller port map (bus_reset, Bus2IP_Clk, keyb_clk_out, keyb_cols, keyb_rows, keyb_scan, keyb_interrupt);
--USER logic implementation added here
 
----------------------------------------
-- Example code to read/write user logic slave model s/w accessible registers
--
-- Note:
-- The example code presented here is to show you one way of reading/writing
-- software accessible registers implemented in the user logic slave model.
-- Each bit of the Bus2IP_WrCE/Bus2IP_RdCE signals is configured to correspond
-- to one software accessible register by the top level template. For example,
-- if you have four 32 bit software accessible registers in the user logic, you
-- are basically operating on the following memory mapped registers:
--
-- Bus2IP_WrCE or Memory Mapped
-- Bus2IP_RdCE Register
-- "1000" C_BASEADDR + 0x0
-- "0100" C_BASEADDR + 0x4
-- "0010" C_BASEADDR + 0x8
-- "0001" C_BASEADDR + 0xC
--
----------------------------------------
slv_reg_write_select <= Bus2IP_WrCE(0 to 0);
slv_reg_read_select <= Bus2IP_RdCE(0 to 0);
slv_write_ack <= Bus2IP_WrCE(0);
slv_read_ack <= Bus2IP_RdCE(0);
RESETTER : process is
variable count : natural range 0 to 50000; --reset 1ms
begin
wait until rising_edge(Bus2IP_Clk);
if (Bus2IP_Reset='1') then
count := 0;
else
if (count < 50000) then
count := count + 1;
bus_reset <= '1';
else
bus_reset <= '0';
end if;
end if;
end process RESETTER;
SLAVE_REG_READ_PROC : process( slv_reg_read_select, keyb_scan) is
begin
 
case slv_reg_read_select is
when "1" => slv_ip2bus_data <= keyb_scan;
when others => slv_ip2bus_data <= (others => '0');
end case;
 
end process SLAVE_REG_READ_PROC;
 
----------------------------------------
-- Example code to drive IP to Bus signals
----------------------------------------
IP2Bus_Data <= slv_ip2bus_data;
keyb_up <= keyb_scan(7);
IP2Bus_Ack <= slv_write_ack or slv_read_ack;
IP2Bus_Error <= '0';
IP2Bus_Retry <= '0';
IP2Bus_ToutSup <= '0';
 
end IMP;
/tags/KEYB_CON_0_01/Constants.vhd
0,0 → 1,137
library ieee;
use ieee.std_logic_1164.all;
 
library work;
 
package Constants is
constant number_of_rows : natural := 6;
constant number_of_cols : natural := 12;
constant scancode_width : natural := 8;
constant max_keys_pressed : natural := 3;
 
constant number_of_keys : natural := number_of_rows * number_of_cols;
 
-- internal clock of 50 Mhz divided by 512 gives about 100 kHz, 1 clock-cycle is about 10 us
-- 100 ticks is about 1 ms.
constant debounce_count : natural := 100;
subtype row is std_logic_vector(number_of_cols-1 downto 0);
subtype col is std_logic_vector(number_of_rows-1 downto 0);
 
--3 bits
subtype col_number is natural range 0 to number_of_rows-1;
--4 bits
subtype row_number is natural range 0 to number_of_cols-1;
--number of keys pressed
subtype key_number is natural range 0 to max_keys_pressed ;
 
subtype states is std_logic_vector(6 downto 0);
--last bit is to differentiate between idle and storing_stage2
--output-lines : strobe, sample, analyse, store, produce, release
constant idle : states := "0000000";
constant strobing : states := "1000000";
constant sampling : states := "0100000";
constant analysing : states := "0110000";
constant storing : states := "0001000";
constant storing_stage2 : states := "0000001";
constant producenormal : states := "0000100";
constant producerelease : states := "0000110";
 
type keymap is array (number_of_rows-1 downto 0) of row;
 
subtype scancode is std_logic_vector(scancode_width-1 downto 0);
-- we need 4 bits to encode the columns and 3 bits for the rows, gives an address of 7 bits
-- that makes 128 possibilities of which 70 are used
type set1_scancodes_lut_type is array (0 to 93) of std_logic_vector(scancode_width-1 downto 0);
constant set1_scancodes_lut : set1_scancodes_lut_type :=
(0 => X"01", --esc
1 => X"10", --q
2 => X"1e", --a
3 => X"2a", --lshi
4 => X"33", --,<
5 => X"1d", --ctrl
 
8 => X"3b", --f1
9 => X"11", --w
10 => X"1f", --s
11 => X"2c", --z
12 => X"1c", --enter
13 => X"38", --alt
 
16 => X"3c", --f2
17 => X"12", --e
18 => X"20", --d
19 => X"2d", --x
20 => X"48", --up
21 => X"39", --space
 
24 => X"3d", --f3
25 => X"13", --r
26 => X"21", --f
27 => X"2e", --c
28 => X"50", --down
 
32 => X"3e", --f4
33 => X"14", --t
34 => X"22", --g
35 => X"2f", --v
36 => X"4b", --left
 
40 => X"3f", --f5
41 => X"15", --y
42 => X"23", --h
43 => X"30", --b
44 => X"4d", --right
45 => X"39", --space
 
48 => X"28", --'"
49 => X"16", --u
50 => X"24", --j
51 => X"31", --n
53 => X"0f", --tab
 
56 => X"1a", --[{
57 => X"17", --i
58 => X"25", --k
59 => X"32", --m
60 => X"34", --.>
61 => X"3a", --caps
64 => X"1b", --]}
65 => X"18", --o
66 => X"26", --l
67 => X"36", --rshi
68 => X"0e", --backspace
69 => X"27", --;:
 
72 => X"0c", ---_
73 => X"19", --p
74 => X"08", --7&
75 => X"05", --4$
76 => X"52", --ins
77 => X"02", --1!
 
80 => X"0d", --=+
81 => X"29", --`~
82 => X"09", --8*
83 => X"06", --5%
84 => X"0b", --0)
85 => X"03", --2@
 
88 => X"2b", --\|
89 => X"35", --/?
90 => X"0a", --9(
91 => X"07", --6^
92 => X"53", --del
93 => X"04", --3#
 
others => X"00" --error
);
 
 
end Constants;
/tags/KEYB_CON_0_01/Analyser.vhd
0,0 → 1,265
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.Constants.all;
entity Analyser is
port (reset, clk : in std_logic;
analyse : in std_logic;
store : in std_logic;
debounced: out std_logic;
keychanged : out std_logic;
released : out std_logic;
sample_col : in col;
sample_row_number : in row_number;
conv_col : out col_number;
conv_row : out row_number
);
end Analyser;
 
architecture Analyser_arc of Analyser is
 
function ones_in_column(inp: col) return col_number is
variable number : col_number;
begin
number := 0;
for i in inp'range loop
if inp(i)='1' then number := number+1;
end if;
end loop;
return number;
end ones_in_column;
 
function ones_in_row(inp: row) return row_number is
variable number : row_number;
begin
number := 0;
for i in inp'range loop
if inp(i)='1' then number := number + 1;
end if;
end loop;
return number;
end ones_in_row;
 
function priority_encode(inp: col) return col_number is
variable tmp: col_number;
begin
if inp(5)='1' then tmp:= 5;
elsif inp(4)='1' then tmp:= 4;
elsif inp(3)='1' then tmp:= 3;
elsif inp(2)='1' then tmp:= 2;
elsif inp(1)='1' then tmp:= 1;
else tmp:= 0;
end if;
return tmp;
end priority_encode;
 
 
--reduce or function to look for key press in a column
function key_pressed(inp : row) return std_logic is
variable tmp: std_logic;
begin
tmp:='0';
for i in inp'range loop
tmp := tmp or inp(i);
end loop;
return tmp;
end key_pressed;
 
--function that checks whether the new key specified by col_number and row_number is valid
--large input is necessary to make it a legal function
 
function valid_key(colnum: col_number; rownum: row_number; row0:row; row1:row; row2:row; row3:row; row4:row; row5:row; keysdown: key_number) return std_logic is
variable colpress : col;
variable rowpress : row;
variable valid :std_logic;
begin
valid := '1'; --valid until proven otherwise
colpress := "000000";
rowpress := "000000000000";
colpress(0):= key_pressed(row0);
colpress(1):= key_pressed(row1);
colpress(2):= key_pressed(row2);
colpress(3):= key_pressed(row3);
colpress(4):= key_pressed(row4);
colpress(5):= key_pressed(row5);
for i in number_of_cols-1 downto 0 loop
rowpress(i) := row0(i) or row1(i) or row2(i) or row3(i) or row4(i) or row5(i);
end loop;
--add virtual key
colpress(colnum) := '1';
rowpress(rownum) := '1';
if (keysdown >= max_keys_pressed) then --too many keys pressed
valid := '0';
elsif (keysdown = 2) then --check for ghosting
if (ones_in_column(colpress)=2 and ones_in_row(rowpress)=2) then
valid := '0';
end if;
end if;
return valid;
 
end valid_key;
 
signal debounce_state : col;
signal keysdown : natural range 0 to max_keys_pressed ;
signal next_keysdown : natural range 0 to max_keys_pressed;
signal keychange : std_logic;
signal release : std_logic;
signal conv_col_number : col_number;
signal conv_row_number : row_number;
signal previous_sample : col; --last sampled column
 
signal row0 : row;
signal row1 : row;
signal row2 : row;
signal row3 : row;
signal row4 : row;
signal row5 : row;
 
begin
--look for valid keychange
detector: process ( conv_col_number, conv_row_number, keysdown, row0, row1, row2, row3, row4, row5, sample_row_number, previous_sample)
variable colpress : col_number;
begin
colpress := 0;
if ((row0(sample_row_number) xor previous_sample(0))='1') then
--change detected
--keychange if valid or !pressed_down
keychange <= (not previous_sample(0)) or valid_key(0, sample_row_number, row0, row1, row2, row3, row4, row5, keysdown);
release <= not previous_sample(0);
colpress := 0;
elsif((row1(sample_row_number) xor previous_sample(1))='1') then
keychange <= (not previous_sample(1)) or valid_key(1, sample_row_number, row0, row1, row2, row3, row4, row5, keysdown);
release <= not previous_sample(1);
colpress := 1;
elsif((row2(sample_row_number) xor previous_sample(2))='1') then
keychange <= (not previous_sample(2)) or valid_key(2, sample_row_number, row0, row1, row2, row3, row4, row5, keysdown);
release <= not previous_sample(2);
colpress := 2;
elsif((row3(sample_row_number) xor previous_sample(3))='1') then
keychange <= (not previous_sample(3)) or valid_key(3, sample_row_number, row0, row1, row2, row3, row4, row5, keysdown);
release <= not previous_sample(3);
colpress := 3;
elsif((row4(sample_row_number) xor previous_sample(4))='1') then
keychange <= (not previous_sample(4)) or valid_key(4, sample_row_number, row0, row1, row2, row3, row4, row5, keysdown);
release <= not previous_sample(4);
colpress := 4;
elsif ((row5(sample_row_number) xor previous_sample(5))='1') then
keychange <= (not previous_sample(5)) or valid_key(5, sample_row_number, row0, row1, row2, row3, row4, row5, keysdown);
release <= not previous_sample(5);
colpress := 5;
else
keychange <= '0';
release <= '0';
end if;
conv_col_number <= colpress;
conv_row_number <= sample_row_number;
end process;
 
next_keysdown <= keysdown+1 when keychange='1' and release='0'
else
keysdown-1 when keychange='1' and release='1'
else
keysdown;
storer:process
begin
wait until rising_edge(clk);
if (reset='1') then
row0 <= "000000000000";
row1 <= "000000000000";
row2 <= "000000000000";
row3 <= "000000000000";
row4 <= "000000000000";
row5 <= "000000000000";
keychanged <= '0';
released <= '0';
keysdown <= 0;
conv_col <= 0;
conv_row <= 0;
elsif (store='1') then
if (debounce_state = "000000") then
keychanged <= keychange;
released <= release;
keysdown <= next_keysdown;
conv_col <= conv_col_number;
conv_row <= conv_row_number;
if (keychange='1') then
case conv_col_number is
when 0 => row0(conv_row_number) <= previous_sample(0);
when 1 => row1(conv_row_number) <= previous_sample(1);
when 2 => row2(conv_row_number) <= previous_sample(2);
when 3 => row3(conv_row_number) <= previous_sample(3);
when 4 => row4(conv_row_number) <= previous_sample(4);
when 5 => row5(conv_row_number) <= previous_sample(5);
when others => null;
end case;
end if;
else
keychanged <= '0';
released <= '0';
end if;
else
keychanged <= '0';
released <= '0';
end if;
end process;
 
--debouncing
debouncer: process
variable counter : natural range 0 to debounce_count;
begin
wait until rising_edge(clk);
if (reset = '1') then
debounce_state <= (others=> '0');
previous_sample <= (others => '0');
counter := debounce_count;
debounced <= '0';
else
if (analyse='1') then
 
if (counter > 0 and counter < debounce_count) then
counter := counter - 1;
debounce_state <= debounce_state or (previous_sample xor sample_col);
debounced <= '0';
end if;
if (counter = debounce_count) then
previous_sample <= sample_col;
counter := counter -1 ;
end if;
if (counter = 0) then
debounced <= '1';
end if;
else
counter := debounce_count;
debounced <= '0';
debounce_state <= (others=> '0');
end if;
end if;
end process;
 
end Analyser_arc;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.