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

Subversion Repositories ps2

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 41 to Rev 42
    Reverse comparison

Rev 41 → Rev 42

/tags/rel_13/sim/rtl_sim/bin/rtl_file_list
0,0 → 1,6
ps2_keyboard.v
ps2_mouse.v
ps2_top.v
ps2_translation_table.v
ps2_wb_if.v
ps2_io_ctrl.v
/tags/rel_13/sim/rtl_sim/bin/sim_file_list
0,0 → 1,5
ps2_keyboard_model.v
ps2_test_bench.v
wb_master32.v
wb_master_behavioral.v
ps2_sim_top.v
/tags/rel_13/sim/rtl_sim/bin/xilinx_file_list
0,0 → 1,2
RAMB4_S8.v
glbl.v
/tags/rel_13/sim/rtl_sim/bin/cds.lib
0,0 → 1,6
#
# cds.lib: Defines the locations of compiled libraries.
# Created by ncprep on Wed Aug 1 15:03:54 2001
#
 
define worklib ./INCA_libs/worklib
/tags/rel_13/sim/rtl_sim/bin/hdl.var
0,0 → 1,9
#
# hdl.var: Defines variables used by the INCA tools.
# Created by ncprep on Wed Aug 1 15:03:54 2001
#
 
softinclude $CDS_INST_DIR/tools/inca/files/hdl.var
 
define LIB_MAP ( $LIB_MAP, + => worklib )
define VIEW_MAP ( $VIEW_MAP, .v => v)
/tags/rel_13/sim/rtl_sim/log/ncelab.log
0,0 → 1,56
TOOL: ncelab 04.10-b001: Started on Nov 30, 2003 at 12:53:31
ncelab
-f ncelab.args
-MESSAGES
-NOCOPYRIGHT
-CDSLIB ../bin/cds.lib
-HDLVAR ../bin/hdl.var
-LOGFILE ../log/ncelab.log
-TIMESCALE 1ns/100ps
-SNAPSHOT worklib.ps2_test_bench:rtl
-NO_TCHK_MSG
-ACCESS +RWC
worklib.ps2_test_bench
 
Elaborating the design hierarchy:
Caching library 'worklib' ....... Done
Building instance overlay tables: .................... Done
Generating native compiled code:
worklib.WB_MASTER32:v <0x285dcd5e>
streams: 14, words: 37673
worklib.WB_MASTER_BEHAVIORAL:v <0x4011829a>
streams: 6, words: 64972
worklib.ps2_io_ctrl:v <0x1a9cfb7e>
streams: 7, words: 4237
worklib.ps2_keyboard:v <0x48cda7c5>
streams: 107, words: 77889
worklib.ps2_keyboard_model:v <0x64c1328f>
streams: 13, words: 19418
worklib.ps2_sim_top:v <0x3261324c>
streams: 4, words: 1087
worklib.ps2_test_bench:v <0x1e73bec9>
streams: 46, words: 159235
worklib.ps2_top:v <0x758f909c>
streams: 3, words: 782
worklib.ps2_translation_table:v <0x726febd5>
streams: 14, words: 9671
worklib.ps2_wb_if:v <0x2138f2f1>
streams: 101, words: 78860
Loading native compiled code: .................... Done
Building instance specific data structures.
Design hierarchy summary:
Instances Unique
Modules: 10 10
Primitives: 2 1
Registers: 254 254
Scalar wires: 74 -
Expanded wires: 32 1
Vectored wires: 16 -
Always blocks: 41 41
Initial blocks: 4 4
Parallel blocks: 14 14
Cont. assignments: 40 56
Pseudo assignments: 5 59
Simulation timescale: 1ps
Writing initial simulation snapshot: worklib.ps2_test_bench:rtl
TOOL: ncelab 04.10-b001: Exiting on Nov 30, 2003 at 12:53:33 (total: 00:00:02)
/tags/rel_13/sim/rtl_sim/log/ncvlog.log
0,0 → 1,59
TOOL: ncvlog 04.10-b001: Started on Nov 30, 2003 at 12:53:30
ncvlog
-f ncvlog.args
-CDSLIB ../bin/cds.lib
-HDLVAR ../bin/hdl.var
-MESSAGES
-INCDIR ../../../bench/verilog
-INCDIR ../../../rtl/verilog
-NOCOPYRIGHT
-LOGFILE ../log/ncvlog.log
-DEFINE PS2_NUM_OF_NORMAL_SCANCODES 85
-DEFINE PS2_NUM_OF_EXTENDED_SCANCODES 38
-DEFINE SIM
../../../rtl/verilog/ps2_keyboard.v
../../../rtl/verilog/ps2_mouse.v
../../../rtl/verilog/ps2_top.v
../../../rtl/verilog/ps2_translation_table.v
../../../rtl/verilog/ps2_wb_if.v
../../../rtl/verilog/ps2_io_ctrl.v
../../../bench/verilog/ps2_keyboard_model.v
../../../bench/verilog/ps2_test_bench.v
../../../bench/verilog/wb_master32.v
../../../bench/verilog/wb_master_behavioral.v
../../../bench/verilog/ps2_sim_top.v
 
file: ../../../rtl/verilog/ps2_keyboard.v
module worklib.ps2_keyboard:v
errors: 0, warnings: 0
file: ../../../rtl/verilog/ps2_mouse.v
module worklib.ps2_mouse:v
errors: 0, warnings: 0
file: ../../../rtl/verilog/ps2_top.v
module worklib.ps2_top:v
errors: 0, warnings: 0
file: ../../../rtl/verilog/ps2_translation_table.v
module worklib.ps2_translation_table:v
errors: 0, warnings: 0
file: ../../../rtl/verilog/ps2_wb_if.v
module worklib.ps2_wb_if:v
errors: 0, warnings: 0
file: ../../../rtl/verilog/ps2_io_ctrl.v
module worklib.ps2_io_ctrl:v
errors: 0, warnings: 0
file: ../../../bench/verilog/ps2_keyboard_model.v
module worklib.ps2_keyboard_model:v
errors: 0, warnings: 0
file: ../../../bench/verilog/ps2_test_bench.v
module worklib.ps2_test_bench:v
errors: 0, warnings: 0
file: ../../../bench/verilog/wb_master32.v
module worklib.WB_MASTER32:v
errors: 0, warnings: 0
file: ../../../bench/verilog/wb_master_behavioral.v
module worklib.WB_MASTER_BEHAVIORAL:v
errors: 0, warnings: 0
file: ../../../bench/verilog/ps2_sim_top.v
module worklib.ps2_sim_top:v
errors: 0, warnings: 0
TOOL: ncvlog 04.10-b001: Exiting on Nov 30, 2003 at 12:53:30 (total: 00:00:00)
/tags/rel_13/sim/rtl_sim/log/ncsim.log
0,0 → 1,27
TOOL: ncsim 04.10-b001: Started on Nov 30, 2003 at 12:53:34
ncsim
-LICQUEUE
-f ./ncsim.args
-MESSAGES
-NOCOPYRIGHT
-CDSLIB ../bin/cds.lib
-HDLVAR ../bin/hdl.var
-INPUT ncsim.tcl
-LOGFILE ../log/ncsim.log
worklib.ps2_test_bench:rtl
 
Loading snapshot worklib.ps2_test_bench:rtl .................... Done
ncsim> source /shared/tools/ncsim/tools/inca/files/ncsimrc
ncsim> database -open waves -shm -into ../out/waves.shm
Created SHM database waves
ncsim> probe -create -database waves ps2_test_bench -shm -all -depth all
Created probe 1
ncsim> run
 
 
status: Testbench done
report (deaddead)
exit (00000000)
/projects/highland/gorand/tmp/ps2/bench/verilog/ps2_test_bench.v:289 $finish(0);
ncsim> quit
TOOL: ncsim 04.10-b001: Exiting on Nov 30, 2003 at 13:02:41 (total: 00:09:07)
/tags/rel_13/sim/rtl_sim/run/ncelab.args
0,0 → 1,10
-MESSAGES
-NOCOPYRIGHT
-CDSLIB ../bin/cds.lib
-HDLVAR ../bin/hdl.var
-LOGFILE ../log/ncelab.log
-TIMESCALE 1ns/100ps
-SNAPSHOT worklib.ps2_test_bench:rtl
-NO_TCHK_MSG
-ACCESS +RWC
worklib.ps2_test_bench
/tags/rel_13/sim/rtl_sim/run/ncvlog.args
0,0 → 1,21
-CDSLIB ../bin/cds.lib
-HDLVAR ../bin/hdl.var
-MESSAGES
-INCDIR ../../../bench/verilog
-INCDIR ../../../rtl/verilog
-NOCOPYRIGHT
-LOGFILE ../log/ncvlog.log
-DEFINE "PS2_NUM_OF_NORMAL_SCANCODES 85"
-DEFINE "PS2_NUM_OF_EXTENDED_SCANCODES 38"
-DEFINE "SIM"
../../../rtl/verilog/ps2_keyboard.v
../../../rtl/verilog/ps2_mouse.v
../../../rtl/verilog/ps2_top.v
../../../rtl/verilog/ps2_translation_table.v
../../../rtl/verilog/ps2_wb_if.v
../../../rtl/verilog/ps2_io_ctrl.v
../../../bench/verilog/ps2_keyboard_model.v
../../../bench/verilog/ps2_test_bench.v
../../../bench/verilog/wb_master32.v
../../../bench/verilog/wb_master_behavioral.v
../../../bench/verilog/ps2_sim_top.v
/tags/rel_13/sim/rtl_sim/run/ncsim.args
0,0 → 1,7
-MESSAGES
-NOCOPYRIGHT
-CDSLIB ../bin/cds.lib
-HDLVAR ../bin/hdl.var
-INPUT ncsim.tcl
-LOGFILE ../log/ncsim.log
worklib.ps2_test_bench:rtl
/tags/rel_13/sim/rtl_sim/run/ncsim.tcl
0,0 → 1,4
database -open waves -shm -into ../out/waves.shm
probe -create -database waves ps2_test_bench -shm -all -depth all
run
quit
/tags/rel_13/sim/rtl_sim/run/run_sim
0,0 → 1,99
#!/bin/csh -f
 
set current_par = 0
set output_waveform = 0
while ( $current_par < $# )
@ current_par = $current_par + 1
case wave:
@ output_waveform = 1
breaksw
default:
echo 'Unknown option "'$argv[$current_par]'"!'
exit
breaksw
endsw
end
 
echo "-CDSLIB ../bin/cds.lib" > ncvlog.args
echo "-HDLVAR ../bin/hdl.var" >> ncvlog.args
echo "-MESSAGES" >> ncvlog.args
echo "-INCDIR ../../../bench/verilog" >> ncvlog.args
echo "-INCDIR ../../../rtl/verilog" >> ncvlog.args
echo "-NOCOPYRIGHT" >> ncvlog.args
echo "-LOGFILE ../log/ncvlog.log" >> ncvlog.args
echo '-DEFINE "PS2_NUM_OF_NORMAL_SCANCODES 85"' >> ./ncvlog.args
echo '-DEFINE "PS2_NUM_OF_EXTENDED_SCANCODES 38"' >> ./ncvlog.args
echo '-DEFINE "SIM"' >> ./ncvlog.args
 
 
foreach filename ( `cat ../bin/rtl_file_list` )
echo "../../../rtl/verilog/"$filename >> ncvlog.args
end
 
foreach filename ( `cat ../bin/sim_file_list` )
echo "../../../bench/verilog/"$filename >> ncvlog.args
end
 
ncvlog -f ncvlog.args
 
echo "-MESSAGES" > ncelab.args
echo "-NOCOPYRIGHT" >> ncelab.args
echo "-CDSLIB ../bin/cds.lib" >> ncelab.args
echo "-HDLVAR ../bin/hdl.var" >> ncelab.args
echo "-LOGFILE ../log/ncelab.log" >> ncelab.args
echo "-TIMESCALE 1ns/100ps" >> ncelab.args
echo "-SNAPSHOT worklib.ps2_test_bench:rtl" >> ncelab.args
echo "-NO_TCHK_MSG" >> ncelab.args
echo "-ACCESS +RWC" >> ncelab.args
echo "worklib.ps2_test_bench" >> ncelab.args
 
ncelab -f ncelab.args
 
echo "-MESSAGES" > ncsim.args
echo "-NOCOPYRIGHT" >> ncsim.args
echo "-CDSLIB ../bin/cds.lib" >> ncsim.args
echo "-HDLVAR ../bin/hdl.var" >> ncsim.args
echo "-INPUT ncsim.tcl" >> ncsim.args
echo "-LOGFILE ../log/ncsim.log" >> ncsim.args
echo "worklib.ps2_test_bench:rtl" >> ncsim.args
 
if ( $output_waveform ) then
echo "database -open waves -shm -into ../out/waves.shm" > ./ncsim.tcl
echo "probe -create -database waves ps2_test_bench -shm -all -depth all" >> ./ncsim.tcl
echo "run" >> ./ncsim.tcl
else
echo "run" > ./ncsim.tcl
endif
 
echo "quit" >> ncsim.tcl
 
ncsim -LICQUEUE -f ./ncsim.args
 
set exit_line_nb = `sed -n '/exit/=' < ../log/ncsim.log`
 
#echo "$exit_line_nb"
 
set dead_line_nb = 0
 
if ( $exit_line_nb ) then
 
@ dead_line_nb = $exit_line_nb - 1
set exit_line=`sed -n $exit_line_nb's/exit/&/gp' < ../log/ncsim.log`
set dead_line=`sed -n $dead_line_nb's/report/&/gp' < ../log/ncsim.log`
 
echo "$dead_line"
echo "$exit_line"
 
echo "TEST: ps2"
if ( "$dead_line" == "report (deaddead)" ) then
if ( "$exit_line" == "exit (00000000)" ) then
echo "STATUS: passed" #|tee -a ../log/run_sim.log 2>&1
else
echo "STATUS: failed" #|tee -a ../log/run_sim.log 2>&1
endif
else
echo "STATUS: failed"
endif
 
endif
 
tags/rel_13/sim/rtl_sim/run/run_sim Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/rel_13/bench/verilog/ps2_test_bench.v =================================================================== --- tags/rel_13/bench/verilog/ps2_test_bench.v (nonexistent) +++ tags/rel_13/bench/verilog/ps2_test_bench.v (revision 42) @@ -0,0 +1,1670 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// ps2_test_bench.v //// +//// //// +//// This file is part of the "ps2" project //// +//// http://www.opencores.org/cores/ps2/ //// +//// //// +//// Author(s): //// +//// - mihad@opencores.org //// +//// - Miha Dolenc //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: not supported by cvs2svn $ +// Revision 1.7 2003/10/03 10:16:50 primozs +// support for configurable devider added +// +// Revision 1.6 2003/05/28 16:26:51 simons +// Change the address width. +// +// Revision 1.5 2002/04/09 13:17:03 mihad +// Mouse interface testcases added +// +// Revision 1.4 2002/02/20 16:35:34 mihad +// Little/big endian changes continued +// +// Revision 1.3 2002/02/20 15:20:02 mihad +// Little/big endian changes incorporated +// +// Revision 1.2 2002/02/18 18:08:31 mihad +// One bug fixed +// +// Revision 1.1.1.1 2002/02/18 16:16:55 mihad +// Initial project import - working +// +// + +`include "timescale.v" +`include "ps2_testbench_defines.v" +`include "ps2_defines.v" + +`define KBD_STATUS_REG 32'h64 +`define KBD_CNTL_REG 32'h64 +`define KBD_DATA_REG 32'h60 +/* + * controller commands + */ +`define KBD_READ_MODE 32'h20_00_00_00 +`define KBD_WRITE_MODE 32'h60_00_00_00 +`define KBD_SELF_TEST 32'hAA_00_00_00 +`define KBD_SELF_TEST2 32'hAB_00_00_00 +`define KBD_CNTL_ENABLE 32'hAE_00_00_00 +/* + * keyboard commands + */ +`define KBD_ENABLE 32'hF4_00_00_00 +`define KBD_DISABLE 32'hF5_00_00_00 +`define KBD_RESET 32'hFF_00_00_00 +/* + * keyboard replies + */ +`define KBD_ACK 32'hFA +`define KBD_POR 32'hAA +/* + * status register bits + */ +`define KBD_OBF 32'h01 +`define KBD_IBF 32'h02 +`define KBD_GTO 32'h40 +`define KBD_PERR 32'h80 +/* + * keyboard controller mode register bits + */ +`define KBD_EKI 32'h01_00_00_00 +`define KBD_SYS 32'h04_00_00_00 +`define KBD_DMS 32'h20_00_00_00 +`define KBD_KCC 32'h40_00_00_00 +`define KBD_DISABLE_COMMAND 32'h10_00_00_00 +`define AUX_OBUF_FULL 8'h20 /* output buffer (from device) full */ +`define AUX_INTERRUPT_ON 32'h02_000000 /* enable controller interrupts */ + +`ifdef PS2_AUX +`define AUX_ENABLE 32'ha8_000000 /* enable aux */ +`define AUX_DISABLE 32'ha7_000000 /* disable aux */ +`define AUX_MAGIC_WRITE 32'hd4_000000 /* value to send aux device data */ +`define AUX_SET_SAMPLE 32'hf3_000000 /* set sample rate */ +`define AUX_SET_RES 32'he8_000000 /* set resolution */ +`define AUX_SET_SCALE21 32'he7_000000 /* set 2:1 scaling */ +`define AUX_INTS_OFF 32'h65_000000 /* disable controller interrupts */ +`define AUX_INTS_ON 32'h47_000000 /* enable controller interrupts */ +`define AUX_ENABLE_DEV 32'hf4_000000 /* enable aux device */ +`endif + +module ps2_test_bench() ; + +parameter [31:0] MAX_SEQUENCE_LENGTH = 10 ; +wire kbd_clk_cable ; +wire kbd_data_cable ; + +pullup(kbd_clk_cable) ; +pullup(kbd_data_cable) ; + +`ifdef PS2_AUX +pullup(aux_clk_cable) ; +pullup(aux_data_cable) ; +wire wb_intb ; +reg stop_mouse_tests ; +`endif + +reg wb_clock ; +reg wb_reset ; + +wire [7:0] received_char ; +wire char_valid ; + +reg error ; + +`ifdef XILINX + assign glbl.GSR = wb_reset ; +`endif +ps2_keyboard_model i_ps2_keyboard_model +( + .kbd_clk_io (kbd_clk_cable), + .kbd_data_io (kbd_data_cable), + .last_char_received_o (received_char), + .char_valid_o (char_valid) +) ; + +`ifdef PS2_AUX +wire [7:0] aux_received_char ; +ps2_keyboard_model i_ps2_mouse_model +( + .kbd_clk_io (aux_clk_cable), + .kbd_data_io (aux_data_cable), + .last_char_received_o (aux_received_char), + .char_valid_o (aux_char_valid) +) ; +`endif + +reg ok ; +reg error1 ; + +reg ok_o; + +integer rem; +integer wb_period; +reg wb_rem; +reg [15:0] wb_dev_data; + + +integer watchdog_timer ; +reg watchdog_reset ; +reg watchdog_reset_previous ; + +reg [7:0] normal_scancode_set2_mem [0:`PS2_NUM_OF_NORMAL_SCANCODES - 1] ; +reg [7:0] normal_scancode_set1_mem [0:`PS2_NUM_OF_NORMAL_SCANCODES - 1] ; +reg [7:0] extended_scancode_set2_mem [0:`PS2_NUM_OF_EXTENDED_SCANCODES - 1] ; +reg [7:0] extended_scancode_set1_mem [0:`PS2_NUM_OF_EXTENDED_SCANCODES - 1] ; + +`define WB_PERIOD (1/`WB_FREQ) +initial +begin + + + $readmemh("../../../bench/data/normal_scancodes_set2.hex", normal_scancode_set2_mem) ; + $readmemh("../../../bench/data/normal_scancodes_set1.hex", normal_scancode_set1_mem) ; + $readmemh("../../../bench/data/extended_scancodes_set2.hex", extended_scancode_set2_mem) ; + $readmemh("../../../bench/data/extended_scancodes_set1.hex", extended_scancode_set1_mem) ; + + + wb_period =50; + wb_rem = 1'b0; + rem =0; + + error1 = 1'b0 ; + + watchdog_timer = 32'h1000_0000 ; + watchdog_reset = 0 ; + watchdog_reset_previous = 0 ; + + wb_clock = 1'b1 ; + wb_reset = 1'b1 ; + + #100 ; + + repeat ( 10 ) + @(posedge wb_clock) ; + + wb_reset <= 1'b0 ; + + repeat(6) + + begin + @(posedge wb_clock) + begin + rem = 5000 % wb_period; + + if (rem > 0) + begin + wb_rem = 1'b1; + + end + else + begin + wb_rem = 1'b0; + + end + end + + begin + devider_write(4'h8,5000/wb_period + wb_rem ,ok_o); + + + @(posedge wb_clock) ; + #1 initialize_controler ; + + test_scan_code_receiving ; + + `ifdef PS2_AUX + fork + begin + `endif + test_normal_scancodes ; + + test_extended_scancodes ; + + test_print_screen_and_pause_scancodes ; + `ifdef PS2_AUX + stop_mouse_tests = 1'b1 ; + end + begin + stop_mouse_tests = 0 ; + receive_mouse_movement ; + end + join + `endif + + test_keyboard_inhibit ; + wb_period = wb_period + 10 ; + + end + end + $display("\n\nstatus: Testbench done"); + if ( error1 == 0 ) + begin + $display ("report (%h)", 32'hdeaddead ) ; + $display ("exit (00000000)" ) ; + end + else + begin + $display ("report (%h)", 32'heeeeeeee ) ; + $display ("exit (00000000)" ) ; + end + + $finish(0); + + + //$display("end simulation"); + // +end + +always + #(wb_period/2.0) wb_clock = !wb_clock ; + +wire wb_cyc, + wb_stb, + wb_we, + wb_ack, + wb_rty, + wb_int ; + +wire [3:0] wb_sel ; + +wire [31:0] wb_adr, wb_dat_m_s, wb_dat_s_m ; + +ps2_sim_top +i_ps2_top +( + .wb_clk_i (wb_clock), + .wb_rst_i (wb_reset), + .wb_cyc_i (wb_cyc), + .wb_stb_i (wb_stb), + .wb_we_i (wb_we), + .wb_sel_i (wb_sel), + .wb_adr_i (wb_adr[3:0]), + .wb_dat_i (wb_dat_m_s), + .wb_dat_o (wb_dat_s_m), + .wb_ack_o (wb_ack), + + .wb_int_o (wb_int), + + .ps2_kbd_clk_io (kbd_clk_cable), + .ps2_kbd_data_io (kbd_data_cable) + `ifdef PS2_AUX + , + .wb_intb_o(wb_intb), + + .ps2_aux_clk_io(aux_clk_cable), + .ps2_aux_data_io(aux_data_cable) + `endif +) ; + +WB_MASTER_BEHAVIORAL i_wb_master +( + .CLK_I (wb_clock), + .RST_I (wb_reset), + .TAG_I (1'b0), + .TAG_O (), + .ACK_I (wb_ack), + .ADR_O (wb_adr), + .CYC_O (wb_cyc), + .DAT_I (wb_dat_s_m), + .DAT_O (wb_dat_m_s), + .ERR_I (1'b0), + .RTY_I (1'b0), + .SEL_O (wb_sel), + .STB_O (wb_stb), + .WE_O (wb_we), + .CAB_O () +); + +always@(posedge wb_clock) +begin + if ( watchdog_timer === 0 ) + begin + $display("Warning! Simulation watchdog timer has expired!") ; + watchdog_timer = 32'hFFFF_FFFF ; + end + else if ( watchdog_reset !== watchdog_reset_previous ) + watchdog_timer = 32'hFFFF_FFFF ; + + watchdog_reset_previous = watchdog_reset ; + +end + +task initialize_controler ; + reg [7:0] data ; + reg status ; +begin:main + + // simulate keyboard driver's behaviour + data = `KBD_OBF ; + status = 1 ; + while ( data & `KBD_OBF ) + begin + read_status_reg(data, status) ; + if ( status !== 1 ) + #1 disable main ; + + if ( data & `KBD_OBF ) + begin + read_data_reg(data, status) ; + data = `KBD_OBF ; + end + + if ( status !== 1 ) + #1 disable main ; + + end + + kbd_write(`KBD_CNTL_REG, `KBD_SELF_TEST, status) ; + + if ( status !== 1 ) + #1 disable main ; + + // command sent - wait for commands output to be ready + data = 0 ; + while( !( data & `KBD_OBF ) ) + begin + read_status_reg(data, status) ; + if ( status !== 1 ) + #1 disable main ; + end + + read_data_reg( data, status ) ; + + if ( status !== 1 ) + #1 disable main ; + + if ( data !== 8'h55 ) + begin + $display("Error! Keyboard controler should respond to self test command with hard coded value 0x55! ") ; + error1 = 1'b1 ; + + end + + // perform self test 2 + kbd_write(`KBD_CNTL_REG, `KBD_SELF_TEST2, status) ; + + if ( status !== 1 ) + #1 disable main ; + + // command sent - wait for commands output to be ready + data = 0 ; + while( status && !( data & `KBD_OBF ) ) + read_status_reg(data, status) ; + + if ( status !== 1 ) + #1 disable main ; + + read_data_reg( data, status ) ; + + if ( status !== 1 ) + #1 disable main ; + + if ( data !== 8'h00 ) + begin + $display("Error! Keyboard controler should respond to self test command 2 with hard coded value 0x00! ") ; + error1 = 1'b1 ; + + end + + kbd_write(`KBD_CNTL_REG, `KBD_CNTL_ENABLE, status); + + if ( status !== 1 ) + #1 disable main ; + + // send reset command to keyboard + kbd_write(`KBD_DATA_REG, `KBD_RESET, status) ; + + if ( status !== 1 ) + #1 disable main ; + + fork + begin + // wait for keyboard to respond with acknowledge + data = 0 ; + while( status && !( data & `KBD_OBF ) ) + read_status_reg(data, status) ; + + if ( status !== 1 ) + #1 disable main ; + + read_data_reg( data, status ) ; + + if ( status !== 1 ) + #1 disable main ; + + if ( data !== `KBD_ACK ) + begin + $display("Error! Expected character from keyboard was 0x%h, actualy received 0x%h!", `KBD_ACK, data ) ; + error1 = 1'b1 ; + + end + + // wait for keyboard to respond with BAT status + data = 0 ; + while( status && !( data & `KBD_OBF ) ) + read_status_reg(data, status) ; + + if ( status !== 1 ) + #1 disable main ; + + read_data_reg( data, status ) ; + + if ( status !== 1 ) + #1 disable main ; + + if ( data !== `KBD_POR ) + begin + $display("Error! Expected character from keyboard was 0x%h, actualy received 0x%h!", `KBD_POR, data ) ; + error1 = 1'b1 ; + + end + + // send disable command to keyboard + kbd_write(`KBD_DATA_REG, `KBD_DISABLE, status) ; + + if ( status !== 1 ) + #1 disable main ; + + // wait for keyboard to respond with acknowledge + data = 0 ; + while( status && !( data & `KBD_OBF ) ) + read_status_reg(data, status) ; + + if ( status !== 1 ) + #1 disable main ; + + read_data_reg( data, status ) ; + + if ( status !== 1 ) + #1 disable main ; + + if ( data !== `KBD_ACK ) + begin + $display("Error! Expected character from keyboard was 0x%h, actualy received 0x%h!", `KBD_ACK, data ) ; + error1 = 1'b1 ; + + end + + kbd_write(`KBD_CNTL_REG, `KBD_WRITE_MODE, status); + if ( status !== 1 ) + #1 disable main ; + + kbd_write(`KBD_DATA_REG, `KBD_EKI|`KBD_SYS|`KBD_DMS|`KBD_KCC, status); + if ( status !== 1 ) + #1 disable main ; + + // send disable command to keyboard + kbd_write(`KBD_DATA_REG, `KBD_ENABLE, status) ; + + if ( status !== 1 ) + #1 disable main ; + + // wait for keyboard to respond with acknowledge + data = 0 ; + while( status && !( data & `KBD_OBF ) ) + read_status_reg(data, status) ; + + if ( status !== 1 ) + #1 disable main ; + + read_data_reg( data, status ) ; + + if ( status !== 1 ) + #1 disable main ; + + if ( data !== `KBD_ACK ) + begin + $display("Error! Expected character from keyboard was 0x%h, actualy received 0x%h!", `KBD_ACK, data ) ; + error1 = 1'b1 ; + + end + + // now check if command byte is as expected + kbd_write(`KBD_CNTL_REG, `KBD_READ_MODE, status); + if ( status !== 1 ) + #1 disable main ; + + data = 0 ; + while( status && !( data & `KBD_OBF ) ) + read_status_reg(data, status) ; + + if ( status !== 1 ) + #1 disable main ; + + read_data_reg(data, status) ; + + if ( status !== 1 ) + #1 disable main ; + + if ( ({data, 24'h0} & (`KBD_EKI|`KBD_SYS|`KBD_DMS|`KBD_KCC)) !== (`KBD_EKI|`KBD_SYS|`KBD_DMS|`KBD_KCC) ) + begin + $display("Error! Read command byte returned wrong value!") ; + error1 = 1'b1 ; + + end + end + begin + @(char_valid) ; + if ( {received_char, 24'h0} !== `KBD_RESET ) + begin + $display("Error! Keyboard received invalid character/command") ; + error1 = 1'b1 ; + + end + + i_ps2_keyboard_model.kbd_send_char + ( + `KBD_ACK, + ok, + error + ) ; + + i_ps2_keyboard_model.kbd_send_char + ( + `KBD_POR, + ok, + error + ) ; + + @(char_valid) ; + if ( {received_char,24'h0} !== `KBD_DISABLE ) + begin + $display("Error! Keyboard received invalid character/command") ; + error1 = 1'b1 ; + + end + + i_ps2_keyboard_model.kbd_send_char + ( + `KBD_ACK, + ok, + error + ) ; + + @(char_valid) ; + if ( {received_char,24'h0} !== `KBD_ENABLE ) + begin + $display("Error! Keyboard received invalid character/command") ; + error1 = 1'b1 ; + + end + + i_ps2_keyboard_model.kbd_send_char + ( + `KBD_ACK, + ok, + error + ) ; + + end + join + + watchdog_reset = !watchdog_reset ; + + `ifdef PS2_AUX + kbd_write(`KBD_CNTL_REG, `AUX_ENABLE, status) ; + + if ( status !== 1 ) + #1 disable main ; + + // simulate aux driver's behaviour + data = 1 ; + status = 1 ; + + kbd_write(`KBD_CNTL_REG, `AUX_MAGIC_WRITE, status) ; + if ( status !== 1 ) + #1 disable main ; + + data = 1 ; + + kbd_write(`KBD_DATA_REG, `AUX_SET_SAMPLE, status) ; + + if ( status !== 1 ) + #1 disable main ; + + @(aux_char_valid) ; + if ( {aux_received_char, 24'h000000} !== `AUX_SET_SAMPLE) + begin + $display("Time %t ", $time) ; + $display("PS2 mouse didn't receive expected character! Expected %h, actual %h !", `AUX_SET_SAMPLE, aux_received_char ) ; + end + + data = 1 ; + status = 1 ; + + kbd_write(`KBD_CNTL_REG, `AUX_MAGIC_WRITE, status) ; + if ( status !== 1 ) + #1 disable main ; + + data = 1 ; + + kbd_write(`KBD_DATA_REG, `AUX_SET_RES, status) ; + + if ( status !== 1 ) + #1 disable main ; + + + @(aux_char_valid) ; + if ( {aux_received_char, 24'h000000} !== `AUX_SET_RES ) + begin + $display("Time %t ", $time) ; + $display("PS2 mouse didn't receive expected character! Expected %h, actual %h !", `AUX_SET_RES, aux_received_char ) ; + end + + data = 1 ; + status = 1 ; + + kbd_write(`KBD_CNTL_REG, `AUX_MAGIC_WRITE, status) ; + if ( status !== 1 ) + #1 disable main ; + + data = 1 ; + + kbd_write(`KBD_DATA_REG, {8'd100, 24'h000000}, status) ; + + if ( status !== 1 ) + #1 disable main ; + + @(aux_char_valid) ; + if ( aux_received_char !== 8'd100 ) + begin + $display("Time %t ", $time) ; + $display("PS2 mouse didn't receive expected character! Expected %h, actual %h !", 100, aux_received_char ) ; + end + + data = 1 ; + status = 1 ; + + kbd_write(`KBD_CNTL_REG, `AUX_MAGIC_WRITE, status) ; + if ( status !== 1 ) + #1 disable main ; + + data = 1 ; + + kbd_write(`KBD_DATA_REG, {8'd3, 24'h000000}, status) ; + + if ( status !== 1 ) + #1 disable main ; + + + @(aux_char_valid) ; + if ( aux_received_char !== 8'd3 ) + begin + $display("Time %t ", $time) ; + $display("PS2 mouse didn't receive expected character! Expected %h, actual %h !", 3, aux_received_char ) ; + end + + data = 1 ; + status = 1 ; + + kbd_write(`KBD_CNTL_REG, `AUX_MAGIC_WRITE, status) ; + if ( status !== 1 ) + #1 disable main ; + + data = 1 ; + + kbd_write(`KBD_DATA_REG, `AUX_SET_SCALE21, status) ; + + if ( status !== 1 ) + #1 disable main ; + + @(aux_char_valid) ; + if ( {aux_received_char, 24'h000000} !== `AUX_SET_SCALE21) + begin + $display("Time %t ", $time) ; + $display("PS2 mouse didn't receive expected character! Expected %h, actual %h !", `AUX_SET_SCALE21, aux_received_char ) ; + end + + kbd_write(`KBD_CNTL_REG, `AUX_DISABLE, status) ; + if ( status !== 1 ) + #1 disable main ; + + kbd_write(`KBD_CNTL_REG, `KBD_WRITE_MODE, status) ; + if ( status !== 1 ) + #1 disable main ; + + kbd_write(`KBD_DATA_REG, `AUX_INTS_OFF, status) ; + if ( status !== 1 ) + #1 disable main ; + + data = 1 ; + + kbd_write(`KBD_CNTL_REG, `AUX_ENABLE, status) ; + if ( status !== 1 ) + #1 disable main ; + + kbd_write(`KBD_CNTL_REG, `AUX_MAGIC_WRITE, status) ; + if ( status !== 1 ) + #1 disable main ; + + data = 1 ; + + kbd_write(`KBD_DATA_REG, `AUX_ENABLE_DEV, status) ; + + if ( status !== 1 ) + #1 disable main ; + + @(aux_char_valid) ; + if ( {aux_received_char, 24'h000000} !== `AUX_ENABLE_DEV) + begin + $display("Time %t ", $time) ; + $display("PS2 mouse didn't receive expected character! Expected %h, actual %h !", `AUX_ENABLE_DEV, aux_received_char ) ; + end + + kbd_write(`KBD_CNTL_REG, `KBD_WRITE_MODE, status) ; + if ( status !== 1 ) + #1 disable main ; + + kbd_write(`KBD_DATA_REG, `AUX_INTS_ON, status) ; + if ( status !== 1 ) + #1 disable main ; + + watchdog_reset = !watchdog_reset ; + `endif + +end +endtask // initialize_controler + +task read_data_reg ; + output [7:0] return_byte_o ; + output ok_o ; + reg `READ_STIM_TYPE read_data ; + reg `READ_RETURN_TYPE read_status ; + reg `WB_TRANSFER_FLAGS flags ; + reg in_use ; +begin:main + if ( in_use === 1 ) + begin + $display("Task read_data_reg re-entered! Time %t", $time) ; + #1 disable main ; + end + else + in_use = 1 ; + + ok_o = 1 ; + flags`WB_TRANSFER_SIZE = 1 ; + flags`WB_TRANSFER_AUTO_RTY = 0 ; + flags`WB_TRANSFER_CAB = 0 ; + flags`INIT_WAITS = 0 ; + flags`SUBSEQ_WAITS = 0 ; + + read_data`READ_ADDRESS = `KBD_DATA_REG ; + read_data`READ_SEL = 4'h8 ; + + read_status = 0 ; + + i_wb_master.wb_single_read( read_data, flags, read_status ) ; + + if ( read_status`CYC_ACK !== 1'b1 ) + begin + $display("Error! Keyboard controler didn't acknowledge single read access!") ; + + ok_o = 0 ; + end + else + return_byte_o = read_status`READ_DATA ; + + in_use = 0 ; + +end +endtask //read_data_reg + +task read_status_reg ; + output [7:0] return_byte_o ; + output ok_o ; + reg `READ_STIM_TYPE read_data ; + reg `READ_RETURN_TYPE read_status ; + reg `WB_TRANSFER_FLAGS flags ; + reg in_use ; +begin:main + if ( in_use === 1 ) + begin + $display("Task read_status_reg re-entered! Time %t !", $time) ; + #1 disable main ; + end + else + in_use = 1 ; + + ok_o = 1 ; + flags`WB_TRANSFER_SIZE = 1 ; + flags`WB_TRANSFER_AUTO_RTY = 0 ; + flags`WB_TRANSFER_CAB = 0 ; + flags`INIT_WAITS = 0 ; + flags`SUBSEQ_WAITS = 0 ; + + read_data`READ_ADDRESS = `KBD_STATUS_REG ; + read_data`READ_SEL = 4'h8 ; + + read_status = 0 ; + + i_wb_master.wb_single_read( read_data, flags, read_status ) ; + + if ( read_status`CYC_ACK !== 1'b1 ) + begin + $display("Error! Keyboard controler didn't acknowledge single read access!") ; + error1 = 1'b1 ; + + ok_o = 0 ; + end + else + return_byte_o = read_status`READ_DATA ; + + in_use = 0 ; +end +endtask // read_status_reg + +task kbd_write ; + input [31:0] address_i ; + input [31:0] data_i ; + output ok_o ; + + reg `WRITE_STIM_TYPE write_data ; + reg `WRITE_RETURN_TYPE write_status ; + reg `WB_TRANSFER_FLAGS flags ; + reg [7:0] kbd_status ; +begin:main + ok_o = 1 ; + flags`WB_TRANSFER_SIZE = 1 ; + flags`WB_TRANSFER_AUTO_RTY = 0 ; + flags`WB_TRANSFER_CAB = 0 ; + flags`INIT_WAITS = 0 ; + flags`SUBSEQ_WAITS = 0 ; + + write_data`WRITE_ADDRESS = address_i ; + write_data`WRITE_DATA = data_i ; + write_data`WRITE_SEL = 4'h8 ; + + read_status_reg(kbd_status, ok_o) ; + + while( ok_o && ( kbd_status & `KBD_IBF )) + begin + read_status_reg(kbd_status, ok_o) ; + end + + if ( ok_o !== 1 ) + #1 disable main ; + + i_wb_master.wb_single_write( write_data, flags, write_status ) ; + + if ( write_status`CYC_ACK !== 1 ) + begin + $display("Error! Keyboard controller didn't acknowledge single write access") ; + error1 = 1'b1 ; + + ok_o = 0 ; + end +end +endtask // kbd_write + +task devider_write ; + input [31:0] address_i ; + input [31:16] data_i ; + output ok_o ; + + reg `WRITE_STIM_TYPE write_data ; + reg `WRITE_RETURN_TYPE write_status ; + reg `WB_TRANSFER_FLAGS flags ; +begin:main + ok_o = 1 ; + flags`WB_TRANSFER_SIZE = 1 ; + flags`WB_TRANSFER_AUTO_RTY = 0 ; + flags`WB_TRANSFER_CAB = 0 ; + flags`INIT_WAITS = 0 ; + flags`SUBSEQ_WAITS = 0 ; + + write_data`WRITE_ADDRESS = address_i ; + write_data`WRITE_DATA = {2{data_i}}; + write_data`WRITE_SEL = 4'hC ; + + i_wb_master.wb_single_write( write_data, flags, write_status ) ; + + if ( write_status`CYC_ACK !== 1 ) + begin + $display("Error! Keyboard controller didn't acknowledge single write access") ; + error1 = 1'b1 ; + + ok_o = 0 ; + end +end +endtask // devider_write + +task test_scan_code_receiving ; + reg ok_keyboard ; + reg ok_controler ; + reg ok ; + reg [7:0] data ; + reg [(MAX_SEQUENCE_LENGTH*8 - 1) : 0] keyboard_sequence ; + reg [(MAX_SEQUENCE_LENGTH*8 - 1) : 0] controler_sequence ; +begin:main + // prepare character sequence to send from keyboard to controler + // L SHIFT make + keyboard_sequence[7:0] = 8'h12 ; + // A make + keyboard_sequence[15:8] = 8'h1C ; + // A break + keyboard_sequence[23:16] = 8'hF0 ; + keyboard_sequence[31:24] = 8'h1C ; + // L SHIFT break + keyboard_sequence[39:32] = 8'hF0 ; + keyboard_sequence[47:40] = 8'h12 ; + + // prepare character sequence as it is received in scan code set 1 through the controler + // L SHIFT make + controler_sequence[7:0] = 8'h2A ; + // A make + controler_sequence[15:8] = 8'h1E ; + // A break + controler_sequence[23:16] = 8'h9E ; + // L SHIFT break + controler_sequence[31:24] = 8'hAA ; + + fork + begin + send_sequence( keyboard_sequence, 6, ok_keyboard ) ; + if ( ok_keyboard !== 1 ) + #1 disable main ; + end + begin + receive_sequence( controler_sequence, 4, ok_controler ) ; + + if ( ok_controler !== 1 ) + #1 disable main ; + end + join + + // test same thing with translation disabled! + kbd_write(`KBD_CNTL_REG, `KBD_WRITE_MODE, ok); + if ( ok !== 1 ) + #1 disable main ; + + kbd_write(`KBD_DATA_REG, `KBD_EKI|`KBD_SYS|`AUX_INTERRUPT_ON, ok); + if ( ok !== 1 ) + #1 disable main ; + + // since translation is disabled, controler sequence is the same as keyboard sequence + controler_sequence = keyboard_sequence ; + + fork + begin + + send_sequence( keyboard_sequence, 6, ok_keyboard ) ; + if ( ok_keyboard !== 1 ) + #1 disable main ; + + end + begin + receive_sequence( controler_sequence, 6, ok_controler ) ; + if ( ok_controler !== 1 ) + #1 disable main ; + end + join + + // turn translation on again + kbd_write(`KBD_CNTL_REG, `KBD_WRITE_MODE, ok); + if ( ok !== 1 ) + #1 disable main ; + + kbd_write(`KBD_DATA_REG, `KBD_EKI|`KBD_SYS|`AUX_INTERRUPT_ON|`KBD_KCC, ok); + if ( ok !== 1 ) + #1 disable main ; + + // test extended character receiving - rctrl + s combination + // prepare sequence to send from keyboard to controler + // R CTRL make + keyboard_sequence[7:0] = 8'hE0 ; + keyboard_sequence[15:8] = 8'h14 ; + // S make + keyboard_sequence[23:16] = 8'h1B ; + // S break + keyboard_sequence[31:24] = 8'hF0 ; + keyboard_sequence[39:32] = 8'h1B ; + // R CTRL break + keyboard_sequence[47:40] = 8'hE0 ; + keyboard_sequence[55:48] = 8'hF0 ; + keyboard_sequence[63:56] = 8'h14 ; + + // prepare sequence that should be received from the controler + // R CTRL make + controler_sequence[7:0] = 8'hE0 ; + controler_sequence[15:8] = 8'h1D ; + // S make + controler_sequence[23:16] = 8'h1F ; + // S break + controler_sequence[31:24] = 8'h9F ; + // R CTRL break + controler_sequence[39:32] = 8'hE0 ; + controler_sequence[47:40] = 8'h9D ; + + fork + begin + send_sequence( keyboard_sequence, 8, ok_keyboard ) ; + if ( ok_keyboard !== 1 ) + #1 disable main ; + end + begin + + receive_sequence( controler_sequence, 6, ok_controler ) ; + + if ( ok_controler !== 1 ) + #1 disable main ; + end + join + + // test same thing with translation disabled! + kbd_write(`KBD_CNTL_REG, `KBD_WRITE_MODE, ok); + if ( ok !== 1 ) + #1 disable main ; + + kbd_write(`KBD_DATA_REG, `KBD_EKI|`KBD_SYS|`AUX_INTERRUPT_ON, ok); + if ( ok !== 1 ) + #1 disable main ; + + // since translation is disabled, controler sequence is the same as keyboard sequence + controler_sequence = keyboard_sequence ; + + fork + begin + send_sequence( keyboard_sequence, 8, ok_keyboard ) ; + if ( ok_keyboard !== 1 ) + #1 disable main ; + end + begin + + receive_sequence( controler_sequence, 8, ok_controler ) ; + + if ( ok_controler !== 1 ) + #1 disable main ; + end + join + + watchdog_reset = !watchdog_reset ; +end +endtask // test_scan_code_receiving + +task test_normal_scancodes ; + reg ok ; + reg ok_keyboard ; + reg ok_controler ; + integer i ; + reg [(MAX_SEQUENCE_LENGTH*8 - 1) : 0] keyboard_sequence ; + reg [(MAX_SEQUENCE_LENGTH*8 - 1) : 0] controler_sequence ; +begin:main + // turn translation on + kbd_write(`KBD_CNTL_REG, `KBD_WRITE_MODE, ok); + if ( ok !== 1 ) + #1 disable main ; + + kbd_write(`KBD_DATA_REG, `KBD_EKI|`KBD_SYS|`AUX_INTERRUPT_ON|`KBD_KCC, ok); + if ( ok !== 1 ) + #1 disable main ; + + for ( i = 0 ; i < `PS2_NUM_OF_NORMAL_SCANCODES ; i = i + 1 ) + begin + keyboard_sequence[7:0] = normal_scancode_set2_mem[i] ; + keyboard_sequence[15:8] = 8'hF0 ; + keyboard_sequence[23:16] = normal_scancode_set2_mem[i] ; + + controler_sequence[7:0] = normal_scancode_set1_mem[i] ; + controler_sequence[15:8] = normal_scancode_set1_mem[i] | 8'h80 ; + fork + begin + send_sequence( keyboard_sequence, 3, ok_keyboard ) ; + if ( ok_keyboard !== 1 ) + #1 disable main ; + end + begin + receive_sequence( controler_sequence, 2, ok_controler ) ; + if ( ok_controler !== 1 ) + #1 disable main ; + end + join + end + + watchdog_reset = !watchdog_reset ; + +end +endtask // test_normal_scancodes + +task test_extended_scancodes ; + reg ok ; + reg ok_keyboard ; + reg ok_controler ; + integer i ; + reg [(MAX_SEQUENCE_LENGTH*8 - 1) : 0] keyboard_sequence ; + reg [(MAX_SEQUENCE_LENGTH*8 - 1) : 0] controler_sequence ; +begin:main + // turn translation on + kbd_write(`KBD_CNTL_REG, `KBD_WRITE_MODE, ok); + if ( ok !== 1 ) + #1 disable main ; + + kbd_write(`KBD_DATA_REG, `KBD_EKI|`KBD_SYS|`AUX_INTERRUPT_ON|`KBD_KCC, ok); + if ( ok !== 1 ) + #1 disable main ; + + for ( i = 0 ; i < `PS2_NUM_OF_EXTENDED_SCANCODES ; i = i + 1 ) + begin + keyboard_sequence[7:0] = 8'hE0 ; + keyboard_sequence[15:8] = extended_scancode_set2_mem[i] ; + keyboard_sequence[23:16] = 8'hE0 ; + keyboard_sequence[31:24] = 8'hF0 ; + keyboard_sequence[39:32] = extended_scancode_set2_mem[i] ; + + controler_sequence[7:0] = 8'hE0 ; + controler_sequence[15:8] = extended_scancode_set1_mem[i] ; + controler_sequence[23:16] = 8'hE0 ; + controler_sequence[31:24] = extended_scancode_set1_mem[i] | 8'h80 ; + fork + begin + send_sequence( keyboard_sequence, 5, ok_keyboard ) ; + if ( ok_keyboard !== 1 ) + #1 disable main ; + end + begin + receive_sequence( controler_sequence, 4, ok_controler ) ; + if ( ok_controler !== 1 ) + #1 disable main ; + end + join + end + + watchdog_reset = !watchdog_reset ; + +end +endtask // test_extended_scancodes + +task return_scan_code_on_irq ; + output [7:0] scan_code_o ; + output ok_o ; + reg [7:0] temp_data ; +begin:main + wait ( wb_int === 1 ) ; + read_status_reg( temp_data, ok_o ) ; + + if ( ok_o !== 1'b1 ) + #1 disable main ; + + if ( !( temp_data & `KBD_OBF ) ) + begin + $display("Error! Interrupt received from keyboard controler when OBF status not set!") ; + error1 = 1'b1 ; + + end + + if ( temp_data & `AUX_OBUF_FULL ) + begin + $display("Error! Interrupt received from keyboard controler when AUX_OBUF_FULL status was set!") ; + error1 = 1'b1 ; + + end + + read_data_reg( temp_data, ok_o ) ; + + if ( ok_o !== 1'b1 ) + #1 disable main ; + + scan_code_o = temp_data ; +end +endtask // return_scan_code_on_irq + +task send_sequence ; + input [(MAX_SEQUENCE_LENGTH*8 - 1) : 0] sequence_i ; + input [31:0] num_of_chars_i ; + output ok_o ; + reg [7:0] current_char ; + integer i ; + reg ok ; + reg error ; +begin:main + + error = 0 ; + ok_o = 1 ; + ok = 0 ; + + for( i = 0 ; i < num_of_chars_i ; i = i + 1 ) + begin + current_char = sequence_i[7:0] ; + + sequence_i = sequence_i >> 8 ; + ok = 0 ; + error = 0 ; + while ( (ok !== 1) && (error === 0) ) + begin + i_ps2_keyboard_model.kbd_send_char + ( + current_char, + ok, + error + ) ; + end + + if ( error ) + begin + $display("Time %t", $time) ; + $display("Keyboard model signaled an error!") ; + ok_o = 0 ; + #1 disable main ; + end + end +end +endtask // send_sequence + +task receive_sequence ; + input [(MAX_SEQUENCE_LENGTH*8 - 1) : 0] sequence_i ; + input [31:0] num_of_chars_i ; + output ok_o ; + reg [7:0] current_char ; + reg [7:0] data ; + integer i ; +begin:main + + ok_o = 1 ; + + for( i = 0 ; i < num_of_chars_i ; i = i + 1 ) + begin + current_char = sequence_i[7:0] ; + + sequence_i = sequence_i >> 8 ; + + return_scan_code_on_irq( data, ok_o ) ; + + if ( ok_o !== 1 ) + #1 disable main ; + + if ( data !== current_char ) + begin + $display("Time %t", $time) ; + $display("Error! Character received was wrong!") ; + $display("Expected character: %h, received %h ", current_char, data ) ; + end + end +end +endtask // receive_seqence + +task test_keyboard_inhibit ; + reg ok_controler ; + reg ok_keyboard ; + reg error ; + reg [7:0] data ; +begin:main + // first test, if keyboard stays inhibited after character is received, but not read from the controler + + i_ps2_keyboard_model.kbd_send_char + ( + 8'hE0, + ok_keyboard, + error + ) ; + + if ( error ) + begin + $display("Error! Keyboard signaled an error while sending character!") ; + #1 disable main ; + end + + if ( !ok_keyboard ) + begin + $display("Something is wrong! Keyboard wasn't able to send a character!") ; + #1 disable main ; + end + + // wait 5 us to see, if keyboard is inhibited + #60000 ; + + // now check, if clock line is low! + if ( kbd_clk_cable !== 0 ) + begin + $display("Error! Keyboard wasn't inhibited when output buffer was filled!") ; + #1 disable main ; + end + + // now read the character from input buffer and check if clock was released + return_scan_code_on_irq( data, ok_controler ) ; + if ( ok_controler !== 1'b1 ) + #1 disable main ; + + if ( data !== 8'hE0 ) + begin + $display("Time %t", $time) ; + $display("Error! Character read from controler not as expected!") ; + end + + fork + begin + repeat(10) + @(posedge wb_clock) ; + + if ( kbd_clk_cable !== 1 ) + begin + $display("Error! Keyboard wasn't released from inhibited state when output buffer was read!") ; + #1 disable main ; + end + end + begin + i_ps2_keyboard_model.kbd_send_char + ( + 8'h1C, + ok_keyboard, + error + ) ; + if ( !ok_keyboard ) + begin + $display("Something is wrong! Keyboard wasn't able to send a character!") ; + #1 disable main ; + end + end + begin + return_scan_code_on_irq( data, ok_controler ) ; + if ( ok_controler !== 1'b1 ) + #1 disable main ; + + if ( data !== 8'h1E ) + begin + $display("Time %t", $time) ; + $display("Error! Character read from controler not as expected!") ; + end + end + join + + // disable keyboard controler + kbd_write( `KBD_CNTL_REG, `KBD_WRITE_MODE, ok_controler ) ; + if ( ok_controler !== 1 ) + #1 disable main ; + + kbd_write(`KBD_DATA_REG, `KBD_EKI|`KBD_SYS|`AUX_INTERRUPT_ON|`KBD_KCC | `KBD_DISABLE_COMMAND, ok_controler); + + if ( ok_controler !== 1 ) + #1 disable main ; + + repeat( 5 ) + @(posedge wb_clock) ; + + // now check, if clock line is high! + if ( kbd_clk_cable !== 1 ) + begin + $display("Error! Keyboard is not supposed to be inhibited when keyboard controler is disabled!") ; + #1 disable main ; + end + + // send character and enable keyboard controler at the same time + fork + begin + i_ps2_keyboard_model.kbd_send_char + ( + 8'hE0, + ok_keyboard, + error + ) ; + + if ( !ok_keyboard ) + begin + $display("Something is wrong! Keyboard wasn't able to send a character!") ; + #1 disable main ; + end + end + begin + // enable keyboard controler + kbd_write( `KBD_CNTL_REG, `KBD_WRITE_MODE, ok_controler ) ; + if ( ok_controler !== 1 ) + #1 disable main ; + + kbd_write(`KBD_DATA_REG, `KBD_EKI|`KBD_SYS|`AUX_INTERRUPT_ON|`KBD_KCC, ok_controler); + if ( ok_controler !== 1 ) + #1 disable main ; + end + begin + return_scan_code_on_irq( data, ok_controler ) ; + if ( ok_controler !== 1'b1 ) + #1 disable main ; + + if ( data !== 8'hE0 ) + begin + $display("Time %t", $time) ; + $display("Error! Character read from controler not as expected!") ; + end + end + join + + // do D2 command, that copies parameter in input buffer to output buffer + kbd_write( `KBD_CNTL_REG, 32'hD2_00_00_00, ok_controler ) ; + if ( ok_controler !== 1 ) + #1 disable main ; + + kbd_write(`KBD_DATA_REG, 32'h5555_5555, ok_controler) ; + + if ( ok_controler !== 1 ) + #1 disable main ; + + return_scan_code_on_irq( data, ok_controler ) ; + if ( ok_controler !== 1 ) + #1 disable main ; + + if ( data !== 8'h55 ) + begin + $display("Error! D2 command doesn't work properly") ; + end + +end +endtask // test_keyboard_inhibit + +task test_print_screen_and_pause_scancodes ; + reg ok ; + reg ok_keyboard ; + reg ok_controler ; + integer i ; + reg [(MAX_SEQUENCE_LENGTH*8 - 1) : 0] keyboard_sequence ; + reg [(MAX_SEQUENCE_LENGTH*8 - 1) : 0] controler_sequence ; +begin:main + // turn translation on + kbd_write(`KBD_CNTL_REG, `KBD_WRITE_MODE, ok); + if ( ok !== 1 ) + #1 disable main ; + + kbd_write(`KBD_DATA_REG, `KBD_EKI|`KBD_SYS|`AUX_INTERRUPT_ON|`KBD_KCC, ok); + if ( ok !== 1 ) + #1 disable main ; + + // prepare character sequence to send from keyboard to controler - pause + keyboard_sequence[7:0] = 8'hE1 ; + keyboard_sequence[15:8] = 8'h14 ; + keyboard_sequence[23:16] = 8'h77 ; + keyboard_sequence[31:24] = 8'hE1 ; + keyboard_sequence[39:32] = 8'hF0 ; + keyboard_sequence[47:40] = 8'h14 ; + keyboard_sequence[55:48] = 8'hF0 ; + keyboard_sequence[63:56] = 8'h77 ; + + // prepare character sequence as it is received in scan code set 1 through the controler + controler_sequence[7:0] = 8'hE1 ; + controler_sequence[15:8] = 8'h1D ; + controler_sequence[23:16] = 8'h45 ; + controler_sequence[31:24] = 8'hE1 ; + controler_sequence[39:32] = 8'h9D ; + controler_sequence[47:40] = 8'hC5 ; + + fork + begin + send_sequence( keyboard_sequence, 8, ok_keyboard ) ; + if ( ok_keyboard !== 1 ) + #1 disable main ; + end + begin + receive_sequence( controler_sequence, 6, ok_controler ) ; + if ( ok_controler !== 1 ) + #1 disable main ; + end + join + + // prepare character sequence to send from keyboard to controler - make print screen + keyboard_sequence[7:0] = 8'hE0 ; + keyboard_sequence[15:8] = 8'h12 ; + keyboard_sequence[23:16] = 8'hE0 ; + keyboard_sequence[31:24] = 8'h7C ; + + // prepare character sequence as it is received in scan code set 1 through the controler + controler_sequence[7:0] = 8'hE0 ; + controler_sequence[15:8] = 8'h2A ; + controler_sequence[23:16] = 8'hE0 ; + controler_sequence[31:24] = 8'h37 ; + + fork + begin + send_sequence( keyboard_sequence, 4, ok_keyboard ) ; + if ( ok_keyboard !== 1 ) + #1 disable main ; + end + begin + receive_sequence( controler_sequence, 4, ok_controler ) ; + if ( ok_controler !== 1 ) + #1 disable main ; + end + join + + // prepare character sequence to send from keyboard to controler - break print screen + keyboard_sequence[7:0] = 8'hE0 ; + keyboard_sequence[15:8] = 8'hF0 ; + keyboard_sequence[23:16] = 8'h7C ; + keyboard_sequence[31:24] = 8'hE0 ; + keyboard_sequence[39:32] = 8'hF0 ; + keyboard_sequence[47:40] = 8'h12 ; + + // prepare character sequence as it is received in scan code set 1 through the controler + controler_sequence[7:0] = 8'hE0 ; + controler_sequence[15:8] = 8'hB7 ; + controler_sequence[23:16] = 8'hE0 ; + controler_sequence[31:24] = 8'hAA ; + + fork + begin + send_sequence( keyboard_sequence, 6, ok_keyboard ) ; + if ( ok_keyboard !== 1 ) + #1 disable main ; + end + begin + receive_sequence( controler_sequence, 4, ok_controler ) ; + if ( ok_controler !== 1 ) + #1 disable main ; + end + join +end +endtask // test_print_screen_and_pause_scancodes + +`ifdef PS2_AUX +task receive_mouse_movement; + reg [7:0] mouse_data_received ; + reg ok_mouse ; + reg ok_wb ; + reg error ; + integer num_of_mouse_data_sent ; +begin:main + error = 0 ; + num_of_mouse_data_sent = 0 ; + while ( !stop_mouse_tests ) + begin + fork + begin + ok_mouse = 0 ; + while ( !ok_mouse && !error ) + begin + i_ps2_mouse_model.kbd_send_char + ( + num_of_mouse_data_sent[7:0], + ok_mouse, + error + ) ; + end + if ( error ) + begin + $display("Mouse model signaled an error while transmiting data! Time %t", $time) ; + #1 disable main ; + end + else + num_of_mouse_data_sent = num_of_mouse_data_sent + 1 ; + + end + begin + return_mouse_data_on_irq( mouse_data_received, ok_wb ) ; + if ( !ok_wb ) + #1 disable main ; + + if ( mouse_data_received !== num_of_mouse_data_sent[7:0] ) + begin + $display("Time %t", $time) ; + $display("Data received from mouse has unexpected value! Expected %h, actual %h", num_of_mouse_data_sent[7:0], mouse_data_received) ; + end + end + join + end + + $display("Number of chars received from mouse %d", num_of_mouse_data_sent) ; +end +endtask //receive_mouse_movement + +task return_mouse_data_on_irq ; + output [7:0] mouse_data_o ; + output ok_o ; + reg [7:0] temp_data ; +begin:main + wait ( wb_intb === 1 ) ; + + wait ( ps2_test_bench.read_status_reg.in_use !== 1'b1 ); + + read_status_reg( temp_data, ok_o ) ; + + if ( ok_o !== 1'b1 ) + #1 disable main ; + + if ( !( temp_data & `AUX_OBUF_FULL ) || !(temp_data & `KBD_OBF)) + begin + $display("Error! Interrupt b received from controler when AUX_OBF status or KBD_OBF statuses not set!") ; + + end + + wait ( ps2_test_bench.read_data_reg.in_use !== 1'b1 ); + + read_data_reg( temp_data, ok_o ) ; + + if ( ok_o !== 1'b1 ) + #1 disable main ; + + mouse_data_o = temp_data ; +end +endtask // return_scan_code_on_irq +`endif + +endmodule // ps2_test_bench Index: tags/rel_13/bench/verilog/ps2_sim_top.v =================================================================== --- tags/rel_13/bench/verilog/ps2_sim_top.v (nonexistent) +++ tags/rel_13/bench/verilog/ps2_sim_top.v (revision 42) @@ -0,0 +1,163 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// ps2_sim_top.v //// +//// //// +//// This file is part of the "ps2" project //// +//// http://www.opencores.org/cores/ps2/ //// +//// //// +//// Author(s): //// +//// - mihad@opencores.org //// +//// - Miha Dolenc //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: not supported by cvs2svn $ +// Revision 1.4 2003/07/01 12:33:45 mihad +// Added an option to use constant values instead of RAM +// in the translation table. +// +// Revision 1.3 2003/05/28 16:26:51 simons +// Change the address width. +// +// Revision 1.2 2002/04/09 13:16:04 mihad +// Mouse interface added +// +// Revision 1.1.1.1 2002/02/18 16:16:55 mihad +// Initial project import - working +// +// + +`include "ps2_defines.v" +module ps2_sim_top +( + wb_clk_i, + wb_rst_i, + wb_cyc_i, + wb_stb_i, + wb_we_i, + wb_sel_i, + wb_adr_i, + wb_dat_i, + wb_dat_o, + wb_ack_o, + + wb_int_o, + + ps2_kbd_clk_io, + ps2_kbd_data_io + + `ifdef PS2_AUX + , + wb_intb_o, + + ps2_aux_clk_io, + ps2_aux_data_io + `endif +) ; + +input wb_clk_i, + wb_rst_i, + wb_cyc_i, + wb_stb_i, + wb_we_i ; + +input [3:0] wb_sel_i ; + +input [3:0] wb_adr_i ; +input [31:0] wb_dat_i ; + +output [31:0] wb_dat_o ; + +output wb_ack_o, + wb_int_o ; + +inout ps2_kbd_clk_io, + ps2_kbd_data_io ; +`ifdef PS2_AUX +output wb_intb_o ; +inout ps2_aux_clk_io ; +inout ps2_aux_data_io ; +`endif + +wire ps2_kbd_clk_pad_i = ps2_kbd_clk_io ; +wire ps2_kbd_data_pad_i = ps2_kbd_data_io ; + +wire ps2_kbd_clk_pad_o, + ps2_kbd_data_pad_o, + ps2_kbd_clk_pad_oe_o, + ps2_kbd_data_pad_oe_o ; + +ps2_top i_ps2_top +( + .wb_clk_i (wb_clk_i), + .wb_rst_i (wb_rst_i), + .wb_cyc_i (wb_cyc_i), + .wb_stb_i (wb_stb_i), + .wb_we_i (wb_we_i), + .wb_sel_i (wb_sel_i), + .wb_adr_i (wb_adr_i), + .wb_dat_i (wb_dat_i), + .wb_dat_o (wb_dat_o), + .wb_ack_o (wb_ack_o), + + .wb_int_o (wb_int_o), + + .ps2_kbd_clk_pad_i (ps2_kbd_clk_pad_i), + .ps2_kbd_data_pad_i (ps2_kbd_data_pad_i), + .ps2_kbd_clk_pad_o (ps2_kbd_clk_pad_o), + .ps2_kbd_data_pad_o (ps2_kbd_data_pad_o), + .ps2_kbd_clk_pad_oe_o (ps2_kbd_clk_pad_oe_o), + .ps2_kbd_data_pad_oe_o (ps2_kbd_data_pad_oe_o) + + `ifdef PS2_AUX + , + .wb_intb_o (wb_intb_o), + + .ps2_aux_clk_pad_i (ps2_aux_clk_io), + .ps2_aux_data_pad_i (ps2_aux_data_io), + .ps2_aux_clk_pad_o (ps2_aux_clk_pad_o), + .ps2_aux_data_pad_o (ps2_aux_data_pad_o), + .ps2_aux_clk_pad_oe_o (ps2_aux_clk_pad_oe_o), + .ps2_aux_data_pad_oe_o (ps2_aux_data_pad_oe_o) + `endif +) ; + +assign ps2_kbd_clk_io = ps2_kbd_clk_pad_oe_o ? ps2_kbd_clk_pad_o : 1'bz ; +assign ps2_kbd_data_io = ps2_kbd_data_pad_oe_o ? ps2_kbd_data_pad_o : 1'bz ; + +`ifdef PS2_AUX +assign ps2_aux_clk_io = ps2_aux_clk_pad_oe_o ? ps2_aux_clk_pad_o : 1'bz ; +assign ps2_aux_data_io = ps2_aux_data_pad_oe_o ? ps2_aux_data_pad_o : 1'bz ; +`endif +endmodule Index: tags/rel_13/bench/verilog/ps2_testbench_defines.v =================================================================== --- tags/rel_13/bench/verilog/ps2_testbench_defines.v (nonexistent) +++ tags/rel_13/bench/verilog/ps2_testbench_defines.v (revision 42) @@ -0,0 +1,153 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// ps2_testbench_defines.v //// +//// //// +//// This file is part of the "ps2" project //// +//// http://www.opencores.org/cores/ps2/ //// +//// //// +//// Author(s): //// +//// - mihad@opencores.org //// +//// - Miha Dolenc //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: not supported by cvs2svn $ +// Revision 1.2 2002/04/09 13:17:38 mihad +// Mouse interface testcases added +// +// Revision 1.1.1.1 2002/02/18 16:16:56 mihad +// Initial project import - working +// +// + +//=================================================================================== +// User-unchangeable testbench defines (constants) +//=================================================================================== + +// setup and hold time definitions for WISHBONE - used in BFMs for signal generation +`define Tsetup 2 +`define Thold 2 + +// how many clock cycles should model wait for design's response - integer 32 bit value +`define WAIT_FOR_RESPONSE 6 + +// maximum number of transactions allowed in single call to block or cab transfer routines +`define MAX_BLK_SIZE 8 + +// maximum retry terminations allows for WISHBONE master to repeat an access +`define WB_TB_MAX_RTY 1000 + + +// some common types and defines +`define WB_ADDR_WIDTH 32 +`define WB_DATA_WIDTH 32 +`define WB_SEL_WIDTH `WB_DATA_WIDTH/8 +`define WB_TAG_WIDTH 1 +`define WB_ADDR_TYPE [(`WB_ADDR_WIDTH - 1):0] +`define WB_DATA_TYPE [(`WB_DATA_WIDTH - 1):0] +`define WB_SEL_TYPE [(`WB_SEL_WIDTH - 1):0] +`define WB_TAG_TYPE [(`WB_TAG_WIDTH - 1):0] + +// definitions file only for testbench usage +// wishbone master behavioral defines +// flags type for wishbone cycle initialization +`define CYC_FLAG_TYPE [0:0] +// cab flag field in cycle initialization data +`define CYC_CAB_FLAG [0] +// read cycle stimulus - consists of: +// - address field - which address read will be performed from +// - sel field - what byte select value should be +// - tag field - what tag values should be put on the bus +`define READ_STIM_TYPE [(`WB_ADDR_WIDTH + `WB_SEL_WIDTH + `WB_TAG_WIDTH - 1):0] +`define READ_STIM_LENGTH (`WB_ADDR_WIDTH + `WB_SEL_WIDTH + `WB_TAG_WIDTH) +`define READ_ADDRESS [(`WB_ADDR_WIDTH - 1):0] +`define READ_SEL [(`WB_ADDR_WIDTH + `WB_SEL_WIDTH - 1):`WB_ADDR_WIDTH] +`define READ_TAG_STIM [(`WB_ADDR_WIDTH + `WB_SEL_WIDTH + `WB_TAG_WIDTH - 1):(`WB_ADDR_WIDTH + `WB_SEL_WIDTH)] + +// read cycle return type consists of: +// - read data field +// - tag field received from WISHBONE +// - wishbone slave response fields - ACK, ERR and RTY +// - test bench error indicator (when testcase has not used wb master model properly) +// - how much data was actually transfered +`define READ_RETURN_TYPE [(32 + 4 + `WB_DATA_WIDTH + `WB_TAG_WIDTH - 1):0] +`define READ_DATA [(32 + `WB_DATA_WIDTH + 4 - 1):32 + 4] +`define READ_TAG_RET [(32 + 4 + `WB_DATA_WIDTH + `WB_TAG_WIDTH - 1):(`WB_DATA_WIDTH + 32 + 4)] +`define READ_RETURN_LENGTH (32 + 4 + `WB_DATA_WIDTH + `WB_TAG_WIDTH - 1) + +// write cycle stimulus type consists of +// - address field +// - data field +// - sel field +// - tag field +`define WRITE_STIM_TYPE [(`WB_ADDR_WIDTH + `WB_DATA_WIDTH + `WB_SEL_WIDTH + `WB_TAG_WIDTH - 1):0] +`define WRITE_ADDRESS [(`WB_ADDR_WIDTH - 1):0] +`define WRITE_DATA [(`WB_ADDR_WIDTH + `WB_DATA_WIDTH - 1):`WB_ADDR_WIDTH] +`define WRITE_SEL [(`WB_ADDR_WIDTH + `WB_DATA_WIDTH + `WB_SEL_WIDTH - 1):(`WB_ADDR_WIDTH + `WB_DATA_WIDTH)] +`define WRITE_TAG_STIM [(`WB_ADDR_WIDTH + `WB_DATA_WIDTH + `WB_SEL_WIDTH + `WB_TAG_WIDTH - 1):(`WB_ADDR_WIDTH + `WB_DATA_WIDTH + `WB_SEL_WIDTH)] + +// length of WRITE_STIMULUS +`define WRITE_STIM_LENGTH (`WB_ADDR_WIDTH + `WB_DATA_WIDTH + `WB_SEL_WIDTH + `WB_TAG_WIDTH) + +// write cycle return type consists of: +// - test bench error indicator (when testcase has not used wb master model properly) +// - wishbone slave response fields - ACK, ERR and RTY +// - tag field received from WISHBONE +// - how much data was actually transfered +`define WRITE_RETURN_TYPE [(32 + 4 + `WB_TAG_WIDTH - 1):0] +`define WRITE_TAG_RET [(32 + 4 + `WB_TAG_WIDTH - 1):32 + 4] + +// this four fields are common to both read and write routines return values +`define TB_ERROR_BIT [0] +`define CYC_ACK [1] +`define CYC_RTY [2] +`define CYC_ERR [3] +`define CYC_RESPONSE [3:1] +`define CYC_ACTUAL_TRANSFER [35:4] + +// block transfer flags +`define WB_TRANSFER_FLAGS [41:0] +// consists of: +// - number of transfer cycles to perform +// - flag that enables retry termination handling - if disabled, block transfer routines will return on any termination other than acknowledge +// - flag indicating CAB transfer is to be performed - ignored by all single transfer routines +// - number of initial wait states to insert +// - number of subsequent wait states to insert +`define WB_TRANSFER_SIZE [41:10] +`define WB_TRANSFER_AUTO_RTY [8] +`define WB_TRANSFER_CAB [9] +`define INIT_WAITS [3:0] +`define SUBSEQ_WAITS [7:4] + +`define WB_FREQ 0.10 Index: tags/rel_13/bench/verilog/ps2_keyboard_model.v =================================================================== --- tags/rel_13/bench/verilog/ps2_keyboard_model.v (nonexistent) +++ tags/rel_13/bench/verilog/ps2_keyboard_model.v (revision 42) @@ -0,0 +1,296 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// ps2_keyboard_model.v //// +//// //// +//// This file is part of the "ps2" project //// +//// http://www.opencores.org/cores/ps2/ //// +//// //// +//// Author(s): //// +//// - mihad@opencores.org //// +//// - Miha Dolenc //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: not supported by cvs2svn $ +// Revision 1.2 2002/04/09 13:15:16 mihad +// Wrong acknowledge generation during receiving repaired +// +// Revision 1.1.1.1 2002/02/18 16:16:55 mihad +// Initial project import - working +// +// + +`include "timescale.v" + +module ps2_keyboard_model +( + kbd_clk_io, + kbd_data_io, + last_char_received_o, + char_valid_o +); + +parameter [31:0] kbd_clk_period = 50000; // chould be between 33 and 50 us to generate the clock between 30 and 20 kHz + +inout kbd_clk_io, + kbd_data_io ; + +output [7:0] last_char_received_o ; +reg [7:0] last_char_received_o ; + +output char_valid_o ; +reg char_valid_o ; + +reg kbd_clk, + kbd_data ; + +assign kbd_clk_io = kbd_clk ? 1'bz : 1'b0 ; +assign kbd_data_io = kbd_data ? 1'bz : 1'b0 ; + +reg receiving ; +initial +begin + kbd_clk = 1'b1 ; + kbd_data = 1'b1 ; + + last_char_received_o = 0 ; + char_valid_o = 0 ; + + receiving = 0 ; +end + +always@(kbd_data_io or kbd_clk_io) +begin + // check if host is driving keyboard data low and doesn't drive clock + if ( !kbd_data_io && kbd_data && kbd_clk_io) + begin + // wait for half of clock period + #(kbd_clk_period/2) ; + + // state hasn't changed - host wishes to send data - go receiving + if ( !kbd_data_io && kbd_data && kbd_clk_io) + kbd_receive_char(last_char_received_o) ; + end +end + +task kbd_send_char ; + input [7:0] char ; + output transmited_ok ; + output severe_error ; + reg [10:0] tx_reg ; + integer i ; +begin:main + severe_error = 1'b0 ; + transmited_ok = 1'b0 ; + + wait ( !receiving ) ; + + tx_reg = { 1'b1, !(^char), char, 1'b0 } ; + + fork + begin:wait_for_idle + wait( (kbd_clk_io === 1'b1) && (kbd_data_io === 1'b1) ) ; + // disable timeout ; + end + /*begin:timeout + #(256 * kbd_clk_period) ; + $display("Error! Keyboard bus did not go idle in 256 keyboard clock cycles time!") ; + severe_error = 1'b1 ; + transmited_ok = 1'b0 ; + disable main ; + end*/ + join + + #(kbd_clk_period/2) ; + if ( !kbd_clk_io ) + begin + transmited_ok = 1'b0 ; + kbd_data = 1'b1 ; + disable main ; + end + + i = 0 ; + while ( i < 11 ) + begin + kbd_data = tx_reg[i] ; + + #(kbd_clk_period/2) ; + + if ( !kbd_clk_io ) + begin + transmited_ok = 1'b0 ; + kbd_data = 1'b1 ; + disable main ; + end + + kbd_clk = 1'b0 ; + + i = i + 1 ; + + #(kbd_clk_period/2) ; + kbd_clk = 1'b1 ; + end + + if ( i == 11 ) + transmited_ok = 1'b1 ; +end +endtask // kbd_send_char + +task kbd_receive_char; + output [7:0] char ; + reg parity ; + integer i ; + reg stop_clocking ; +begin:main + i = 0 ; + receiving = 1 ; + stop_clocking = 1'b0 ; + + #(kbd_clk_period/2) ; + + while ( !stop_clocking ) + begin + + if ( !kbd_clk_io ) + begin + receiving = 0 ; + disable main ; + end + + kbd_clk = 1'b0 ; + + #(kbd_clk_period/2) ; + + kbd_clk = 1'b1 ; + + if ( i > 0 ) + begin + if ( i <= 8 ) + char[i - 1] = kbd_data_io ; + else if ( i == 9 ) + begin + parity = kbd_data_io ; + if ( parity !== ( !(^char) ) ) + $display("Invalid parity bit received") ; + end + end + + i = i + 1 ; + #(kbd_clk_period/4) ; + if ( i > 9 ) + begin + if ( kbd_data_io === 1'b1 ) + begin + kbd_data <= 1'b0 ; + stop_clocking = 1'b1 ; + end + end + + #(kbd_clk_period/4) ; + end + + kbd_clk = 1'b0 ; + + #(kbd_clk_period/2) ; + kbd_clk <= 1'b1 ; + kbd_data <= 1'b1 ; + + receiving = 0 ; + + if ( i === 10 ) + begin + char_valid_o = !char_valid_o ; + end +end +endtask // kbd_receive_char + + +time last_clk_low; +time last_clk_diference; + + + +initial +begin +last_clk_low =0; +last_clk_diference =0; + +end + +always @(negedge kbd_clk_io) + + begin:low_time_check + if (kbd_clk == 1) + begin + last_clk_low =$time; + fork + begin + #61000 + $display(" clock low more then 61us"); + $display("Time %t", $time) ; + #30000 + $display("error clock low more then 90usec"); + $display("Time %t", $time) ; + $stop; + end + begin + @(posedge kbd_clk_io); + disable low_time_check; + end + join + end + end + + + + +always @(posedge kbd_clk_io ) + begin + if (last_clk_low >0 ) + begin + last_clk_diference = $time - last_clk_low; + if (last_clk_diference < 60000) + begin + $display("error time< 60u"); + #100 $stop; + end + end + end + + + + + + +endmodule // ps2_keyboard_model Index: tags/rel_13/bench/verilog/wb_master_behavioral.v =================================================================== --- tags/rel_13/bench/verilog/wb_master_behavioral.v (nonexistent) +++ tags/rel_13/bench/verilog/wb_master_behavioral.v (revision 42) @@ -0,0 +1,773 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// wb_master_behavioral.v //// +//// //// +//// This file is part of the "ps2" project //// +//// http://www.opencores.org/cores/ps2/ //// +//// //// +//// Author(s): //// +//// - mihad@opencores.org //// +//// - Miha Dolenc //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: not supported by cvs2svn $ +// + +`include "ps2_testbench_defines.v" +`include "timescale.v" +module WB_MASTER_BEHAVIORAL +( + CLK_I, + RST_I, + TAG_I, + TAG_O, + ACK_I, + ADR_O, + CYC_O, + DAT_I, + DAT_O, + ERR_I, + RTY_I, + SEL_O, + STB_O, + WE_O, + CAB_O +); + + input CLK_I; + input RST_I; + input `WB_TAG_TYPE TAG_I; + output `WB_TAG_TYPE TAG_O; + input ACK_I; + output `WB_ADDR_TYPE ADR_O; + output CYC_O; + input `WB_DATA_TYPE DAT_I; + output `WB_DATA_TYPE DAT_O; + input ERR_I; + input RTY_I; + output `WB_SEL_TYPE SEL_O; + output STB_O; + output WE_O; + output CAB_O; + +// instantiate low level master module +WB_MASTER32 wbm_low_level +( + .CLK_I(CLK_I), + .RST_I(RST_I), + .TAG_I(TAG_I), + .TAG_O(TAG_O), + .ACK_I(ACK_I), + .ADR_O(ADR_O), + .CYC_O(CYC_O), + .DAT_I(DAT_I), + .DAT_O(DAT_O), + .ERR_I(ERR_I), + .RTY_I(RTY_I), + .SEL_O(SEL_O), + .STB_O(STB_O), + .WE_O(WE_O), + .CAB_O(CAB_O) +) ; + +// block read and write buffers definition +// single write buffer +reg `WRITE_STIM_TYPE blk_write_data [0:(`MAX_BLK_SIZE - 1)] ; +// read stimulus buffer - addresses, tags, selects etc. +reg `READ_STIM_TYPE blk_read_data_in [0:(`MAX_BLK_SIZE - 1)] ; +// read return buffer - data and tags received while performing block reads +reg `READ_RETURN_TYPE blk_read_data_out [0:(`MAX_BLK_SIZE - 1)] ; + +// single write task +task wb_single_write ; + input `WRITE_STIM_TYPE write_data ; + input `WB_TRANSFER_FLAGS write_flags ; + inout `WRITE_RETURN_TYPE return ; + reg in_use ; + reg cab ; + reg ok ; + integer cyc_count ; + integer rty_count ; + reg retry ; +begin:main + + return`TB_ERROR_BIT = 1'b0 ; + cab = 0 ; + return`CYC_ACTUAL_TRANSFER = 0 ; + rty_count = 0 ; + + // check if task was called before previous call finished + if ( in_use === 1 ) + begin + $display("*E, wb_single_write routine re-entered! Time %t ", $time) ; + return`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + in_use = 1 ; + + retry = 1 ; + + while (retry === 1) + begin + // synchronize operation to clock + @(posedge CLK_I) ; + + wbm_low_level.start_cycle(cab, 1'b1, ok) ; + if ( ok !== 1 ) + begin + $display("*E, Failed to initialize cycle! Routine wb_single_write, Time %t ", $time) ; + return`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + // first insert initial wait states + cyc_count = write_flags`INIT_WAITS ; + while ( cyc_count > 0 ) + begin + @(posedge CLK_I) ; + cyc_count = cyc_count - 1 ; + end + + wbm_low_level.wbm_write(write_data, return) ; + + if ( return`CYC_ERR === 0 && return`CYC_ACK === 0 && return`CYC_RTY === 1 && write_flags`WB_TRANSFER_AUTO_RTY === 1 && return`TB_ERROR_BIT === 0) + begin + if ( rty_count === `WB_TB_MAX_RTY ) + begin + $display("*E, maximum number of retries received - access will not be repeated anymore! Routine wb_single_write, Time %t ", $time) ; + retry = 0 ; + end + else + begin + retry = 1 ; + rty_count = rty_count + 1 ; + end + end + else + retry = 0 ; + + // if test bench error bit is set, there is no meaning in introducing subsequent wait states + if ( return`TB_ERROR_BIT !== 0 ) + begin + @(posedge CLK_I) ; + wbm_low_level.end_cycle ; + disable main ; + end + + cyc_count = write_flags`SUBSEQ_WAITS ; + while ( cyc_count > 0 ) + begin + @(posedge CLK_I) ; + cyc_count = cyc_count - 1 ; + end + + wbm_low_level.end_cycle ; + end + + in_use = 0 ; + +end //main +endtask // wb_single_write + +task wb_single_read ; + input `READ_STIM_TYPE read_data ; + input `WB_TRANSFER_FLAGS read_flags ; + inout `READ_RETURN_TYPE return ; + reg in_use ; + reg cab ; + reg ok ; + integer cyc_count ; + integer rty_count ; + reg retry ; +begin:main + + return`TB_ERROR_BIT = 1'b0 ; + cab = 0 ; + rty_count = 0 ; + return`CYC_ACTUAL_TRANSFER = 0 ; + + // check if task was called before previous call finished + if ( in_use === 1 ) + begin + $display("*E, wb_single_read routine re-entered! Time %t ", $time) ; + return`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + in_use = 1 ; + + retry = 1 ; + + while (retry === 1) + begin + // synchronize operation to clock + @(posedge CLK_I) ; + + wbm_low_level.start_cycle(cab, 1'b0, ok) ; + if ( ok !== 1 ) + begin + $display("*E, Failed to initialize cycle! Routine wb_single_read, Time %t ", $time) ; + return`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + // first insert initial wait states + cyc_count = read_flags`INIT_WAITS ; + while ( cyc_count > 0 ) + begin + @(posedge CLK_I) ; + cyc_count = cyc_count - 1 ; + end + + wbm_low_level.wbm_read(read_data, return) ; + + if ( return`CYC_ERR === 0 && return`CYC_ACK === 0 && return`CYC_RTY === 1 && read_flags`WB_TRANSFER_AUTO_RTY === 1 && return`TB_ERROR_BIT === 0) + begin + if ( rty_count === `WB_TB_MAX_RTY ) + begin + $display("*E, maximum number of retries received - access will not be repeated anymore! Routine wb_single_read, Time %t ", $time) ; + retry = 0 ; + end + else + begin + retry = 1 ; + rty_count = rty_count + 1 ; + end + end + else + begin + retry = 0 ; + end + + // if test bench error bit is set, there is no meaning in introducing subsequent wait states + if ( return`TB_ERROR_BIT !== 0 ) + begin + @(posedge CLK_I) ; + wbm_low_level.end_cycle ; + disable main ; + end + + cyc_count = read_flags`SUBSEQ_WAITS ; + while ( cyc_count > 0 ) + begin + @(posedge CLK_I) ; + cyc_count = cyc_count - 1 ; + end + + wbm_low_level.end_cycle ; + end + + in_use = 0 ; + +end //main +endtask // wb_single_read + +task wb_RMW_read ; + input `READ_STIM_TYPE read_data ; + input `WB_TRANSFER_FLAGS read_flags ; + inout `READ_RETURN_TYPE return ; + reg in_use ; + reg cab ; + reg ok ; + integer cyc_count ; + integer rty_count ; + reg retry ; +begin:main + + return`TB_ERROR_BIT = 1'b0 ; + cab = 0 ; + rty_count = 0 ; + return`CYC_ACTUAL_TRANSFER = 0 ; + + // check if task was called before previous call finished + if ( in_use === 1 ) + begin + $display("*E, wb_RMW_read routine re-entered! Time %t ", $time) ; + return`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + in_use = 1 ; + + retry = 1 ; + + while (retry === 1) + begin + // synchronize operation to clock + @(posedge CLK_I) ; + + wbm_low_level.start_cycle(cab, 1'b0, ok) ; + if ( ok !== 1 ) + begin + $display("*E, Failed to initialize cycle! Routine wb_RMW_read, Time %t ", $time) ; + return`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + // first insert initial wait states + cyc_count = read_flags`INIT_WAITS ; + while ( cyc_count > 0 ) + begin + @(posedge CLK_I) ; + cyc_count = cyc_count - 1 ; + end + + wbm_low_level.wbm_read(read_data, return) ; + + if ( return`CYC_ERR === 0 && return`CYC_ACK === 0 && return`CYC_RTY === 1 && read_flags`WB_TRANSFER_AUTO_RTY === 1 && return`TB_ERROR_BIT === 0) + begin + if ( rty_count === `WB_TB_MAX_RTY ) + begin + $display("*E, maximum number of retries received - access will not be repeated anymore! Routine wb_RMW_read, Time %t ", $time) ; + retry = 0 ; + end + else + begin + retry = 1 ; + rty_count = rty_count + 1 ; + end + end + else + begin + retry = 0 ; + end + + // if test bench error bit is set, there is no meaning in introducing subsequent wait states + if ( return`TB_ERROR_BIT !== 0 ) + begin + @(posedge CLK_I) ; + wbm_low_level.end_cycle ; + disable main ; + end + + cyc_count = read_flags`SUBSEQ_WAITS ; + while ( cyc_count > 0 ) + begin + @(posedge CLK_I) ; + cyc_count = cyc_count - 1 ; + end + + if (retry === 1) + wbm_low_level.end_cycle ; + else + wbm_low_level.modify_cycle ; + end + + in_use = 0 ; + +end //main +endtask // wb_RMW_read + +task wb_RMW_write ; + input `WRITE_STIM_TYPE write_data ; + input `WB_TRANSFER_FLAGS write_flags ; + inout `WRITE_RETURN_TYPE return ; + reg in_use ; + reg cab ; + reg ok ; + integer cyc_count ; + integer rty_count ; + reg retry ; +begin:main + + return`TB_ERROR_BIT = 1'b0 ; + cab = 0 ; + return`CYC_ACTUAL_TRANSFER = 0 ; + rty_count = 0 ; + + // check if task was called before previous call finished + if ( in_use === 1 ) + begin + $display("*E, wb_RMW_write routine re-entered! Time %t ", $time) ; + return`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + in_use = 1 ; + + retry = 1 ; + + while (retry === 1) + begin + // synchronize operation to clock + @(posedge CLK_I) ; + ok = 1 ; + if (rty_count !== 0) + wbm_low_level.start_cycle(cab, 1'b1, ok) ; + + if ( ok !== 1 ) + begin + $display("*E, Failed to initialize cycle! Routine wb_single_write, Time %t ", $time) ; + return`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + // first insert initial wait states + cyc_count = write_flags`INIT_WAITS ; + while ( cyc_count > 0 ) + begin + @(posedge CLK_I) ; + cyc_count = cyc_count - 1 ; + end + + wbm_low_level.wbm_write(write_data, return) ; + + if ( return`CYC_ERR === 0 && return`CYC_ACK === 0 && return`CYC_RTY === 1 && write_flags`WB_TRANSFER_AUTO_RTY === 1 && return`TB_ERROR_BIT === 0) + begin + if ( rty_count === `WB_TB_MAX_RTY ) + begin + $display("*E, maximum number of retries received - access will not be repeated anymore! Routine wb_single_write, Time %t ", $time) ; + retry = 0 ; + end + else + begin + retry = 1 ; + rty_count = rty_count + 1 ; + end + end + else + retry = 0 ; + + // if test bench error bit is set, there is no meaning in introducing subsequent wait states + if ( return`TB_ERROR_BIT !== 0 ) + begin + @(posedge CLK_I) ; + wbm_low_level.end_cycle ; + disable main ; + end + + cyc_count = write_flags`SUBSEQ_WAITS ; + while ( cyc_count > 0 ) + begin + @(posedge CLK_I) ; + cyc_count = cyc_count - 1 ; + end + + wbm_low_level.end_cycle ; + end + + in_use = 0 ; + +end //main +endtask // wb_RMW_write + +task wb_block_write ; + input `WB_TRANSFER_FLAGS write_flags ; + inout `WRITE_RETURN_TYPE return ; + + reg in_use ; + reg `WRITE_STIM_TYPE current_write ; + reg cab ; + reg ok ; + integer cyc_count ; + integer rty_count ; + reg end_blk ; +begin:main + + return`CYC_ACTUAL_TRANSFER = 0 ; + rty_count = 0 ; + + // check if task was called before previous call finished + if ( in_use === 1 ) + begin + $display("*E, wb_block_write routine re-entered! Time %t ", $time) ; + return`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + if (write_flags`WB_TRANSFER_SIZE > `MAX_BLK_SIZE) + begin + $display("*E, number of transfers passed to wb_block_write routine exceeds defined maximum transaction length! Time %t", $time) ; + return`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + in_use = 1 ; + @(posedge CLK_I) ; + cab = write_flags`WB_TRANSFER_CAB ; + wbm_low_level.start_cycle(cab, 1'b1, ok) ; + if ( ok !== 1 ) + begin + $display("*E, Failed to initialize cycle! Routine wb_block_write, Time %t ", $time) ; + return`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + // insert initial wait states + cyc_count = write_flags`INIT_WAITS ; + while ( cyc_count > 0 ) + begin + @(posedge CLK_I) ; + cyc_count = cyc_count - 1 ; + end + + end_blk = 0 ; + while (end_blk === 0) + begin + // collect data for current data beat + current_write = blk_write_data[return`CYC_ACTUAL_TRANSFER] ; + wbm_low_level.wbm_write(current_write, return) ; + + // check result of write operation + // check for severe test error + if (return`TB_ERROR_BIT !== 0) + begin + @(posedge CLK_I) ; + wbm_low_level.end_cycle ; + disable main ; + end + + // slave returned error or error signal had invalid value + if (return`CYC_ERR !== 0) + end_blk = 1 ; + + if ( + (return`CYC_RTY !== 0) && (return`CYC_RTY !== 1) || + (return`CYC_ACK !== 0) && (return`CYC_ACK !== 1) || + (return`CYC_ERR !== 0) && (return`CYC_ERR !== 1) + ) + begin + end_blk = 1 ; + $display("*E, at least one slave response signal was invalid when cycle finished! Routine wb_block_write, Time %t ", $time) ; + $display("ACK = %b \t RTY_O = %b \t ERR_O = %b \t", return`CYC_ACK, return`CYC_RTY, return`CYC_ERR) ; + end + + if ((return`CYC_RTY === 1) && (write_flags`WB_TRANSFER_AUTO_RTY !== 1)) + end_blk = 1 ; + + if ((return`CYC_RTY === 1) && (write_flags`WB_TRANSFER_AUTO_RTY === 1)) + begin + if ( rty_count === `WB_TB_MAX_RTY ) + begin + $display("*E, maximum number of retries received - access will not be repeated anymore! Routine wb_block_write, Time %t ", $time) ; + end_blk = 1 ; + end + else + begin + rty_count = rty_count + 1 ; + end + end + else + rty_count = 0 ; + + // check if slave responded at all + if (return`CYC_RESPONSE === 0) + end_blk = 1 ; + + // check if all intended data was transfered + if (return`CYC_ACTUAL_TRANSFER === write_flags`WB_TRANSFER_SIZE) + end_blk = 1 ; + + // insert subsequent wait cycles, if transfer is supposed to continue + if ( end_blk === 0 ) + begin + cyc_count = write_flags`SUBSEQ_WAITS ; + while ( cyc_count > 0 ) + begin + @(posedge CLK_I) ; + cyc_count = cyc_count - 1 ; + end + end + + if ( (end_blk === 0) && (return`CYC_RTY === 1) ) + begin + wbm_low_level.end_cycle ; + @(posedge CLK_I) ; + wbm_low_level.start_cycle(cab, 1'b1, ok) ; + if ( ok !== 1 ) + begin + $display("*E, Failed to initialize cycle! Routine wb_block_write, Time %t ", $time) ; + return`TB_ERROR_BIT = 1'b1 ; + end_blk = 1 ; + end + end + end //while + + wbm_low_level.end_cycle ; + in_use = 0 ; +end //main +endtask //wb_block_write + +task wb_block_read ; + input `WB_TRANSFER_FLAGS read_flags ; + inout `READ_RETURN_TYPE return ; + + reg in_use ; + reg `READ_STIM_TYPE current_read ; + reg cab ; + reg ok ; + integer cyc_count ; + integer rty_count ; + reg end_blk ; + integer transfered ; +begin:main + + return`CYC_ACTUAL_TRANSFER = 0 ; + transfered = 0 ; + rty_count = 0 ; + + // check if task was called before previous call finished + if ( in_use === 1 ) + begin + $display("*E, wb_block_read routine re-entered! Time %t ", $time) ; + return`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + if (read_flags`WB_TRANSFER_SIZE > `MAX_BLK_SIZE) + begin + $display("*E, number of transfers passed to wb_block_read routine exceeds defined maximum transaction length! Time %t", $time) ; + return`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + in_use = 1 ; + @(posedge CLK_I) ; + cab = read_flags`WB_TRANSFER_CAB ; + + wbm_low_level.start_cycle(cab, 1'b0, ok) ; + + if ( ok !== 1 ) + begin + $display("*E, Failed to initialize cycle! Routine wb_block_read, Time %t ", $time) ; + return`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + // insert initial wait states + cyc_count = read_flags`INIT_WAITS ; + while ( cyc_count > 0 ) + begin + @(posedge CLK_I) ; + cyc_count = cyc_count - 1 ; + end + + end_blk = 0 ; + while (end_blk === 0) + begin + // collect data for current data beat + current_read = blk_read_data_in[return`CYC_ACTUAL_TRANSFER] ; + + wbm_low_level.wbm_read(current_read, return) ; + + if ( transfered !== return`CYC_ACTUAL_TRANSFER ) + begin + blk_read_data_out[transfered] = return ; + transfered = return`CYC_ACTUAL_TRANSFER ; + end + + // check result of read operation + // check for severe test error + if (return`TB_ERROR_BIT !== 0) + begin + @(posedge CLK_I) ; + wbm_low_level.end_cycle ; + disable main ; + end + + // slave returned error or error signal had invalid value + if (return`CYC_ERR !== 0) + end_blk = 1 ; + + if ( + (return`CYC_RTY !== 0) && (return`CYC_RTY !== 1) || + (return`CYC_ACK !== 0) && (return`CYC_ACK !== 1) || + (return`CYC_ERR !== 0) && (return`CYC_ERR !== 1) + ) + begin + end_blk = 1 ; + $display("*E, at least one slave response signal was invalid when cycle finished! Routine wb_block_read, Time %t ", $time) ; + $display("ACK = %b \t RTY_O = %b \t ERR_O = %b \t", return`CYC_ACK, return`CYC_RTY, return`CYC_ERR) ; + end + + if ((return`CYC_RTY === 1) && (read_flags`WB_TRANSFER_AUTO_RTY !== 1)) + end_blk = 1 ; + + if ((return`CYC_RTY === 1) && (read_flags`WB_TRANSFER_AUTO_RTY === 1)) + begin + if ( rty_count === `WB_TB_MAX_RTY ) + begin + $display("*E, maximum number of retries received - access will not be repeated anymore! Routine wb_block_read, Time %t ", $time) ; + end_blk = 1 ; + end + else + begin + rty_count = rty_count + 1 ; + end + end + else + rty_count = 0 ; + + // check if slave responded at all + if (return`CYC_RESPONSE === 0) + end_blk = 1 ; + + // check if all intended data was transfered + if (return`CYC_ACTUAL_TRANSFER === read_flags`WB_TRANSFER_SIZE) + end_blk = 1 ; + + // insert subsequent wait cycles, if transfer is supposed to continue + if ( end_blk === 0 ) + begin + cyc_count = read_flags`SUBSEQ_WAITS ; + while ( cyc_count > 0 ) + begin + @(posedge CLK_I) ; + cyc_count = cyc_count - 1 ; + end + end + + if ( (end_blk === 0) && (return`CYC_RTY === 1) ) + begin + wbm_low_level.end_cycle ; + @(posedge CLK_I) ; + wbm_low_level.start_cycle(cab, 1'b0, ok) ; + if ( ok !== 1 ) + begin + $display("*E, Failed to initialize cycle! Routine wb_block_read, Time %t ", $time) ; + return`TB_ERROR_BIT = 1'b1 ; + end_blk = 1 ; + end + end + end //while + + wbm_low_level.end_cycle ; + in_use = 0 ; +end //main +endtask //wb_block_read + +endmodule + Index: tags/rel_13/bench/verilog/wb_master32.v =================================================================== --- tags/rel_13/bench/verilog/wb_master32.v (nonexistent) +++ tags/rel_13/bench/verilog/wb_master32.v (revision 42) @@ -0,0 +1,366 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// wb_master32.v //// +//// //// +//// This file is part of the "ps2" project //// +//// http://www.opencores.org/cores/ps2/ //// +//// //// +//// Author(s): //// +//// - mihad@opencores.org //// +//// - Miha Dolenc //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: not supported by cvs2svn $ +// + +`include "ps2_testbench_defines.v" +`include "timescale.v" +module WB_MASTER32 +( + CLK_I, + RST_I, + TAG_I, + TAG_O, + ACK_I, + ADR_O, + CYC_O, + DAT_I, + DAT_O, + ERR_I, + RTY_I, + SEL_O, + STB_O, + WE_O, + CAB_O +); + + input CLK_I; + input RST_I; + input `WB_TAG_TYPE TAG_I; + output `WB_TAG_TYPE TAG_O; + input ACK_I; + output `WB_ADDR_TYPE ADR_O; + output CYC_O; + input `WB_DATA_TYPE DAT_I; + output `WB_DATA_TYPE DAT_O; + input ERR_I; + input RTY_I; + output `WB_SEL_TYPE SEL_O; + output STB_O; + output WE_O; + output CAB_O ; + + // period length + real Tp ; + + reg `WB_ADDR_TYPE ADR_O; + reg `WB_SEL_TYPE SEL_O; + reg `WB_TAG_TYPE TAG_O; + reg CYC_O; + reg WE_O; + reg `WB_DATA_TYPE DAT_O; + reg CAB_O ; + reg STB_O ; + + // variable used for indication on whether cycle was already started + reg in_use ; + + // because of non-blocking assignments CYC_O is not sufficient indicator for cycle starting - this var is used in its place + reg cycle_in_progress ; + + // same goes for CAB_O signal + reg cab ; + + reg we ; + + task start_cycle ; + input is_cab ; + input write ; + output ok ; // ok indicates to the caller that cycle was started succesfully - if not, caller must take appropriate action + begin:main + + ok = 1 ; + + // just check if valid value is provided for CAB_O signal (no x's or z's allowed) + if ( (is_cab !== 1'b0) && (is_cab !== 1'b1) ) + begin + $display("*E, invalid CAB value for cycle! Requested CAB_O value = %b, Time %t ", is_cab, $time) ; + ok = 0 ; + disable main ; + end + + if ( (cycle_in_progress === 1) || (CYC_O === 1)) + begin + // cycle was previously started - allow cycle to continue if CAB and WE values match + $display("*W, cycle already in progress when start_cycle routine was called! Time %t ", $time) ; + if ((CAB_O !== is_cab) || (WE_O !== write) ) + begin + ok = 0 ; + if ( is_cab === 1 ) + $display("*E, cab cycle start attempted when non-cab cycle was in progress! Time %t", $time) ; + else + $display("*E, non-cab cycle start attempted when cab cycle was in progress! Time %t", $time) ; + + if ( we === 1 ) + $display("*E, write cycle start attempted when read cycle was in progress! Time %t", $time) ; + else + $display("*E, read cycle start attempted when write cycle was in progress! Time %t", $time) ; + + disable main ; + end + end + + CYC_O <= #(Tp - `Tsetup) 1'b1 ; + CAB_O <= #(Tp - `Tsetup) is_cab ; + WE_O <= #(Tp - `Tsetup) write ; + + // this non-blocking assignments are made to internal variables, so read and write tasks can be called immediately after cycle start task + cycle_in_progress = 1'b1 ; + cab = is_cab ; + we = write ; + end + endtask //start_cycle + + task end_cycle ; + begin + if ( CYC_O !== 1'b1 ) + $display("*W, end_cycle routine called when CYC_O value was %b! Time %t ", CYC_O, $time) ; + + CYC_O <= #`Thold 1'b0 ; + CAB_O <= #`Thold 1'b0 ; + cycle_in_progress = 1'b0 ; + end + endtask //end_cycle + + task modify_cycle ; + begin + if ( CYC_O !== 1'b1 ) + $display("*W, modify_cycle routine called when CYC_O value was %b! Time %t ", CYC_O, $time) ; + + we = ~we ; + WE_O <= #(Tp - `Tsetup) we ; + end + endtask //modify_cycle + + task wbm_read ; + input `READ_STIM_TYPE input_data ; + inout `READ_RETURN_TYPE output_data ; + reg `WB_ADDR_TYPE address ; + reg `WB_DATA_TYPE data ; + reg `WB_SEL_TYPE sel ; + reg `WB_TAG_TYPE tag ; + integer num_of_cyc ; + begin:main + output_data`TB_ERROR_BIT = 1'b0 ; + + // check if task was called before previous call to read or write finished + if ( in_use === 1 ) + begin + $display("*E, wbm_read routine re-entered or called concurently with write routine! Time %t ", $time) ; + output_data`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + if ( cycle_in_progress !== 1 ) + begin + $display("*E, wbm_read routine called without start_cycle routine being called first! Time %t ", $time) ; + output_data`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + if ( we !== 0 ) + begin + $display("*E, wbm_read routine called after write cycle was started! Time %t ", $time) ; + output_data`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + // this branch contains timing controls - claim the use of WISHBONE + in_use = 1 ; + + num_of_cyc = `WAIT_FOR_RESPONSE ; + + // assign data outputs + ADR_O <= #(Tp - `Tsetup) input_data`READ_ADDRESS ; + SEL_O <= #(Tp - `Tsetup) input_data`READ_SEL ; + TAG_O <= #(Tp - `Tsetup) input_data`READ_TAG_STIM ; + + // assign control output + STB_O <= #(Tp - `Tsetup) 1'b1 ; + + output_data`CYC_ACK = 0 ; + output_data`CYC_RTY = 0 ; + output_data`CYC_ERR = 0 ; + + @(posedge CLK_I) ; + output_data`CYC_ACK = ACK_I ; + output_data`CYC_RTY = RTY_I ; + output_data`CYC_ERR = ERR_I ; + + while ( (num_of_cyc > 0) && (output_data`CYC_RESPONSE === 0) ) + begin + @(posedge CLK_I) ; + output_data`CYC_ACK = ACK_I ; + output_data`CYC_RTY = RTY_I ; + output_data`CYC_ERR = ERR_I ; + num_of_cyc = num_of_cyc - 1 ; + end + + output_data`READ_DATA = DAT_I ; + output_data`READ_TAG_RET = TAG_I ; + + if ( output_data`CYC_RESPONSE === 0 ) + begin + + $display("*W, Terminating read cycle because no response was received in %d cycles! Time %t ", `WAIT_FOR_RESPONSE, $time) ; + end + + if ( output_data`CYC_ACK === 1 && output_data`CYC_RTY === 0 && output_data`CYC_ERR === 0 ) + output_data`CYC_ACTUAL_TRANSFER = output_data`CYC_ACTUAL_TRANSFER + 1 ; + + STB_O <= #`Thold 1'b0 ; + ADR_O <= #`Thold {`WB_ADDR_WIDTH{1'bx}} ; + SEL_O <= #`Thold {`WB_SEL_WIDTH{1'bx}} ; + TAG_O <= #`Thold {`WB_TAG_WIDTH{1'bx}} ; + + in_use = 0 ; + end + endtask // wbm_read + + task wbm_write ; + input `WRITE_STIM_TYPE input_data ; + inout `WRITE_RETURN_TYPE output_data ; + reg `WB_ADDR_TYPE address ; + reg `WB_DATA_TYPE data ; + reg `WB_SEL_TYPE sel ; + reg `WB_TAG_TYPE tag ; + integer num_of_cyc ; + begin:main + output_data`TB_ERROR_BIT = 1'b0 ; + + // check if task was called before previous call to read or write finished + if ( in_use === 1 ) + begin + $display("*E, wbm_write routine re-entered or called concurently with read routine! Time %t ", $time) ; + output_data`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + if ( cycle_in_progress !== 1 ) + begin + $display("*E, wbm_write routine called without start_cycle routine being called first! Time %t ", $time) ; + output_data`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + if ( we !== 1 ) + begin + $display("*E, wbm_write routine after read cycle was started! Time %t ", $time) ; + output_data`TB_ERROR_BIT = 1'b1 ; + disable main ; + end + + // this branch contains timing controls - claim the use of WISHBONE + in_use = 1 ; + + num_of_cyc = `WAIT_FOR_RESPONSE ; + + ADR_O <= #(Tp - `Tsetup) input_data`WRITE_ADDRESS ; + DAT_O <= #(Tp - `Tsetup) input_data`WRITE_DATA ; + SEL_O <= #(Tp - `Tsetup) input_data`WRITE_SEL ; + TAG_O <= #(Tp - `Tsetup) input_data`WRITE_TAG_STIM ; + + STB_O <= #(Tp - `Tsetup) 1'b1 ; + + output_data`CYC_ACK = 0 ; + output_data`CYC_RTY = 0 ; + output_data`CYC_ERR = 0 ; + + @(posedge CLK_I) ; + output_data`CYC_ACK = ACK_I ; + output_data`CYC_RTY = RTY_I ; + output_data`CYC_ERR = ERR_I ; + + while ( (num_of_cyc > 0) && (output_data`CYC_RESPONSE === 0) ) + begin + @(posedge CLK_I) ; + output_data`CYC_ACK = ACK_I ; + output_data`CYC_RTY = RTY_I ; + output_data`CYC_ERR = ERR_I ; + num_of_cyc = num_of_cyc - 1 ; + end + + output_data`WRITE_TAG_RET = TAG_I ; + if ( output_data`CYC_RESPONSE === 0 ) + begin + $display("*W, Terminating write cycle because no response was received in %d cycles! Time %t ", `WAIT_FOR_RESPONSE, $time) ; + end + + if ( output_data`CYC_ACK === 1 && output_data`CYC_RTY === 0 && output_data`CYC_ERR === 0 ) + output_data`CYC_ACTUAL_TRANSFER = output_data`CYC_ACTUAL_TRANSFER + 1 ; + + ADR_O <= #`Thold {`WB_ADDR_WIDTH{1'bx}} ; + DAT_O <= #`Thold {`WB_DATA_WIDTH{1'bx}} ; + SEL_O <= #`Thold {`WB_SEL_WIDTH{1'bx}} ; + TAG_O <= #`Thold {`WB_TAG_WIDTH{1'bx}} ; + + STB_O <= #`Thold 1'b0 ; + + in_use = 0 ; + end + endtask //wbm_write + + initial + begin + Tp = 1 / `WB_FREQ ; + in_use = 0 ; + cycle_in_progress = 0 ; + cab = 0 ; + ADR_O <= {`WB_ADDR_WIDTH{1'bx}} ; + DAT_O <= {`WB_DATA_WIDTH{1'bx}} ; + SEL_O <= {`WB_SEL_WIDTH{1'bx}} ; + TAG_O <= {`WB_TAG_WIDTH{1'bx}} ; + CYC_O <= 1'b0 ; + STB_O <= 1'b0 ; + CAB_O <= 1'b0 ; + WE_O <= 1'b0 ; + if ( `Tsetup > Tp || `Thold >= Tp ) + begin + $display("Either Tsetup or Thold values for WISHBONE BFMs are too large!") ; + $stop ; + end + end + +endmodule Index: tags/rel_13/bench/data/extended_scancodes_set1.hex =================================================================== --- tags/rel_13/bench/data/extended_scancodes_set1.hex (nonexistent) +++ tags/rel_13/bench/data/extended_scancodes_set1.hex (revision 42) @@ -0,0 +1,38 @@ +5B +1D +5C +38 +5D +52 +47 +49 +53 +4F +51 +48 +4B +50 +4D +35 +1C +5E +5F +63 +19 +10 +24 +22 +20 +30 +2E +6D +6C +21 +6B +65 +32 +6A +69 +68 +67 +66 \ No newline at end of file
tags/rel_13/bench/data/extended_scancodes_set1.hex Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/rel_13/bench/data/extended_scancodes_set2.hex =================================================================== --- tags/rel_13/bench/data/extended_scancodes_set2.hex (nonexistent) +++ tags/rel_13/bench/data/extended_scancodes_set2.hex (revision 42) @@ -0,0 +1,38 @@ +1F +14 +27 +11 +2F +70 +6C +7D +71 +69 +7A +75 +6B +72 +74 +4A +5A +37 +3F +5E +4D +15 +3B +34 +23 +32 +21 +50 +48 +2B +40 +10 +3A +38 +30 +28 +20 +18 \ No newline at end of file
tags/rel_13/bench/data/extended_scancodes_set2.hex Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/rel_13/bench/data/normal_scancodes_set1.hex =================================================================== --- tags/rel_13/bench/data/normal_scancodes_set1.hex (nonexistent) +++ tags/rel_13/bench/data/normal_scancodes_set1.hex (revision 42) @@ -0,0 +1,85 @@ +1E +30 +2E +20 +12 +21 +22 +23 +17 +24 +25 +26 +32 +31 +18 +19 +10 +13 +1F +14 +16 +2F +11 +2D +15 +2C +0B +02 +03 +04 +05 +06 +0A +29 +0C +0D +2B +0E +39 +0F +3A +2A +1D +38 +36 +1C +01 +3B +3C +3D +3E +3F +40 +41 +42 +43 +44 +57 +58 +1A +45 +37 +4A +4E +53 +52 +4F +50 +51 +4B +4C +4D +47 +48 +49 +1B +27 +28 +33 +07 +08 +09 +46 +34 +35 \ No newline at end of file
tags/rel_13/bench/data/normal_scancodes_set1.hex Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/rel_13/bench/data/normal_scancodes_set2.hex =================================================================== --- tags/rel_13/bench/data/normal_scancodes_set2.hex (nonexistent) +++ tags/rel_13/bench/data/normal_scancodes_set2.hex (revision 42) @@ -0,0 +1,85 @@ +1C +32 +21 +23 +24 +2B +34 +33 +43 +3B +42 +4B +3A +31 +44 +4D +15 +2D +1B +2C +3C +2A +1D +22 +35 +1A +45 +16 +1E +26 +25 +2E +46 +0E +4E +55 +5D +66 +29 +0D +58 +12 +14 +11 +59 +5A +76 +05 +06 +04 +0C +03 +0B +83 +0A +01 +09 +78 +07 +54 +77 +7C +7B +79 +71 +70 +69 +72 +7A +6B +73 +74 +6C +75 +7D +5B +4C +52 +41 +36 +3D +3E +7E +49 +4A \ No newline at end of file
tags/rel_13/bench/data/normal_scancodes_set2.hex Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/rel_13/rtl/verilog/ps2_mouse.v =================================================================== --- tags/rel_13/rtl/verilog/ps2_mouse.v (nonexistent) +++ tags/rel_13/rtl/verilog/ps2_mouse.v (revision 42) @@ -0,0 +1,523 @@ +//------------------------------------------------------------------------------------- +// +// Author: John Clayton +// Date : April 30, 2001 +// Update: 4/30/01 copied this file from lcd_2.v (pared down). +// Update: 5/24/01 changed the first module from "ps2_keyboard_receiver" +// to "ps2_keyboard_interface" +// Update: 5/29/01 Added input synchronizing flip-flops. Changed state +// encoding (m1) for good operation after part config. +// Update: 5/31/01 Added low drive strength and slow transitions to ps2_clk +// and ps2_data in the constraints file. Added the signal +// "tx_shifting_done" as distinguished from "rx_shifting_done." +// Debugged the transmitter portion in the lab. +// Update: 6/01/01 Added horizontal tab to the ascii output. +// Update: 6/01/01 Added parameter TRAP_SHIFT_KEYS. +// Update: 6/05/01 Debugged the "debounce" timer functionality. +// Used 60usec timer as a "watchdog" timeout during +// receive from the keyboard. This means that a keyboard +// can now be "hot plugged" into the interface, without +// messing up the bit_count, since the bit_count is reset +// to zero during periods of inactivity anyway. This was +// difficult to debug. I ended up using the logic analyzer, +// and had to scratch my head quite a bit. +// Update: 6/06/01 Removed extra comments before the input synchronizing +// flip-flops. Used the correct parameter to size the +// 5usec_timer_count. Changed the name of this file from +// ps2.v to ps2_keyboard.v +// Update: 6/06/01 Removed "&& q[7:0]" in output_strobe logic. Removed extra +// commented out "else" condition in the shift register and +// bit counter. +// Update: 6/07/01 Changed default values for 60usec timer parameters so that +// they correspond to 60usec for a 49.152MHz clock. +// +// +// +// +// +// Description +//------------------------------------------------------------------------------------- +// This is a state-machine driven serial-to-parallel and parallel-to-serial +// interface to the ps2 style keyboard interface. The details of the operation +// of the keyboard interface were obtained from the following website: +// +// http://www.beyondlogic.org/keyboard/keybrd.htm +// +// Some aspects of the keyboard interface are not implemented (e.g, parity +// checking for the receive side, and recognition of the various commands +// which the keyboard sends out, such as "power on selt test passed," "Error" +// and "Resend.") However, if the user wishes to recognize these reply +// messages, the scan code output can always be used to extend functionality +// as desired. +// +// Note that the "Extended" (0xE0) and "Released" (0xF0) codes are recognized. +// The rx interface provides separate indicator flags for these two conditions +// with every valid character scan code which it provides. The shift keys are +// also trapped by the interface, in order to provide correct uppercase ASCII +// characters at the ascii output, although the scan codes for the shift keys +// are still provided at the scan code output. So, the left/right ALT keys +// can be differentiated by the presence of the rx_entended signal, while the +// left/right shift keys are differentiable by the different scan codes +// received. +// +// The interface to the ps2 keyboard uses ps2_clk clock rates of +// 30-40 kHz, dependent upon the keyboard itself. The rate at which the state +// machine runs should be at least twice the rate of the ps2_clk, so that the +// states can accurately follow the clock signal itself. Four times +// oversampling is better. Say 200kHz at least. The upper limit for clocking +// the state machine will undoubtedly be determined by delays in the logic +// which decodes the scan codes into ASCII equivalents. The maximum speed +// will be most likely many megahertz, depending upon target technology. +// In order to run the state machine extremely fast, synchronizing flip-flops +// have been added to the ps2_clk and ps2_data inputs of the state machine. +// This avoids poor performance related to slow transitions of the inputs. +// +// Because this is a bi-directional interface, while reading from the keyboard +// the ps2_clk and ps2_data lines are used as inputs. While writing to the +// keyboard, however (which may be done at any time. If writing interrupts a +// read from the keyboard, the keyboard will buffer up its data, and send +// it later) both the ps2_clk and ps2_data lines are occasionally pulled low, +// and pullup resistors are used to bring the lines high again, by setting +// the drivers to high impedance state. +// +// The tx interface, for writing to the keyboard, does not provide any special +// pre-processing. It simply transmits the 8-bit command value to the +// keyboard. +// +// Pullups MUST BE USED on the ps2_clk and ps2_data lines for this design, +// whether they be internal to an FPGA I/O pad, or externally placed. +// If internal pullups are used, they may be fairly weak, causing bounces +// due to crosstalk, etc. There is a "debounce timer" implemented in order +// to eliminate erroneous state transitions which would occur based on bounce. +// +// Parameters are provided in order to configure and appropriately size the +// counter of a 60 microsecond timer used in the transmitter, depending on +// the clock frequency used. The 60 microsecond period is guaranteed to be +// more than one period of the ps2_clk_s signal. +// +// Also, a smaller 5 microsecond timer has been included for "debounce". +// This is used because, with internal pullups on the ps2_clk and ps2_data +// lines, there is some bouncing around which occurs +// +// A parameter TRAP_SHIFT_KEYS allows the user to eliminate shift keypresses +// from producing scan codes (along with their "undefined" ASCII equivalents) +// at the output of the interface. If TRAP_SHIFT_KEYS is non-zero, the shift +// key status will only be reported by rx_shift_key_on. No ascii or scan +// codes will be reported for the shift keys. This is useful for those who +// wish to use the ASCII data stream, and who don't want to have to "filter +// out" the shift key codes. +// +//------------------------------------------------------------------------------------- + + +// synopsys translate_off +`resetall +`include "timescale.v" +// synopsys translate_on +`define TOTAL_BITS 11 + +module ps2_mouse ( + clk, + reset, + ps2_clk_en_o_, + ps2_data_en_o_, + ps2_clk_i, + ps2_data_i, + rx_scan_code, + rx_data_ready, // rx_read_o + rx_read, // rx_read_ack_i + tx_data, + tx_write, + tx_write_ack_o, + tx_error_no_ack, + devide_reg_i + ); + +// 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 + +// 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_ack = 6; +parameter m1_tx_done_recovery = 7; +parameter m1_tx_error_no_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_en_o_ ; +output ps2_data_en_o_ ; +input ps2_clk_i ; +input ps2_data_i ; +output [7:0] rx_scan_code; +output rx_data_ready; +input rx_read; +input [7:0] tx_data; +input tx_write; +output tx_write_ack_o; +output tx_error_no_ack; + +input [15:0] devide_reg_i; + +reg rx_released; +reg [7:0] rx_scan_code; +reg rx_data_ready; +reg tx_error_no_ack; + +// Internal signal declarations +wire timer_60usec_done; +wire timer_5usec_done; +reg timer_done ; +reg timer_5usec ; + // 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; + +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 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. + +reg ps2_clk_ms; +reg ps2_data_ms; + +//-------------------------------------------------------------------------- +// Module code + +assign ps2_clk_en_o_ = ps2_clk_hi_z ; +assign ps2_data_en_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_ms <= #1 ps2_clk_i; + ps2_data_ms <= #1 ps2_data_i; + + ps2_clk_s <= #1 ps2_clk_ms; + ps2_data_s <= #1 ps2_data_ms; + +end + +// State register +always @(posedge clk) +begin : m1_state_register + if (reset) m1_state <= #1 m1_rx_clk_h; + else m1_state <= #1 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 1; + ps2_data_hi_z <= #1 1; + tx_error_no_ack <= #1 0; + enable_timer_60usec <= #1 0; + enable_timer_5usec <= #1 0; + + case (m1_state) + + m1_rx_clk_h : + begin + enable_timer_60usec <= #1 1; + if (tx_write) m1_next_state <= #1 m1_tx_reset_timer; + else if (~ps2_clk_s) m1_next_state <= #1 m1_rx_falling_edge_marker; + else m1_next_state <= #1 m1_rx_clk_h; + end + + m1_rx_falling_edge_marker : + begin + enable_timer_60usec <= #1 0; + m1_next_state <= #1 m1_rx_clk_l; + end + + m1_rx_rising_edge_marker : + begin + enable_timer_60usec <= #1 0; + m1_next_state <= #1 m1_rx_clk_h; + end + + + m1_rx_clk_l : + begin + enable_timer_60usec <= #1 1; + if (tx_write) m1_next_state <= #1 m1_tx_reset_timer; + else if (ps2_clk_s) m1_next_state <= #1 m1_rx_rising_edge_marker; + else m1_next_state <= #1 m1_rx_clk_l; + end + + m1_tx_reset_timer: + begin + enable_timer_60usec <= #1 0; + m1_next_state <= #1 m1_tx_force_clk_l; + end + + m1_tx_force_clk_l : + begin + enable_timer_60usec <= #1 1; + ps2_clk_hi_z <= #1 0; // Force the ps2_clk line low. + if (timer_60usec_done) m1_next_state <= #1 m1_tx_first_wait_clk_h; + else m1_next_state <= #1 m1_tx_force_clk_l; + end + + m1_tx_first_wait_clk_h : + begin + enable_timer_5usec <= #1 1; + ps2_data_hi_z <= #1 0; // Start bit. + if (~ps2_clk_s && timer_5usec_done) + m1_next_state <= #1 m1_tx_clk_l; + else + m1_next_state <= #1 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 <= #1 0; + if (~ps2_clk_s) m1_next_state <= #1 m1_tx_clk_l; + else m1_next_state <= #1 m1_tx_first_wait_clk_l; + end + + m1_tx_wait_clk_h : + begin + enable_timer_5usec <= #1 1; + ps2_data_hi_z <= #1 q[0]; + if (ps2_clk_s && timer_5usec_done) + m1_next_state <= #1 m1_tx_rising_edge_marker; + else + m1_next_state <= #1 m1_tx_wait_clk_h; + end + + m1_tx_rising_edge_marker : + begin + ps2_data_hi_z <= #1 q[0]; + m1_next_state <= #1 m1_tx_clk_h; + end + + m1_tx_clk_h : + begin + ps2_data_hi_z <= #1 q[0]; + if (tx_shifting_done) m1_next_state <= #1 m1_tx_wait_ack; + else if (~ps2_clk_s) m1_next_state <= #1 m1_tx_clk_l; + else m1_next_state <= #1 m1_tx_clk_h; + end + + m1_tx_clk_l : + begin + ps2_data_hi_z <= #1 q[0]; + if (ps2_clk_s) m1_next_state <= #1 m1_tx_wait_clk_h; + else m1_next_state <= #1 m1_tx_clk_l; + end + + m1_tx_wait_ack : + begin + if (~ps2_clk_s && ps2_data_s) + m1_next_state <= #1 m1_tx_error_no_ack; + else if (~ps2_clk_s && ~ps2_data_s) + m1_next_state <= #1 m1_tx_done_recovery; + else m1_next_state <= #1 m1_tx_wait_ack; + end + + m1_tx_done_recovery : + begin + if (ps2_clk_s && ps2_data_s) m1_next_state <= #1 m1_rx_clk_h; + else m1_next_state <= #1 m1_tx_done_recovery; + end + + m1_tx_error_no_ack : + begin + tx_error_no_ack <= #1 1; + if (ps2_clk_s && ps2_data_s) m1_next_state <= #1 m1_rx_clk_h; + else m1_next_state <= #1 m1_tx_error_no_ack; + end + + default : m1_next_state <= #1 m1_rx_clk_h; + endcase +end + +// State register +always @(posedge clk) +begin : m2_state_register + if (reset) m2_state <= #1 m2_rx_data_ready_ack; + else m2_state <= #1 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 1'b0; + if (rx_output_strobe) m2_next_state <= #1 m2_rx_data_ready; + else m2_next_state <= #1 m2_rx_data_ready_ack; + end + m2_rx_data_ready: + begin + rx_data_ready <= #1 1'b1; + if (rx_read) m2_next_state <= #1 m2_rx_data_ready_ack; + else m2_next_state <= #1 m2_rx_data_ready; + end + default : m2_next_state <= #1 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_ack) // After tx is done. + ) bit_count <= #1 0; // normal reset + else if (timer_60usec_done + && (m1_state == m1_rx_clk_h) + && (ps2_clk_s) + ) bit_count <= #1 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 <= #1 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 <= #1 0; + else if (tx_write_ack_o) q <= #1 {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 <= #1 {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 <= #1 0; + else if ( timer_done && !timer_60usec_done) + timer_60usec_count<= #1 timer_60usec_count +1; + end +assign timer_60usec_done = (timer_60usec_count == (TIMER_60USEC_VALUE_PP )); + + + +always @(posedge clk or posedge reset) +if (reset) timer_5usec <= #1 1; +else if (!enable_timer_60usec) timer_5usec <= #1 1; +else if (timer_5usec == devide_reg_i) + begin + timer_5usec <= #1 1; + timer_done <= #1 1; + end +else + begin + timer_5usec<= #1 timer_5usec +1; + timer_done <= #1 0; + end + +// This is the 5usec timer counter +always @(posedge clk) +begin + if (~enable_timer_5usec) timer_5usec_count <= #1 0; + else if (~timer_5usec_done) timer_5usec_count <= #1 timer_5usec_count + 1; +end +assign timer_5usec_done = (timer_5usec_count == devide_reg_i - 1); + +always @(posedge clk) +begin + if (reset) + begin + rx_scan_code <= #1 0; + end + else if (rx_output_strobe) + begin + rx_scan_code <= #1 q[8:1]; + 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 ; + +assign rx_output_strobe = rx_shifting_done ; + +endmodule
tags/rel_13/rtl/verilog/ps2_mouse.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/rel_13/rtl/verilog/ps2_wb_if.v =================================================================== --- tags/rel_13/rtl/verilog/ps2_wb_if.v (nonexistent) +++ tags/rel_13/rtl/verilog/ps2_wb_if.v (revision 42) @@ -0,0 +1,727 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// ps2_wb_if.v //// +//// //// +//// This file is part of the "ps2" project //// +//// http://www.opencores.org/cores/ps2/ //// +//// //// +//// Author(s): //// +//// - mihad@opencores.org //// +//// - Miha Dolenc //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: not supported by cvs2svn $ +// Revision 1.7 2003/10/03 10:16:52 primozs +// support for configurable devider added +// +// Revision 1.6 2003/05/28 16:27:09 simons +// Change the address width. +// +// Revision 1.5 2002/04/09 13:24:11 mihad +// Added mouse interface and everything for its handling, cleaned up some unused code +// +// Revision 1.4 2002/02/20 16:35:43 mihad +// Little/big endian changes continued +// +// Revision 1.3 2002/02/20 15:20:10 mihad +// Little/big endian changes incorporated +// +// Revision 1.2 2002/02/18 18:07:55 mihad +// One bug fixed +// +// Revision 1.1.1.1 2002/02/18 16:16:56 mihad +// Initial project import - working +// +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module ps2_wb_if +( + wb_clk_i, + wb_rst_i, + wb_cyc_i, + wb_stb_i, + wb_we_i, + wb_sel_i, + wb_adr_i, + wb_dat_i, + wb_dat_o, + wb_ack_o, + + wb_int_o, + + tx_kbd_write_ack_i, + tx_kbd_data_o, + tx_kbd_write_o, + rx_scancode_i, + rx_kbd_data_ready_i, + rx_kbd_read_o, + translate_o, + ps2_kbd_clk_i, + devide_reg_o, + inhibit_kbd_if_o + `ifdef PS2_AUX + , + wb_intb_o, + + rx_aux_data_i, + rx_aux_data_ready_i, + rx_aux_read_o, + tx_aux_data_o, + tx_aux_write_o, + tx_aux_write_ack_i, + ps2_aux_clk_i, + inhibit_aux_if_o +`endif +) ; + +input wb_clk_i, + wb_rst_i, + wb_cyc_i, + wb_stb_i, + wb_we_i ; + +input [3:0] wb_sel_i ; + +input [3:0] wb_adr_i ; + +input [31:0] wb_dat_i ; + +output [31:0] wb_dat_o ; + +output wb_ack_o ; + +reg wb_ack_o ; + +output wb_int_o ; +reg wb_int_o ; + +input tx_kbd_write_ack_i ; + +input [7:0] rx_scancode_i ; +input rx_kbd_data_ready_i ; +output rx_kbd_read_o ; + +output tx_kbd_write_o ; +output [7:0] tx_kbd_data_o ; + +output translate_o ; +input ps2_kbd_clk_i ; + +output inhibit_kbd_if_o ; + +reg [7:0] input_buffer, + output_buffer ; + +output [15:0] devide_reg_o; +reg [15:0] devide_reg; +assign devide_reg_o = devide_reg; + + +reg [15:0] wb_dat_i_sampled ; +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + wb_dat_i_sampled <= #1 0 ; + else if ( wb_cyc_i && wb_stb_i && wb_we_i ) + wb_dat_i_sampled <= #1 wb_dat_i[31:16] ; +end + +`ifdef PS2_AUX +output wb_intb_o ; +reg wb_intb_o ; + +input [7:0] rx_aux_data_i ; +input rx_aux_data_ready_i ; +output rx_aux_read_o ; +output [7:0] tx_aux_data_o ; +output tx_aux_write_o ; +input tx_aux_write_ack_i ; +input ps2_aux_clk_i ; +output inhibit_aux_if_o ; +reg inhibit_aux_if_o ; +reg aux_output_buffer_full ; +reg aux_input_buffer_full ; +reg interrupt2 ; +reg enable2 ; +assign tx_aux_data_o = output_buffer ; +assign tx_aux_write_o = aux_output_buffer_full ; +`else +wire aux_input_buffer_full = 1'b0 ; +wire aux_output_buffer_full = 1'b0 ; +wire interrupt2 = 1'b0 ; +wire enable2 = 1'b1 ; +`endif + +assign tx_kbd_data_o = output_buffer ; + +reg input_buffer_full, // receive buffer + output_buffer_full ; // transmit buffer + +assign tx_kbd_write_o = output_buffer_full ; + +wire system_flag ; +wire a2 = 1'b0 ; +wire kbd_inhibit = ps2_kbd_clk_i ; +wire timeout = 1'b0 ; +wire perr = 1'b0 ; + +wire [7:0] status_byte = {perr, timeout, aux_input_buffer_full, kbd_inhibit, a2, system_flag, output_buffer_full || aux_output_buffer_full, input_buffer_full} ; + +reg read_input_buffer_reg ; +wire read_input_buffer = wb_cyc_i && wb_stb_i && wb_sel_i[3] && !wb_ack_o && !read_input_buffer_reg && !wb_we_i && (wb_adr_i[3:0] == 4'h0) ; + +reg write_output_buffer_reg ; +wire write_output_buffer = wb_cyc_i && wb_stb_i && wb_sel_i[3] && !wb_ack_o && !write_output_buffer_reg && wb_we_i && (wb_adr_i[3:0] == 4'h0) ; + +reg read_status_register_reg ; +wire read_status_register = wb_cyc_i && wb_stb_i && wb_sel_i[3] && !wb_ack_o && !read_status_register_reg && !wb_we_i && (wb_adr_i[3:0] == 4'h4) ; + +reg send_command_reg ; +wire send_command = wb_cyc_i && wb_stb_i && wb_sel_i[3] && !wb_ack_o && !send_command_reg && wb_we_i && (wb_adr_i[3:0] == 4'h4) ; + +reg write_devide_reg0 ; +wire write_devide0 = wb_cyc_i && wb_stb_i && wb_sel_i[2] && !wb_ack_o && !write_devide_reg0 && wb_we_i && (wb_adr_i[3:0] == 4'h8) ; + +//reg read_devide_reg ; +wire read_devide = wb_cyc_i && wb_stb_i && ( wb_sel_i[2]|| wb_sel_i [3] ) && !wb_we_i && (wb_adr_i[3:0] == 4'h8) ; + +reg write_devide_reg1 ; +wire write_devide1 = wb_cyc_i && wb_stb_i && wb_sel_i[3] && !wb_ack_o && !write_devide_reg1 && wb_we_i && (wb_adr_i[3:0] == 4'h8) ; + + +reg translate_o, + enable1, + system, + interrupt1 ; + +reg inhibit_kbd_if_o ; +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + inhibit_kbd_if_o <= #1 1'b0 ; + else if ( ps2_kbd_clk_i && rx_kbd_data_ready_i && !enable1) + inhibit_kbd_if_o <= #1 1'b1 ; + else if ( !rx_kbd_data_ready_i || enable1 ) + inhibit_kbd_if_o <= #1 1'b0 ; + +end + +`ifdef PS2_AUX +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + inhibit_aux_if_o <= #1 1'b1 ; + else if ( ps2_aux_clk_i && rx_aux_data_ready_i && !enable2 ) + inhibit_aux_if_o <= #1 1'b1 ; + else if ( !rx_aux_data_ready_i || enable2 ) + inhibit_aux_if_o <= #1 1'b0 ; + +end +`endif + +assign system_flag = system ; + +wire [7:0] command_byte = {1'b0, translate_o, enable2, enable1, 1'b0, system, interrupt2, interrupt1} ; + +reg [7:0] current_command ; +reg [7:0] current_command_output ; + +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + begin + send_command_reg <= #1 1'b0 ; + read_input_buffer_reg <= #1 1'b0 ; + write_output_buffer_reg <= #1 1'b0 ; + read_status_register_reg <= #1 1'b0 ; + write_devide_reg0 <= #1 1'b0 ; + //read_devide_reg <= #1 1'b0 ; + write_devide_reg1 <= #1 1'b0 ; + end + else + begin + send_command_reg <= #1 send_command ; + read_input_buffer_reg <= #1 read_input_buffer ; + write_output_buffer_reg <= #1 write_output_buffer ; + read_status_register_reg <= #1 read_status_register ; + write_devide_reg0 <= #1 write_devide0 ; + //read_devide_reg <= #1 read_devide ; + write_devide_reg1 <= #1 write_devide1 ; + end +end + +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + current_command <= #1 8'h0 ; + else if ( send_command_reg ) + current_command <= #1 wb_dat_i_sampled[15:8] ; +end + +reg current_command_valid, + current_command_returns_value, + current_command_gets_parameter, + current_command_gets_null_terminated_string ; + +reg write_output_buffer_reg_previous ; +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + write_output_buffer_reg_previous <= #1 1'b0 ; + else + write_output_buffer_reg_previous <= #1 write_output_buffer_reg ; +end + +wire invalidate_current_command = + current_command_valid && + (( current_command_returns_value && read_input_buffer_reg && input_buffer_full) || + ( current_command_gets_parameter && write_output_buffer_reg_previous ) || + ( current_command_gets_null_terminated_string && write_output_buffer_reg_previous && (output_buffer == 8'h00) ) || + ( !current_command_returns_value && !current_command_gets_parameter && !current_command_gets_null_terminated_string ) + ) ; + +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + current_command_valid <= #1 1'b0 ; + else if ( invalidate_current_command ) + current_command_valid <= #1 1'b0 ; + else if ( send_command_reg ) + current_command_valid <= #1 1'b1 ; + +end + +reg write_command_byte ; +reg current_command_output_valid ; +always@( + current_command or + command_byte or + write_output_buffer_reg_previous or + current_command_valid or + output_buffer +) +begin + current_command_returns_value = 1'b0 ; + current_command_gets_parameter = 1'b0 ; + current_command_gets_null_terminated_string = 1'b0 ; + current_command_output = 8'h00 ; + write_command_byte = 1'b0 ; + current_command_output_valid = 1'b0 ; + case(current_command) + 8'h20:begin + current_command_returns_value = 1'b1 ; + current_command_output = command_byte ; + current_command_output_valid = 1'b1 ; + end + 8'h60:begin + current_command_gets_parameter = 1'b1 ; + write_command_byte = write_output_buffer_reg_previous && current_command_valid ; + end + 8'hA1:begin + current_command_returns_value = 1'b1 ; + current_command_output = 8'h00 ; + current_command_output_valid = 1'b1 ; + end + 8'hA4:begin + current_command_returns_value = 1'b1 ; + current_command_output = 8'hF1 ; + current_command_output_valid = 1'b1 ; + end + 8'hA5:begin + current_command_gets_null_terminated_string = 1'b1 ; + end + 8'hA6:begin + end + 8'hA7:begin + end + 8'hA8:begin + end + 8'hA9:begin + current_command_returns_value = 1'b1 ; + current_command_output_valid = 1'b1 ; + `ifdef PS2_AUX + current_command_output = 8'h00 ; // interface OK + `else + current_command_output = 8'h02 ; // clock line stuck high + `endif + end + 8'hAA:begin + current_command_returns_value = 1'b1 ; + current_command_output = 8'h55 ; + current_command_output_valid = 1'b1 ; + end + 8'hAB:begin + current_command_returns_value = 1'b1 ; + current_command_output = 8'h00 ; + current_command_output_valid = 1'b1 ; + end + 8'hAD:begin + end + 8'hAE:begin + end + 8'hAF:begin + current_command_returns_value = 1'b1 ; + current_command_output = 8'h00 ; + current_command_output_valid = 1'b1 ; + end + 8'hC0:begin + current_command_returns_value = 1'b1 ; + current_command_output = 8'hFF ; + current_command_output_valid = 1'b1 ; + end + 8'hC1:begin + end + 8'hC2:begin + end + 8'hD0:begin + current_command_returns_value = 1'b1 ; + current_command_output = 8'h01 ; // only system reset bit is 1 + current_command_output_valid = 1'b1 ; + end + 8'hD1:begin + current_command_gets_parameter = 1'b1 ; + end + 8'hD2:begin + current_command_returns_value = 1'b1 ; + current_command_gets_parameter = 1'b1 ; + current_command_output = output_buffer ; + current_command_output_valid = write_output_buffer_reg_previous ; + end + 8'hD3:begin + current_command_gets_parameter = 1'b1 ; + `ifdef PS2_AUX + current_command_returns_value = 1'b1 ; + current_command_output = output_buffer ; + current_command_output_valid = write_output_buffer_reg_previous ; + `endif + end + 8'hD4:begin + current_command_gets_parameter = 1'b1 ; + end + 8'hE0:begin + current_command_returns_value = 1'b1 ; + current_command_output = 8'hFF ; + current_command_output_valid = 1'b1 ; + end + endcase +end + +reg cyc_i_previous ; +reg stb_i_previous ; + +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + begin + cyc_i_previous <= #1 1'b0 ; + stb_i_previous <= #1 1'b0 ; + end + else if ( wb_ack_o ) + begin + cyc_i_previous <= #1 1'b0 ; + stb_i_previous <= #1 1'b0 ; + end + else + begin + cyc_i_previous <= #1 wb_cyc_i ; + stb_i_previous <= #1 wb_stb_i ; + end + +end + +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + wb_ack_o <= #1 1'b0 ; + else if ( wb_ack_o ) + wb_ack_o <= #1 1'b0 ; + else + wb_ack_o <= #1 cyc_i_previous && stb_i_previous ; +end + +reg [31:0] wb_dat_o ; +wire wb_read = read_input_buffer_reg || read_status_register_reg || read_devide ; + +wire [15:0] output_data = read_status_register_reg ? {2{status_byte}} : read_devide ? devide_reg : {2{input_buffer}} ; +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + wb_dat_o <= #1 32'h0 ; + else if ( wb_read ) + wb_dat_o <= #1 {2{output_data}} ; +end + +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + output_buffer_full <= #1 1'b0 ; + else if ( output_buffer_full && tx_kbd_write_ack_i || enable1) + output_buffer_full <= #1 1'b0 ; + else + output_buffer_full <= #1 write_output_buffer_reg && (!current_command_valid || (!current_command_gets_parameter && !current_command_gets_null_terminated_string)) ; +end + +`ifdef PS2_AUX +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + aux_output_buffer_full <= #1 1'b0 ; + else if ( aux_output_buffer_full && tx_aux_write_ack_i || enable2) + aux_output_buffer_full <= #1 1'b0 ; + else + aux_output_buffer_full <= #1 write_output_buffer_reg && current_command_valid && (current_command == 8'hD4) ; +end +`endif + +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + output_buffer <= #1 8'h00 ; + else if ( write_output_buffer_reg ) + output_buffer <= #1 wb_dat_i_sampled[15:8]; +end + +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + devide_reg <= #1 8'h00 ; + else + begin + if ( write_devide_reg0 ) + devide_reg[7:0] <= #1 wb_dat_i_sampled[7:0] ; + if ( write_devide_reg1 ) + devide_reg[15:8] <= #1 wb_dat_i_sampled[15:8] ; + end +end + +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + begin + translate_o <= #1 1'b0 ; + system <= #1 1'b0 ; + interrupt1 <= #1 1'b0 ; + `ifdef PS2_AUX + interrupt2 <= #1 1'b0 ; + `endif + end + else if ( write_command_byte ) + begin + translate_o <= #1 output_buffer[6] ; + system <= #1 output_buffer[2] ; + interrupt1 <= #1 output_buffer[0] ; + `ifdef PS2_AUX + interrupt2 <= #1 output_buffer[1] ; + `endif + end +end + +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + enable1 <= #1 1'b1 ; + else if ( current_command_valid && (current_command == 8'hAE) ) + enable1 <= #1 1'b0 ; + else if ( current_command_valid && (current_command == 8'hAD) ) + enable1 <= #1 1'b1 ; + else if ( write_command_byte ) + enable1 <= #1 output_buffer[4] ; + +end + +`ifdef PS2_AUX +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + enable2 <= #1 1'b1 ; + else if ( current_command_valid && (current_command == 8'hA8) ) + enable2 <= #1 1'b0 ; + else if ( current_command_valid && (current_command == 8'hA7) ) + enable2 <= #1 1'b1 ; + else if ( write_command_byte ) + enable2 <= #1 output_buffer[5] ; + +end +`endif + +wire write_input_buffer_from_command = current_command_valid && current_command_returns_value && current_command_output_valid ; +wire write_input_buffer_from_kbd = !input_buffer_full && rx_kbd_data_ready_i && !enable1 && !current_command_valid ; + +`ifdef PS2_AUX +wire write_input_buffer_from_aux = !input_buffer_full && rx_aux_data_ready_i && !enable2 && !current_command_valid && !write_input_buffer_from_kbd ; +`endif + +wire load_input_buffer_value = + write_input_buffer_from_command + || + write_input_buffer_from_kbd + `ifdef PS2_AUX + || + write_input_buffer_from_aux + `endif + ; + +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + input_buffer_full <= #1 1'b0 ; + else if ( read_input_buffer_reg ) + input_buffer_full <= #1 1'b0 ; + else if ( load_input_buffer_value ) + input_buffer_full <= #1 1'b1 ; +end + +`ifdef PS2_AUX +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + aux_input_buffer_full <= #1 1'b0 ; + else if ( read_input_buffer_reg ) + aux_input_buffer_full <= #1 1'b0 ; + else if ( write_input_buffer_from_aux || (write_input_buffer_from_command && (current_command == 8'hD3)) ) + aux_input_buffer_full <= #1 1'b1 ; +end +`endif + +reg input_buffer_filled_from_command ; +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + input_buffer_filled_from_command <= #1 1'b0 ; + else if ( read_input_buffer_reg ) + input_buffer_filled_from_command <= #1 1'b0 ; + else if ( write_input_buffer_from_command ) + input_buffer_filled_from_command <= #1 1'b1 ; +end + +`ifdef PS2_AUX +reg [7:0] value_to_load_in_input_buffer ; +always@ +( + write_input_buffer_from_command + or + current_command_output + or + rx_scancode_i + or + write_input_buffer_from_kbd + or + rx_aux_data_i +) +begin + case ({write_input_buffer_from_command, write_input_buffer_from_kbd}) + 2'b10, + 2'b11 : value_to_load_in_input_buffer = current_command_output ; + 2'b01 : value_to_load_in_input_buffer = rx_scancode_i ; + 2'b00 : value_to_load_in_input_buffer = rx_aux_data_i ; + endcase +end + +`else +wire [7:0] value_to_load_in_input_buffer = write_input_buffer_from_command ? current_command_output : rx_scancode_i ; +`endif + +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + input_buffer <= #1 8'h00 ; + else if ( load_input_buffer_value ) + input_buffer <= #1 value_to_load_in_input_buffer ; +end + +assign rx_kbd_read_o = rx_kbd_data_ready_i && + ( enable1 + || + ( read_input_buffer_reg + && + input_buffer_full + && + !input_buffer_filled_from_command + `ifdef PS2_AUX + && + !aux_input_buffer_full + `endif + ) + ); + +`ifdef PS2_AUX +assign rx_aux_read_o = rx_aux_data_ready_i && + ( enable2 || + ( read_input_buffer_reg + && + input_buffer_full + && + aux_input_buffer_full + && + !input_buffer_filled_from_command + ) + ); +`endif + +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + wb_int_o <= #1 1'b0 ; + else if ( read_input_buffer_reg || enable1 || !interrupt1) + wb_int_o <= #1 1'b0 ; + else + wb_int_o <= #1 input_buffer_full + `ifdef PS2_AUX + && + !aux_input_buffer_full + `endif + ; +end + +`ifdef PS2_AUX +always@(posedge wb_clk_i or posedge wb_rst_i) +begin + if ( wb_rst_i ) + wb_intb_o <= #1 1'b0 ; + else if ( read_input_buffer_reg || enable2 || !interrupt2) + wb_intb_o <= #1 1'b0 ; + else + wb_intb_o <= #1 input_buffer_full + && + aux_input_buffer_full + ; +end +`endif + +endmodule // ps2_wb_if Index: tags/rel_13/rtl/verilog/ps2_keyboard.v =================================================================== --- tags/rel_13/rtl/verilog/ps2_keyboard.v (nonexistent) +++ tags/rel_13/rtl/verilog/ps2_keyboard.v (revision 42) @@ -0,0 +1,568 @@ +//------------------------------------------------------------------------------------- +// +// Author: John Clayton +// Date : April 30, 2001 +// Update: 4/30/01 copied this file from lcd_2.v (pared down). +// Update: 5/24/01 changed the first module from "ps2_keyboard_receiver" +// to "ps2_keyboard_interface" +// Update: 5/29/01 Added input synchronizing flip-flops. Changed state +// encoding (m1) for good operation after part config. +// Update: 5/31/01 Added low drive strength and slow transitions to ps2_clk +// and ps2_data in the constraints file. Added the signal +// "tx_shifting_done" as distinguished from "rx_shifting_done." +// Debugged the transmitter portion in the lab. +// Update: 6/01/01 Added horizontal tab to the ascii output. +// Update: 6/01/01 Added parameter TRAP_SHIFT_KEYS. +// Update: 6/05/01 Debugged the "debounce" timer functionality. +// Used 60usec timer as a "watchdog" timeout during +// receive from the keyboard. This means that a keyboard +// can now be "hot plugged" into the interface, without +// messing up the bit_count, since the bit_count is reset +// to zero during periods of inactivity anyway. This was +// difficult to debug. I ended up using the logic analyzer, +// and had to scratch my head quite a bit. +// Update: 6/06/01 Removed extra comments before the input synchronizing +// flip-flops. Used the correct parameter to size the +// 5usec_timer_count. Changed the name of this file from +// ps2.v to ps2_keyboard.v +// Update: 6/06/01 Removed "&& q[7:0]" in output_strobe logic. Removed extra +// commented out "else" condition in the shift register and +// bit counter. +// Update: 6/07/01 Changed default values for 60usec timer parameters so that +// they correspond to 60usec for a 49.152MHz clock. +// +// +// +// +// +// Description +//------------------------------------------------------------------------------------- +// This is a state-machine driven serial-to-parallel and parallel-to-serial +// interface to the ps2 style keyboard interface. The details of the operation +// of the keyboard interface were obtained from the following website: +// +// http://www.beyondlogic.org/keyboard/keybrd.htm +// +// Some aspects of the keyboard interface are not implemented (e.g, parity +// checking for the receive side, and recognition of the various commands +// which the keyboard sends out, such as "power on selt test passed," "Error" +// and "Resend.") However, if the user wishes to recognize these reply +// messages, the scan code output can always be used to extend functionality +// as desired. +// +// Note that the "Extended" (0xE0) and "Released" (0xF0) codes are recognized. +// The rx interface provides separate indicator flags for these two conditions +// with every valid character scan code which it provides. The shift keys are +// also trapped by the interface, in order to provide correct uppercase ASCII +// characters at the ascii output, although the scan codes for the shift keys +// are still provided at the scan code output. So, the left/right ALT keys +// can be differentiated by the presence of the rx_entended signal, while the +// left/right shift keys are differentiable by the different scan codes +// received. +// +// The interface to the ps2 keyboard uses ps2_clk clock rates of +// 30-40 kHz, dependent upon the keyboard itself. The rate at which the state +// machine runs should be at least twice the rate of the ps2_clk, so that the +// states can accurately follow the clock signal itself. Four times +// oversampling is better. Say 200kHz at least. The upper limit for clocking +// the state machine will undoubtedly be determined by delays in the logic +// which decodes the scan codes into ASCII equivalents. The maximum speed +// will be most likely many megahertz, depending upon target technology. +// In order to run the state machine extremely fast, synchronizing flip-flops +// have been added to the ps2_clk and ps2_data inputs of the state machine. +// This avoids poor performance related to slow transitions of the inputs. +// +// Because this is a bi-directional interface, while reading from the keyboard +// the ps2_clk and ps2_data lines are used as inputs. While writing to the +// keyboard, however (which may be done at any time. If writing interrupts a +// read from the keyboard, the keyboard will buffer up its data, and send +// it later) both the ps2_clk and ps2_data lines are occasionally pulled low, +// and pullup resistors are used to bring the lines high again, by setting +// the drivers to high impedance state. +// +// The tx interface, for writing to the keyboard, does not provide any special +// pre-processing. It simply transmits the 8-bit command value to the +// keyboard. +// +// Pullups MUST BE USED on the ps2_clk and ps2_data lines for this design, +// whether they be internal to an FPGA I/O pad, or externally placed. +// If internal pullups are used, they may be fairly weak, causing bounces +// due to crosstalk, etc. There is a "debounce timer" implemented in order +// to eliminate erroneous state transitions which would occur based on bounce. +// +// Parameters are provided in order to configure and appropriately size the +// counter of a 60 microsecond timer used in the transmitter, depending on +// the clock frequency used. The 60 microsecond period is guaranteed to be +// more than one period of the ps2_clk_s signal. +// +// Also, a smaller 5 microsecond timer has been included for "debounce". +// This is used because, with internal pullups on the ps2_clk and ps2_data +// lines, there is some bouncing around which occurs +// +// A parameter TRAP_SHIFT_KEYS allows the user to eliminate shift keypresses +// from producing scan codes (along with their "undefined" ASCII equivalents) +// at the output of the interface. If TRAP_SHIFT_KEYS is non-zero, the shift +// key status will only be reported by rx_shift_key_on. No ascii or scan +// codes will be reported for the shift keys. This is useful for those who +// wish to use the ASCII data stream, and who don't want to have to "filter +// out" the shift key codes. +// +//------------------------------------------------------------------------------------- + + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on +`define TOTAL_BITS 11 +`define RELEASE_CODE 16'hF0 + +module ps2_keyboard ( + clk, + reset, + ps2_clk_en_o_, + ps2_data_en_o_, + ps2_clk_i, + ps2_data_i, + rx_released, + rx_scan_code, + 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, + devide_reg_i + ); + +// 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 + +// 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_en_o_ ; +output ps2_data_en_o_ ; +input ps2_clk_i ; +input ps2_data_i ; +output rx_released; +output [7:0] rx_scan_code; +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 ; + +input [15:0] devide_reg_i; + +reg rx_released; +reg [7:0] rx_scan_code; +reg rx_data_ready; +reg tx_error_no_keyboard_ack; + +// Internal signal declarations +wire timer_60usec_done; +wire timer_5usec_done; +wire released; + + // 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; + +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 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. +reg ps2_clk_ms; +reg ps2_data_ms; + + +reg [15:0] timer_5usec; +reg timer_done; + + + +//-------------------------------------------------------------------------- +// Module code + +assign ps2_clk_en_o_ = ps2_clk_hi_z ; +assign ps2_data_en_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_ms <= #1 ps2_clk_i; + ps2_data_ms <= #1 ps2_data_i; + + ps2_clk_s <= #1 ps2_clk_ms; + ps2_data_s <= #1 ps2_data_ms; + +end + +// State register +always @(posedge clk or posedge reset) +begin : m1_state_register + if (reset) m1_state <= #1 m1_rx_clk_h; + else m1_state <= #1 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 1; + ps2_data_hi_z <= #1 1; + tx_error_no_keyboard_ack <= #1 1'b0; + enable_timer_60usec <= #1 0; + enable_timer_5usec <= #1 0; + + case (m1_state) + + m1_rx_clk_h : + begin + enable_timer_60usec <= #1 1; + if (tx_write) m1_next_state <= #1 m1_tx_reset_timer; + else if (~ps2_clk_s) m1_next_state <= #1 m1_rx_falling_edge_marker; + else m1_next_state <= #1 m1_rx_clk_h; + end + + m1_rx_falling_edge_marker : + begin + enable_timer_60usec <= #1 0; + m1_next_state <= #1 m1_rx_clk_l; + end + + m1_rx_rising_edge_marker : + begin + enable_timer_60usec <= #1 0; + m1_next_state <= #1 m1_rx_clk_h; + end + + + m1_rx_clk_l : + begin + enable_timer_60usec <= #1 1; + if (tx_write) m1_next_state <= #1 m1_tx_reset_timer; + else if (ps2_clk_s) m1_next_state <= #1 m1_rx_rising_edge_marker; + else m1_next_state <= #1 m1_rx_clk_l; + end + + m1_tx_reset_timer: + begin + enable_timer_60usec <= #1 0; + m1_next_state <= #1 m1_tx_force_clk_l; + end + + m1_tx_force_clk_l : + begin + enable_timer_60usec <= #1 1; + ps2_clk_hi_z <= #1 0; // Force the ps2_clk line low. + if (timer_60usec_done) m1_next_state <= #1 m1_tx_first_wait_clk_h; + else m1_next_state <= #1 m1_tx_force_clk_l; + end + + m1_tx_first_wait_clk_h : + begin + enable_timer_5usec <= #1 1; + ps2_data_hi_z <= #1 0; // Start bit. + if (~ps2_clk_s && timer_5usec_done) + m1_next_state <= #1 m1_tx_clk_l; + else + m1_next_state <= #1 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 <= #1 0; + if (~ps2_clk_s) m1_next_state <= #1 m1_tx_clk_l; + else m1_next_state <= #1 m1_tx_first_wait_clk_l; + end + + m1_tx_wait_clk_h : + begin + enable_timer_5usec <= #1 1; + ps2_data_hi_z <= #1 q[0]; + if (ps2_clk_s && timer_5usec_done) + m1_next_state <= #1 m1_tx_rising_edge_marker; + else + m1_next_state <= #1 m1_tx_wait_clk_h; + end + + m1_tx_rising_edge_marker : + begin + ps2_data_hi_z <= #1 q[0]; + m1_next_state <= #1 m1_tx_clk_h; + end + + m1_tx_clk_h : + begin + ps2_data_hi_z <= #1 q[0]; + if (tx_shifting_done) m1_next_state <= #1 m1_tx_wait_keyboard_ack; + else if (~ps2_clk_s) m1_next_state <= #1 m1_tx_clk_l; + else m1_next_state <= #1 m1_tx_clk_h; + end + + m1_tx_clk_l : + begin + ps2_data_hi_z <= #1 q[0]; + if (ps2_clk_s) m1_next_state <= #1 m1_tx_wait_clk_h; + else m1_next_state <= #1 m1_tx_clk_l; + end + + m1_tx_wait_keyboard_ack : + begin + if (~ps2_clk_s && ps2_data_s) + m1_next_state <= #1 m1_tx_error_no_keyboard_ack; + else if (~ps2_clk_s && ~ps2_data_s) + m1_next_state <= #1 m1_tx_done_recovery; + else m1_next_state <= #1 m1_tx_wait_keyboard_ack; + end + + m1_tx_done_recovery : + begin + if (ps2_clk_s && ps2_data_s) m1_next_state <= #1 m1_rx_clk_h; + else m1_next_state <= #1 m1_tx_done_recovery; + end + + m1_tx_error_no_keyboard_ack : + begin + tx_error_no_keyboard_ack <= #1 1; + if (ps2_clk_s && ps2_data_s) m1_next_state <= #1 m1_rx_clk_h; + else m1_next_state <= #1 m1_tx_error_no_keyboard_ack; + end + + default : m1_next_state <= #1 m1_rx_clk_h; + endcase +end + +// State register +always @(posedge clk or posedge reset) +begin : m2_state_register + if (reset) m2_state <= #1 m2_rx_data_ready_ack; + else m2_state <= #1 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 1'b0; + if (rx_output_strobe) m2_next_state <= #1 m2_rx_data_ready; + else m2_next_state <= #1 m2_rx_data_ready_ack; + end + m2_rx_data_ready: + begin + rx_data_ready <= #1 1'b1; + if (rx_read) m2_next_state <= #1 m2_rx_data_ready_ack; + else m2_next_state <= #1 m2_rx_data_ready; + end + default : m2_next_state <= #1 m2_rx_data_ready_ack; + endcase +end + +// This is the bit counter +always @(posedge clk or posedge reset) +begin + if ( reset) bit_count <= #1 0; + else if ( rx_shifting_done || (m1_state == m1_tx_wait_keyboard_ack) // After tx is done. + ) bit_count <= #1 0; // normal reset + else if (timer_60usec_done + && (m1_state == m1_rx_clk_h) + && (ps2_clk_s) + ) bit_count <= #1 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 <= #1 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 or posedge reset) +begin + if (reset) q <= #1 0; + else if (tx_write_ack_o) q <= #1 {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 <= #1 {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 <= #1 0; + else if ( timer_done && !timer_60usec_done) + timer_60usec_count<= #1 timer_60usec_count +1; + end +assign timer_60usec_done = (timer_60usec_count == (TIMER_60USEC_VALUE_PP )); + + + +always @(posedge clk or posedge reset) +if (reset) timer_5usec <= #1 1; +else if (!enable_timer_60usec) timer_5usec <= #1 1; +else if (timer_5usec == devide_reg_i) + begin + timer_5usec <= #1 1; + timer_done <= #1 1; + end +else + begin + timer_5usec<= #1 timer_5usec +1; + timer_done <= #1 0; + end + +// This is the 5usec timer counter +always @(posedge clk) +begin + if (~enable_timer_5usec) timer_5usec_count <= #1 0; + else if (~timer_5usec_done) timer_5usec_count <= #1 timer_5usec_count + 1; +end +assign timer_5usec_done = (timer_5usec_count == devide_reg_i -1); + + +// Create the signals which indicate special scan codes received. +// These are the "unlatched versions." +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 or posedge reset) +begin + if (reset) hold_released <= #1 0; + else if (rx_output_event) + begin + hold_released <= #1 0; + end + else + begin + if (rx_shifting_done && released) hold_released <= #1 1; + end +end + +// Output the special scan code flags, the scan code and the ascii +always @(posedge clk or posedge reset) +begin + if (reset) + begin + rx_released <= #1 0; + rx_scan_code <= #1 0; + end + else if (rx_output_strobe) + begin + rx_released <= #1 hold_released; + rx_scan_code <= #1 q[8:1]; + 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 + && ~released + ); + +assign rx_output_strobe = (rx_shifting_done + && ~released + ); + +endmodule + +//`undefine TOTAL_BITS +//`undefine EXTEND_CODE +//`undefine RELEASE_CODE +//`undefine LEFT_SHIFT +//`undefine RIGHT_SHIFT +
tags/rel_13/rtl/verilog/ps2_keyboard.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/rel_13/rtl/verilog/ps2_defines.v =================================================================== --- tags/rel_13/rtl/verilog/ps2_defines.v (nonexistent) +++ tags/rel_13/rtl/verilog/ps2_defines.v (revision 42) @@ -0,0 +1,78 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// ps2_defines.v //// +//// //// +//// This file is part of the "ps2" project //// +//// http://www.opencores.org/cores/ps2/ //// +//// //// +//// Author(s): //// +//// - mihad@opencores.org //// +//// - Miha Dolenc //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: not supported by cvs2svn $ +// Revision 1.4 2003/07/01 12:34:03 mihad +// Added an option to use constant values instead of RAM +// in the translation table. +// +// Revision 1.3 2002/04/09 13:21:15 mihad +// Added mouse interface and everything for its handling, cleaned up some unused code +// +// Revision 1.2 2002/02/18 16:33:08 mihad +// Changed defines for simulation to work without xilinx primitives +// +// Revision 1.1.1.1 2002/02/18 16:16:56 mihad +// Initial project import - working +// +// + +//`define PS2_RAMB4 +`define PS2_CONSTANTS_ROM + +`define PS2_TRANSLATION_TABLE_31_0 256'h5b03111e1f2c71665a02101d702a386559290f3e40424464583c3b3d3f4143ff +`define PS2_TRANSLATION_TABLE_63_32 256'h5f0908162432726a5e071522233031695d061314212f39685c040512202d2e67 +`define PS2_TRANSLATION_TABLE_95_64 256'h76632b751b1c363a6e620d1a7428736d610c19272635346c600a0b181725336b +`define PS2_TRANSLATION_TABLE_127_96 256'h544649374a514e574501484d4c5053526f7f7e474b7d4f7c7b0e7a7978775655 +`define PS2_TRANSLATION_TABLE_159_128 256'h9f9e9d9c9b9a999897969594939291908f8e8d8c8b8a89888786855441828180 +`define PS2_TRANSLATION_TABLE_191_160 256'hbfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a0 +`define PS2_TRANSLATION_TABLE_223_192 256'hdfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0 +`define PS2_TRANSLATION_TABLE_255_224 256'hfffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0 + +`define PS2_TIMER_60USEC_VALUE_PP 12 // Number of sys_clks for 60usec. +`define PS2_TIMER_60USEC_BITS_PP 4 // Number of bits needed for timer +`define PS2_TIMER_5USEC_VALUE_PP 500 // Number of sys_clks for debounce +`define PS2_TIMER_5USEC_BITS_PP 16 // Number of bits needed for timer + +//`define PS2_AUX
tags/rel_13/rtl/verilog/ps2_defines.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/rel_13/rtl/verilog/ps2_top.v =================================================================== --- tags/rel_13/rtl/verilog/ps2_top.v (nonexistent) +++ tags/rel_13/rtl/verilog/ps2_top.v (revision 42) @@ -0,0 +1,305 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// ps2_top.v //// +//// //// +//// This file is part of the "ps2" project //// +//// http://www.opencores.org/cores/ps2/ //// +//// //// +//// Author(s): //// +//// - mihad@opencores.org //// +//// - Miha Dolenc //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: not supported by cvs2svn $ +// Revision 1.5 2003/06/30 15:29:27 simons +// Error fixed again. +// +// Revision 1.4 2003/06/30 15:25:45 simons +// Error fixed. +// +// Revision 1.3 2003/05/28 16:27:09 simons +// Change the address width. +// +// Revision 1.2 2002/04/09 13:21:15 mihad +// Added mouse interface and everything for its handling, cleaned up some unused code +// +// Revision 1.1.1.1 2002/02/18 16:16:56 mihad +// Initial project import - working +// +// + +`include "ps2_defines.v" +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module ps2_top +( + wb_clk_i, + wb_rst_i, + wb_cyc_i, + wb_stb_i, + wb_we_i, + wb_sel_i, + wb_adr_i, + wb_dat_i, + wb_dat_o, + wb_ack_o, + + wb_int_o, + + ps2_kbd_clk_pad_i, + ps2_kbd_data_pad_i, + ps2_kbd_clk_pad_o, + ps2_kbd_data_pad_o, + ps2_kbd_clk_pad_oe_o, + ps2_kbd_data_pad_oe_o + `ifdef PS2_AUX + , + wb_intb_o, + + ps2_aux_clk_pad_i, + ps2_aux_data_pad_i, + ps2_aux_clk_pad_o, + ps2_aux_data_pad_o, + ps2_aux_clk_pad_oe_o, + ps2_aux_data_pad_oe_o + `endif +) ; + +input wb_clk_i, + wb_rst_i, + wb_cyc_i, + wb_stb_i, + wb_we_i ; + +input [3:0] wb_sel_i ; + +input [3:0] wb_adr_i ; +input [31:0] wb_dat_i ; + +output [31:0] wb_dat_o ; + +output wb_ack_o ; + +output wb_int_o ; + +input ps2_kbd_clk_pad_i, + ps2_kbd_data_pad_i ; + +output ps2_kbd_clk_pad_o, + ps2_kbd_data_pad_o, + ps2_kbd_clk_pad_oe_o, + ps2_kbd_data_pad_oe_o ; + +`ifdef PS2_AUX +output wb_intb_o ; +input ps2_aux_clk_pad_i, + ps2_aux_data_pad_i ; + +output ps2_aux_clk_pad_o, + ps2_aux_data_pad_o, + ps2_aux_clk_pad_oe_o, + ps2_aux_data_pad_oe_o ; + +assign ps2_aux_clk_pad_o = 1'b0 ; +assign ps2_aux_data_pad_o = 1'b0 ; +`endif + +wire rx_released, + rx_kbd_data_ready, + rx_translated_data_ready, + rx_kbd_read_wb, + rx_kbd_read_tt, + tx_kbd_write, + tx_kbd_write_ack, + tx_error_no_keyboard_ack, + ps2_ctrl_kbd_data_en_, + ps2_ctrl_kbd_clk_en_, + ps2_ctrl_kbd_clk, + inhibit_kbd_if ; + +wire [15:0] devide_reg; + +wire [7:0] rx_scan_code, + rx_translated_scan_code, + tx_kbd_data ; + +assign ps2_kbd_clk_pad_o = 1'b0 ; +assign ps2_kbd_data_pad_o = 1'b0 ; + +ps2_io_ctrl i_ps2_io_ctrl_keyboard +( + .clk_i (wb_clk_i), + .rst_i (wb_rst_i), + .ps2_ctrl_clk_en_i_ (ps2_ctrl_kbd_clk_en_), + .ps2_ctrl_data_en_i_ (ps2_ctrl_kbd_data_en_), + .ps2_clk_pad_i (ps2_kbd_clk_pad_i), + .ps2_clk_pad_oe_o (ps2_kbd_clk_pad_oe_o), + .ps2_data_pad_oe_o (ps2_kbd_data_pad_oe_o), + .inhibit_if_i (inhibit_kbd_if), + .ps2_ctrl_clk_o (ps2_ctrl_kbd_clk) +); + +`ifdef PS2_AUX +wire rx_aux_data_ready, + rx_aux_read, + tx_aux_write, + tx_aux_write_ack, + tx_error_no_aux_ack, + ps2_ctrl_aux_data_en_, + ps2_ctrl_aux_clk_en_, + ps2_ctrl_aux_clk, + inhibit_aux_if ; + +wire [7:0] rx_aux_data, + tx_aux_data ; + +ps2_io_ctrl i_ps2_io_ctrl_auxiliary +( + .clk_i (wb_clk_i), + .rst_i (wb_rst_i), + .ps2_ctrl_clk_en_i_ (ps2_ctrl_aux_clk_en_), + .ps2_ctrl_data_en_i_ (ps2_ctrl_aux_data_en_), + .ps2_clk_pad_i (ps2_aux_clk_pad_i), + .ps2_clk_pad_oe_o (ps2_aux_clk_pad_oe_o), + .ps2_data_pad_oe_o (ps2_aux_data_pad_oe_o), + .inhibit_if_i (inhibit_aux_if), + .ps2_ctrl_clk_o (ps2_ctrl_aux_clk) +); + +ps2_mouse #(`PS2_TIMER_60USEC_VALUE_PP, `PS2_TIMER_60USEC_BITS_PP, `PS2_TIMER_5USEC_VALUE_PP, `PS2_TIMER_5USEC_BITS_PP) +i_ps2_mouse +( + .clk (wb_clk_i), + .reset (wb_rst_i), + .ps2_clk_en_o_ (ps2_ctrl_aux_clk_en_), + .ps2_data_en_o_ (ps2_ctrl_aux_data_en_), + .ps2_clk_i (ps2_ctrl_aux_clk), + .ps2_data_i (ps2_aux_data_pad_i), + .rx_scan_code (rx_aux_data), + .rx_data_ready (rx_aux_data_ready), + .rx_read (rx_aux_read), + .tx_data (tx_aux_data), + .tx_write (tx_aux_write), + .tx_write_ack_o (tx_aux_write_ack), + .tx_error_no_ack (tx_error_no_aux_ack), + .devide_reg_i (devide_reg) +); + +`endif + +ps2_keyboard #(`PS2_TIMER_60USEC_VALUE_PP, `PS2_TIMER_60USEC_BITS_PP, `PS2_TIMER_5USEC_VALUE_PP, `PS2_TIMER_5USEC_BITS_PP) +i_ps2_keyboard +( + .clk (wb_clk_i), + .reset (wb_rst_i), + .ps2_clk_en_o_ (ps2_ctrl_kbd_clk_en_), + .ps2_data_en_o_ (ps2_ctrl_kbd_data_en_), + .ps2_clk_i (ps2_ctrl_kbd_clk), + .ps2_data_i (ps2_kbd_data_pad_i), + .rx_released (rx_released), + .rx_scan_code (rx_scan_code), + .rx_data_ready (rx_kbd_data_ready), + .rx_read (rx_kbd_read_tt), + .tx_data (tx_kbd_data), + .tx_write (tx_kbd_write), + .tx_write_ack_o (tx_kbd_write_ack), + .tx_error_no_keyboard_ack (tx_error_no_keyboard_ack), + .translate (translate), + .devide_reg_i (devide_reg) +); + +ps2_wb_if i_ps2_wb_if +( + .wb_clk_i (wb_clk_i), + .wb_rst_i (wb_rst_i), + .wb_cyc_i (wb_cyc_i), + .wb_stb_i (wb_stb_i), + .wb_we_i (wb_we_i), + .wb_sel_i (wb_sel_i), + .wb_adr_i (wb_adr_i), + .wb_dat_i (wb_dat_i), + .wb_dat_o (wb_dat_o), + .wb_ack_o (wb_ack_o), + + .wb_int_o (wb_int_o), + + .devide_reg_o (devide_reg), + + .rx_scancode_i (rx_translated_scan_code), + .rx_kbd_data_ready_i (rx_translated_data_ready), + .rx_kbd_read_o (rx_kbd_read_wb), + .tx_kbd_data_o (tx_kbd_data), + .tx_kbd_write_o (tx_kbd_write), + .tx_kbd_write_ack_i (tx_kbd_write_ack), + .translate_o (translate), + .ps2_kbd_clk_i (ps2_kbd_clk_pad_i), + .inhibit_kbd_if_o (inhibit_kbd_if) + `ifdef PS2_AUX + , + .wb_intb_o (wb_intb_o), + + .rx_aux_data_i (rx_aux_data), + .rx_aux_data_ready_i (rx_aux_data_ready), + .rx_aux_read_o (rx_aux_read), + .tx_aux_data_o (tx_aux_data), + .tx_aux_write_o (tx_aux_write), + .tx_aux_write_ack_i (tx_aux_write_ack), + .ps2_aux_clk_i (ps2_aux_clk_pad_i), + .inhibit_aux_if_o (inhibit_aux_if) + `endif +) ; + +ps2_translation_table i_ps2_translation_table +( + .reset_i (wb_rst_i), + .clock_i (wb_clk_i), + .translate_i (translate), + .code_i (rx_scan_code), + .code_o (rx_translated_scan_code), + .address_i (8'h00), + .data_i (8'h00), + .we_i (1'b0), + .re_i (1'b0), + .data_o (), + .rx_data_ready_i (rx_kbd_data_ready), + .rx_translated_data_ready_o (rx_translated_data_ready), + .rx_read_i (rx_kbd_read_wb), + .rx_read_o (rx_kbd_read_tt), + .rx_released_i (rx_released) +) ; + +endmodule // ps2_top Index: tags/rel_13/rtl/verilog/ps2_translation_table.v =================================================================== --- tags/rel_13/rtl/verilog/ps2_translation_table.v (nonexistent) +++ tags/rel_13/rtl/verilog/ps2_translation_table.v (revision 42) @@ -0,0 +1,290 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// ps2_translation_table.v //// +//// //// +//// This file is part of the "ps2" project //// +//// http://www.opencores.org/cores/ps2/ //// +//// //// +//// Author(s): //// +//// - mihad@opencores.org //// +//// - Miha Dolenc //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: not supported by cvs2svn $ +// Revision 1.3 2003/06/02 17:13:22 simons +// resetall keyword removed. ifdef moved to a separated line. +// +// Revision 1.2 2002/04/09 13:21:15 mihad +// Added mouse interface and everything for its handling, cleaned up some unused code +// +// Revision 1.1.1.1 2002/02/18 16:16:56 mihad +// Initial project import - working +// +// + +`include "ps2_defines.v" + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module ps2_translation_table +( + reset_i, + clock_i, + translate_i, + code_i, + code_o, + address_i, + data_i, + we_i, + re_i, + data_o, + rx_data_ready_i, + rx_translated_data_ready_o, + rx_read_i, + rx_read_o, + rx_released_i +) ; + +input reset_i, + clock_i, + translate_i ; + +input [7:0] code_i ; +output [7:0] code_o ; +input [7:0] address_i ; +input [7:0] data_i ; +input we_i, + re_i ; + +output [7:0] data_o ; + +input rx_data_ready_i, + rx_read_i ; + +output rx_translated_data_ready_o ; +output rx_read_o ; + +input rx_released_i ; + +wire translation_table_write_enable = we_i && (!translate_i || !rx_data_ready_i) ; +wire [7:0] translation_table_address = ((we_i || re_i) && (!rx_data_ready_i || !translate_i)) ? address_i : code_i ; +wire translation_table_enable = we_i || re_i || (translate_i && rx_data_ready_i) ; + +reg rx_translated_data_ready ; +always@(posedge clock_i or posedge reset_i) +begin + if ( reset_i ) + rx_translated_data_ready <= #1 1'b0 ; + else if ( rx_read_i || !translate_i ) + rx_translated_data_ready <= #1 1'b0 ; + else + rx_translated_data_ready <= #1 rx_data_ready_i ; +end + +`ifdef PS2_RAMB4 + `define PS2_RAM_SELECTED + + wire [7:0] ram_out ; + RAMB4_S8 + `ifdef SIM + #("ignore", + `PS2_TRANSLATION_TABLE_31_0, + `PS2_TRANSLATION_TABLE_63_32, + `PS2_TRANSLATION_TABLE_95_64, + `PS2_TRANSLATION_TABLE_127_96, + `PS2_TRANSLATION_TABLE_159_128, + `PS2_TRANSLATION_TABLE_191_160, + `PS2_TRANSLATION_TABLE_223_192, + `PS2_TRANSLATION_TABLE_255_224) + `endif + ps2_ram + ( + .DO (ram_out), + .ADDR ({1'b0, translation_table_address}), + .DI (data_i), + .EN (translation_table_enable), + .CLK (clock_i), + .WE (translation_table_write_enable), + .RST (reset_i) + ) ; + +`endif + +`ifdef PS2_CONSTANTS_ROM + `define PS2_RAM_SELECTED + + reg [32 * 8 - 1:0] ps2_32byte_constant ; + reg [7:0] ram_out ; + + always@(translation_table_address) + begin + case (translation_table_address[7:5]) + 3'b000:ps2_32byte_constant = `PS2_TRANSLATION_TABLE_31_0 ; + 3'b001:ps2_32byte_constant = `PS2_TRANSLATION_TABLE_63_32 ; + 3'b010:ps2_32byte_constant = `PS2_TRANSLATION_TABLE_95_64 ; + 3'b011:ps2_32byte_constant = `PS2_TRANSLATION_TABLE_127_96 ; + 3'b100:ps2_32byte_constant = `PS2_TRANSLATION_TABLE_159_128 ; + 3'b101:ps2_32byte_constant = `PS2_TRANSLATION_TABLE_191_160 ; + 3'b110:ps2_32byte_constant = `PS2_TRANSLATION_TABLE_223_192 ; + 3'b111:ps2_32byte_constant = `PS2_TRANSLATION_TABLE_255_224 ; + endcase + end + + always@(posedge clock_i or posedge reset_i) + begin + if ( reset_i ) + ram_out <= #1 8'h0 ; + else if ( translation_table_enable ) + begin:get_dat_out + reg [7:0] bit_num ; + + bit_num = translation_table_address[4:0] << 3 ; + + repeat(8) + begin + ram_out[bit_num % 8] <= #1 ps2_32byte_constant[bit_num] ; + bit_num = bit_num + 1'b1 ; + end + end + end + +`endif + +`ifdef PS2_RAM_SELECTED +`else + `define PS2_RAM_SELECTED + + reg [7:0] ps2_ram [0:255] ; + reg [7:0] ram_out ; + + always@(posedge clock_i or posedge reset_i) + begin + if ( reset_i ) + ram_out <= #1 8'h0 ; + else if ( translation_table_enable ) + ram_out <= #1 ps2_ram[translation_table_address] ; + end + + always@(posedge clock_i) + begin + if ( translation_table_write_enable ) + ps2_ram[translation_table_address] <= #1 data_i ; + end + + // synopsys translate_off + initial + begin:ps2_ram_init + integer i ; + reg [255:0] temp_init_val ; + + temp_init_val = `PS2_TRANSLATION_TABLE_31_0 ; + + for ( i = 0 ; i <= 31 ; i = i + 1 ) + begin + ps2_ram[i] = temp_init_val[7:0] ; + temp_init_val = temp_init_val >> 8 ; + end + + temp_init_val = `PS2_TRANSLATION_TABLE_63_32 ; + + for ( i = 32 ; i <= 63 ; i = i + 1 ) + begin + ps2_ram[i] = temp_init_val[7:0] ; + temp_init_val = temp_init_val >> 8 ; + end + + temp_init_val = `PS2_TRANSLATION_TABLE_95_64 ; + + for ( i = 64 ; i <= 95 ; i = i + 1 ) + begin + ps2_ram[i] = temp_init_val[7:0] ; + temp_init_val = temp_init_val >> 8 ; + end + + temp_init_val = `PS2_TRANSLATION_TABLE_127_96 ; + + for ( i = 96 ; i <= 127 ; i = i + 1 ) + begin + ps2_ram[i] = temp_init_val[7:0] ; + temp_init_val = temp_init_val >> 8 ; + end + + temp_init_val = `PS2_TRANSLATION_TABLE_159_128 ; + + for ( i = 128 ; i <= 159 ; i = i + 1 ) + begin + ps2_ram[i] = temp_init_val[7:0] ; + temp_init_val = temp_init_val >> 8 ; + end + + temp_init_val = `PS2_TRANSLATION_TABLE_191_160 ; + + for ( i = 160 ; i <= 191 ; i = i + 1 ) + begin + ps2_ram[i] = temp_init_val[7:0] ; + temp_init_val = temp_init_val >> 8 ; + end + + temp_init_val = `PS2_TRANSLATION_TABLE_223_192 ; + + for ( i = 192 ; i <= 223 ; i = i + 1 ) + begin + ps2_ram[i] = temp_init_val[7:0] ; + temp_init_val = temp_init_val >> 8 ; + end + + temp_init_val = `PS2_TRANSLATION_TABLE_255_224 ; + + for ( i = 224 ; i <= 255 ; i = i + 1 ) + begin + ps2_ram[i] = temp_init_val[7:0] ; + temp_init_val = temp_init_val >> 8 ; + end + end + + // synopsys translate_on + +`endif + +assign data_o = ram_out ; +assign code_o = translate_i ? {(rx_released_i | ram_out[7]), ram_out[6:0]} : code_i ; +assign rx_translated_data_ready_o = translate_i ? rx_translated_data_ready : rx_data_ready_i ; +assign rx_read_o = rx_read_i ; + +`undef PS2_RAM_SELECTED + +endmodule //ps2_translation_table Index: tags/rel_13/rtl/verilog/ps2_io_ctrl.v =================================================================== --- tags/rel_13/rtl/verilog/ps2_io_ctrl.v (nonexistent) +++ tags/rel_13/rtl/verilog/ps2_io_ctrl.v (revision 42) @@ -0,0 +1,106 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// ps2_io_ctrl.v //// +//// //// +//// This file is part of the "ps2" project //// +//// http://www.opencores.org/cores/ps2/ //// +//// //// +//// Author(s): //// +//// - mihad@opencores.org //// +//// - Miha Dolenc //// +//// //// +//// All additional information is avaliable in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: not supported by cvs2svn $ +// Revision 1.1.1.1 2002/02/18 16:16:56 mihad +// Initial project import - working +// +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module ps2_io_ctrl +( + clk_i, + rst_i, + ps2_ctrl_clk_en_i_, + ps2_ctrl_data_en_i_, + ps2_clk_pad_i, + ps2_clk_pad_oe_o, + ps2_data_pad_oe_o, + inhibit_if_i, + ps2_ctrl_clk_o +); + +input clk_i, + rst_i, + ps2_ctrl_clk_en_i_, + ps2_ctrl_data_en_i_, + ps2_clk_pad_i, + inhibit_if_i ; + +output ps2_clk_pad_oe_o, + ps2_data_pad_oe_o, + ps2_ctrl_clk_o ; + +reg ps2_clk_pad_oe_o, + ps2_data_pad_oe_o ; + +always@(posedge clk_i or posedge rst_i) +begin + if ( rst_i ) + begin + ps2_clk_pad_oe_o <= #1 1'b0 ; + ps2_data_pad_oe_o <= #1 1'b0 ; + end + else + begin + ps2_clk_pad_oe_o <= #1 !ps2_ctrl_clk_en_i_ || inhibit_if_i ; + ps2_data_pad_oe_o <= #1 !ps2_ctrl_data_en_i_ ; + end +end + +reg inhibit_if_previous ; +always@(posedge clk_i or posedge rst_i) +begin + if ( rst_i ) + inhibit_if_previous <= #1 1'b1 ; + else + inhibit_if_previous <= #1 inhibit_if_i ; +end + +assign ps2_ctrl_clk_o = ps2_clk_pad_i || ps2_clk_pad_oe_o && inhibit_if_previous ; +endmodule // ps2_io_ctrl Index: tags/rel_13/rtl/verilog/timescale.v =================================================================== --- tags/rel_13/rtl/verilog/timescale.v (nonexistent) +++ tags/rel_13/rtl/verilog/timescale.v (revision 42) @@ -0,0 +1 @@ +`timescale 1ns/1ps \ No newline at end of file Index: tags/rel_13/syn/xilinx/constraints/ps2.ucf =================================================================== --- tags/rel_13/syn/xilinx/constraints/ps2.ucf (nonexistent) +++ tags/rel_13/syn/xilinx/constraints/ps2.ucf (revision 42) @@ -0,0 +1,8 @@ +INST *ps2_ram INIT_00 = 5b03111e1f2c71665a02101d702a386559290f3e40424464583c3b3d3f4143ff ; +INST *ps2_ram INIT_01 = 5f0908162432726a5e071522233031695d061314212f39685c040512202d2e67 ; +INST *ps2_ram INIT_02 = 76632b751b1c363a6e620d1a7428736d610c19272635346c600a0b181725336b ; +INST *ps2_ram INIT_03 = 544649374a514e574501484d4c5053526f7f7e474b7d4f7c7b0e7a7978775655 ; +INST *ps2_ram INIT_04 = 9f9e9d9c9b9a999897969594939291908f8e8d8c8b8a89888786855441828180 ; +INST *ps2_ram INIT_05 = bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a0 ; +INST *ps2_ram INIT_06 = dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0 ; +INST *ps2_ram INIT_07 = fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0 ;
tags/rel_13/syn/xilinx/constraints/ps2.ucf Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/rel_13/syn/xilinx/constraints/ps2.sdc =================================================================== --- tags/rel_13/syn/xilinx/constraints/ps2.sdc (nonexistent) +++ tags/rel_13/syn/xilinx/constraints/ps2.sdc (revision 42) @@ -0,0 +1,33 @@ +# Synplicity, Inc. constraint file +# G:\ps2\mihad\ps2\syn\xilinx\constraints\ps2.sdc +# Written on Mon Feb 18 14:17:46 2002 +# by Synplify Pro, 7.0 Beta3 Scope Editor + +# +# Clocks +# + +# +# Inputs/Outputs +# + +# +# Registers +# + +# +# Multicycle Path +# + +# +# False Path +# + +# +# Attributes +# +define_global_attribute syn_netlist_hierarchy {0} + +# +# Other Constraints +#
tags/rel_13/syn/xilinx/constraints/ps2.sdc Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/rel_13/misc/scancode_translation_values =================================================================== --- tags/rel_13/misc/scancode_translation_values (nonexistent) +++ tags/rel_13/misc/scancode_translation_values (revision 42) @@ -0,0 +1,17 @@ +Values are listed from 0 - 255 +0xff,0x43,0x41,0x3f,0x3d,0x3b,0x3c,0x58,0x64,0x44,0x42,0x40,0x3e,0x0f,0x29,0x59, +0x65,0x38,0x2a,0x70,0x1d,0x10,0x02,0x5a,0x66,0x71,0x2c,0x1f,0x1e,0x11,0x03,0x5b, +0x67,0x2e,0x2d,0x20,0x12,0x05,0x04,0x5c,0x68,0x39,0x2f,0x21,0x14,0x13,0x06,0x5d, +0x69,0x31,0x30,0x23,0x22,0x15,0x07,0x5e,0x6a,0x72,0x32,0x24,0x16,0x08,0x09,0x5f, +0x6b,0x33,0x25,0x17,0x18,0x0b,0x0a,0x60,0x6c,0x34,0x35,0x26,0x27,0x19,0x0c,0x61, +0x6d,0x73,0x28,0x74,0x1a,0x0d,0x62,0x6e,0x3a,0x36,0x1c,0x1b,0x75,0x2b,0x63,0x76, +0x55,0x56,0x77,0x78,0x79,0x7a,0x0e,0x7b,0x7c,0x4f,0x7d,0x4b,0x47,0x7e,0x7f,0x6f, +0x52,0x53,0x50,0x4c,0x4d,0x48,0x01,0x45,0x57,0x4e,0x51,0x4a,0x37,0x49,0x46,0x54, +0x80,0x81,0x82,0x41,0x54,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, +0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, +0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, +0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, +0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf, +0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, +0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef, +0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff \ No newline at end of file
tags/rel_13/misc/scancode_translation_values Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property

powered by: WebSVN 2.1.0

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