URL
https://opencores.org/ocsvn/ps2/ps2/trunk
Subversion Repositories ps2
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 15 to Rev 16
- ↔ Reverse comparison
Rev 15 → Rev 16
/tags/rel_2/bench/verilog/ps2_sim_top.v
0,0 → 1,156
////////////////////////////////////////////////////////////////////// |
//// //// |
//// 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.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 [2:0] wb_adr_i, |
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 |
/tags/rel_2/bench/verilog/ps2_test_bench.v
0,0 → 1,1580
////////////////////////////////////////////////////////////////////// |
//// //// |
//// 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.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 ; |
|
`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 error ; |
|
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) ; |
|
if ( ((`PS2_TIMER_5USEC_VALUE_PP * `WB_PERIOD) < 5000) || ((`PS2_TIMER_5USEC_VALUE_PP * `WB_PERIOD) > 6000) ) |
begin |
$display("Warning! 5us timer max value is not defined correctly regarding to WISHBONE bus clock!") ; |
$stop ; |
end |
|
if ( ((`PS2_TIMER_60USEC_VALUE_PP * `WB_PERIOD) < 60000) || ((`PS2_TIMER_60USEC_VALUE_PP * `WB_PERIOD) > 61000) ) |
begin |
$display("Warning! 60us timer max value is not defined correctly regarding to WISHBONE bus clock!") ; |
$stop ; |
end |
|
if ( (1 << `PS2_TIMER_5USEC_BITS_PP) < `PS2_TIMER_5USEC_VALUE_PP ) |
begin |
$display("Warning! 5us timer max value is not defined correctly regarding to the length in bits of 5us timer!") ; |
$stop ; |
end |
|
if ( (1 << `PS2_TIMER_60USEC_BITS_PP) < `PS2_TIMER_60USEC_VALUE_PP ) |
begin |
$display("Warning! 60us timer max value is not defined correctly regarding to the length in bits of 60us timer!") ; |
$stop ; |
end |
|
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 ; |
|
@(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 ; |
|
#400 $stop ; |
end |
|
always |
#(`WB_PERIOD / 2) 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[2: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! ") ; |
#400 $stop ; |
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! ") ; |
#400 $stop ; |
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 ) ; |
#400 $stop ; |
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 ) ; |
#400 $stop ; |
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 ) ; |
#400 $stop ; |
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 ) ; |
#400 $stop ; |
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!") ; |
#400 $stop ; |
end |
end |
begin |
@(char_valid) ; |
if ( {received_char, 24'h0} !== `KBD_RESET ) |
begin |
$display("Error! Keyboard received invalid character/command") ; |
#400 $stop ; |
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") ; |
#400 $stop ; |
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") ; |
#400 $stop ; |
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!") ; |
#400 $stop ; |
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!") ; |
#400 $stop ; |
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") ; |
#400 $stop ; |
ok_o = 0 ; |
end |
end |
endtask // kbd_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!") ; |
#400 $stop ; |
end |
|
if ( temp_data & `AUX_OBUF_FULL ) |
begin |
$display("Error! Interrupt received from keyboard controler when AUX_OBUF_FULL status was set!") ; |
#400 $stop ; |
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 |
#5000 ; |
|
// 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!") ; |
#400 $stop ; |
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 |
/tags/rel_2/bench/verilog/ps2_testbench_defines.v
0,0 → 1,150
////////////////////////////////////////////////////////////////////// |
//// //// |
//// 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.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.025 |
/tags/rel_2/bench/verilog/ps2_keyboard_model.v
0,0 → 1,235
////////////////////////////////////////////////////////////////////// |
//// //// |
//// 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.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 |
|
endmodule // ps2_keyboard_model |
/tags/rel_2/bench/verilog/wb_master_behavioral.v
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 |
|
/tags/rel_2/bench/verilog/wb_master32.v
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 |
/tags/rel_2/bench/data/extended_scancodes_set1.hex
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 |
tags/rel_2/bench/data/extended_scancodes_set1.hex
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: tags/rel_2/bench/data/extended_scancodes_set2.hex
===================================================================
--- tags/rel_2/bench/data/extended_scancodes_set2.hex (nonexistent)
+++ tags/rel_2/bench/data/extended_scancodes_set2.hex (revision 16)
@@ -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_2/bench/data/extended_scancodes_set2.hex
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: tags/rel_2/bench/data/normal_scancodes_set1.hex
===================================================================
--- tags/rel_2/bench/data/normal_scancodes_set1.hex (nonexistent)
+++ tags/rel_2/bench/data/normal_scancodes_set1.hex (revision 16)
@@ -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_2/bench/data/normal_scancodes_set1.hex
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: tags/rel_2/bench/data/normal_scancodes_set2.hex
===================================================================
--- tags/rel_2/bench/data/normal_scancodes_set2.hex (nonexistent)
+++ tags/rel_2/bench/data/normal_scancodes_set2.hex (revision 16)
@@ -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_2/bench/data/normal_scancodes_set2.hex
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: tags/rel_2/rtl/verilog/ps2_top.v
===================================================================
--- tags/rel_2/rtl/verilog/ps2_top.v (nonexistent)
+++ tags/rel_2/rtl/verilog/ps2_top.v (revision 16)
@@ -0,0 +1,290 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// 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.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 [2:0] wb_adr_i,
+ 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 [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)
+);
+
+`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)
+);
+
+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),
+
+ .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_2/rtl/verilog/ps2_wb_if.v
===================================================================
--- tags/rel_2/rtl/verilog/ps2_wb_if.v (nonexistent)
+++ tags/rel_2/rtl/verilog/ps2_wb_if.v (revision 16)
@@ -0,0 +1,686 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// 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.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,
+ 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 [2: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 ;
+
+reg [7: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:24] ;
+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[2:0] == 3'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[2:0] == 3'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[2:0] == 3'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[2:0] == 3'h4) ;
+
+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'b1 ;
+ 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 ;
+ 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 ;
+ 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 ;
+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 ;
+
+wire [7:0] output_data = read_status_register_reg ? status_byte : 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 {4{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 ;
+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_2/rtl/verilog/ps2_io_ctrl.v
===================================================================
--- tags/rel_2/rtl/verilog/ps2_io_ctrl.v (nonexistent)
+++ tags/rel_2/rtl/verilog/ps2_io_ctrl.v (revision 16)
@@ -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_2/rtl/verilog/ps2_defines.v
===================================================================
--- tags/rel_2/rtl/verilog/ps2_defines.v (nonexistent)
+++ tags/rel_2/rtl/verilog/ps2_defines.v (revision 16)
@@ -0,0 +1,71 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// 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.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_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 1500 // Number of sys_clks for 60usec.
+`define PS2_TIMER_60USEC_BITS_PP 11 // Number of bits needed for timer
+`define PS2_TIMER_5USEC_VALUE_PP 125 // Number of sys_clks for debounce
+`define PS2_TIMER_5USEC_BITS_PP 7 // Number of bits needed for timer
+
+//`define PS2_AUX
+
+//`define SIM
tags/rel_2/rtl/verilog/ps2_defines.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: tags/rel_2/rtl/verilog/ps2_keyboard.v
===================================================================
--- tags/rel_2/rtl/verilog/ps2_keyboard.v (nonexistent)
+++ tags/rel_2/rtl/verilog/ps2_keyboard.v (revision 16)
@@ -0,0 +1,536 @@
+//-------------------------------------------------------------------------------------
+//
+// 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
+`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
+ );
+
+// 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 ;
+
+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.
+
+//--------------------------------------------------------------------------
+// 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_s <= ps2_clk_i;
+ ps2_data_s <= ps2_data_i;
+end
+
+// State register
+always @(posedge clk)
+begin : m1_state_register
+ if (reset) m1_state <= m1_rx_clk_h;
+ else m1_state <= m1_next_state;
+end
+
+// State transition logic
+always @(m1_state
+ or q
+ or tx_shifting_done
+ or tx_write
+ or ps2_clk_s
+ or ps2_data_s
+ or timer_60usec_done
+ or timer_5usec_done
+ )
+begin : m1_state_logic
+
+ // Output signals default to this value, unless changed in a state condition.
+ ps2_clk_hi_z <= 1;
+ ps2_data_hi_z <= 1;
+ tx_error_no_keyboard_ack <= 0;
+ enable_timer_60usec <= 0;
+ enable_timer_5usec <= 0;
+
+ case (m1_state)
+
+ m1_rx_clk_h :
+ begin
+ enable_timer_60usec <= 1;
+ if (tx_write) m1_next_state <= m1_tx_reset_timer;
+ else if (~ps2_clk_s) m1_next_state <= m1_rx_falling_edge_marker;
+ else m1_next_state <= m1_rx_clk_h;
+ end
+
+ m1_rx_falling_edge_marker :
+ begin
+ enable_timer_60usec <= 0;
+ m1_next_state <= m1_rx_clk_l;
+ end
+
+ m1_rx_rising_edge_marker :
+ begin
+ enable_timer_60usec <= 0;
+ m1_next_state <= m1_rx_clk_h;
+ end
+
+
+ m1_rx_clk_l :
+ begin
+ enable_timer_60usec <= 1;
+ if (tx_write) m1_next_state <= m1_tx_reset_timer;
+ else if (ps2_clk_s) m1_next_state <= m1_rx_rising_edge_marker;
+ else m1_next_state <= m1_rx_clk_l;
+ end
+
+ m1_tx_reset_timer:
+ begin
+ enable_timer_60usec <= 0;
+ m1_next_state <= m1_tx_force_clk_l;
+ end
+
+ m1_tx_force_clk_l :
+ begin
+ enable_timer_60usec <= 1;
+ ps2_clk_hi_z <= 0; // Force the ps2_clk line low.
+ if (timer_60usec_done) m1_next_state <= m1_tx_first_wait_clk_h;
+ else m1_next_state <= m1_tx_force_clk_l;
+ end
+
+ m1_tx_first_wait_clk_h :
+ begin
+ enable_timer_5usec <= 1;
+ ps2_data_hi_z <= 0; // Start bit.
+ if (~ps2_clk_s && timer_5usec_done)
+ m1_next_state <= m1_tx_clk_l;
+ else
+ m1_next_state <= m1_tx_first_wait_clk_h;
+ end
+
+ // This state must be included because the device might possibly
+ // delay for up to 10 milliseconds before beginning its clock pulses.
+ // During that waiting time, we cannot drive the data (q[0]) because it
+ // is possibly 1, which would cause the keyboard to abort its receive
+ // and the expected clocks would then never be generated.
+ m1_tx_first_wait_clk_l :
+ begin
+ ps2_data_hi_z <= 0;
+ if (~ps2_clk_s) m1_next_state <= m1_tx_clk_l;
+ else m1_next_state <= m1_tx_first_wait_clk_l;
+ end
+
+ m1_tx_wait_clk_h :
+ begin
+ enable_timer_5usec <= 1;
+ ps2_data_hi_z <= q[0];
+ if (ps2_clk_s && timer_5usec_done)
+ m1_next_state <= m1_tx_rising_edge_marker;
+ else
+ m1_next_state <= m1_tx_wait_clk_h;
+ end
+
+ m1_tx_rising_edge_marker :
+ begin
+ ps2_data_hi_z <= q[0];
+ m1_next_state <= m1_tx_clk_h;
+ end
+
+ m1_tx_clk_h :
+ begin
+ ps2_data_hi_z <= q[0];
+ if (tx_shifting_done) m1_next_state <= m1_tx_wait_keyboard_ack;
+ else if (~ps2_clk_s) m1_next_state <= m1_tx_clk_l;
+ else m1_next_state <= m1_tx_clk_h;
+ end
+
+ m1_tx_clk_l :
+ begin
+ ps2_data_hi_z <= q[0];
+ if (ps2_clk_s) m1_next_state <= m1_tx_wait_clk_h;
+ else m1_next_state <= m1_tx_clk_l;
+ end
+
+ m1_tx_wait_keyboard_ack :
+ begin
+ if (~ps2_clk_s && ps2_data_s)
+ m1_next_state <= m1_tx_error_no_keyboard_ack;
+ else if (~ps2_clk_s && ~ps2_data_s)
+ m1_next_state <= m1_tx_done_recovery;
+ else m1_next_state <= m1_tx_wait_keyboard_ack;
+ end
+
+ m1_tx_done_recovery :
+ begin
+ if (ps2_clk_s && ps2_data_s) m1_next_state <= m1_rx_clk_h;
+ else m1_next_state <= m1_tx_done_recovery;
+ end
+
+ m1_tx_error_no_keyboard_ack :
+ begin
+ tx_error_no_keyboard_ack <= 1;
+ if (ps2_clk_s && ps2_data_s) m1_next_state <= m1_rx_clk_h;
+ else m1_next_state <= m1_tx_error_no_keyboard_ack;
+ end
+
+ default : m1_next_state <= m1_rx_clk_h;
+ endcase
+end
+
+// State register
+always @(posedge clk)
+begin : m2_state_register
+ if (reset) m2_state <= m2_rx_data_ready_ack;
+ else m2_state <= m2_next_state;
+end
+
+// State transition logic
+always @(m2_state or rx_output_strobe or rx_read)
+begin : m2_state_logic
+ case (m2_state)
+ m2_rx_data_ready_ack:
+ begin
+ rx_data_ready <= 1'b0;
+ if (rx_output_strobe) m2_next_state <= m2_rx_data_ready;
+ else m2_next_state <= m2_rx_data_ready_ack;
+ end
+ m2_rx_data_ready:
+ begin
+ rx_data_ready <= 1'b1;
+ if (rx_read) m2_next_state <= m2_rx_data_ready_ack;
+ else m2_next_state <= m2_rx_data_ready;
+ end
+ default : m2_next_state <= m2_rx_data_ready_ack;
+ endcase
+end
+
+// This is the bit counter
+always @(posedge clk)
+begin
+ if ( reset
+ || rx_shifting_done
+ || (m1_state == m1_tx_wait_keyboard_ack) // After tx is done.
+ ) bit_count <= 0; // normal reset
+ else if (timer_60usec_done
+ && (m1_state == m1_rx_clk_h)
+ && (ps2_clk_s)
+ ) bit_count <= 0; // rx watchdog timer reset
+ else if ( (m1_state == m1_rx_falling_edge_marker) // increment for rx
+ ||(m1_state == m1_tx_rising_edge_marker) // increment for tx
+ )
+ bit_count <= bit_count + 1;
+end
+// This signal is high for one clock at the end of the timer count.
+assign rx_shifting_done = (bit_count == `TOTAL_BITS);
+assign tx_shifting_done = (bit_count == `TOTAL_BITS-1);
+
+// This is the signal which enables loading of the shift register.
+// It also indicates "ack" to the device writing to the transmitter.
+assign tx_write_ack_o = ( (tx_write && (m1_state == m1_rx_clk_h))
+ ||(tx_write && (m1_state == m1_rx_clk_l))
+ );
+
+// This is the ODD parity bit for the transmitted word.
+assign tx_parity_bit = ~^tx_data;
+
+// This is the shift register
+always @(posedge clk)
+begin
+ if (reset) q <= 0;
+ else if (tx_write_ack_o) q <= {1'b1,tx_parity_bit,tx_data,1'b0};
+ else if ( (m1_state == m1_rx_falling_edge_marker)
+ ||(m1_state == m1_tx_rising_edge_marker) )
+ q <= {ps2_data_s,q[`TOTAL_BITS-1:1]};
+end
+
+// This is the 60usec timer counter
+always @(posedge clk)
+begin
+ if (~enable_timer_60usec) timer_60usec_count <= 0;
+ else if (~timer_60usec_done) timer_60usec_count <= timer_60usec_count + 1;
+end
+assign timer_60usec_done = (timer_60usec_count == (TIMER_60USEC_VALUE_PP - 1));
+
+// This is the 5usec timer counter
+always @(posedge clk)
+begin
+ if (~enable_timer_5usec) timer_5usec_count <= 0;
+ else if (~timer_5usec_done) timer_5usec_count <= timer_5usec_count + 1;
+end
+assign timer_5usec_done = (timer_5usec_count == TIMER_5USEC_VALUE_PP - 1);
+
+
+// Create the signals which indicate special scan codes received.
+// These are the "unlatched versions."
+assign released = (q[8:1] == `RELEASE_CODE) && rx_shifting_done && translate ;
+
+// Store the special scan code status bits
+// Not the final output, but an intermediate storage place,
+// until the entire set of output data can be assembled.
+always @(posedge clk)
+begin
+ if (reset || rx_output_event)
+ begin
+ hold_released <= 0;
+ end
+ else
+ begin
+ if (rx_shifting_done && released) hold_released <= 1;
+ end
+end
+
+// Output the special scan code flags, the scan code and the ascii
+always @(posedge clk)
+begin
+ if (reset)
+ begin
+ rx_released <= 0;
+ rx_scan_code <= 0;
+ end
+ else if (rx_output_strobe)
+ begin
+ rx_released <= hold_released;
+ rx_scan_code <= 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_2/rtl/verilog/ps2_keyboard.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: tags/rel_2/rtl/verilog/ps2_translation_table.v
===================================================================
--- tags/rel_2/rtl/verilog/ps2_translation_table.v (nonexistent)
+++ tags/rel_2/rtl/verilog/ps2_translation_table.v (revision 16)
@@ -0,0 +1,242 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// 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.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_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
+ integer i ;
+ reg [255:0] temp_init_val ;
+ initial
+ begin
+ 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_2/rtl/verilog/ps2_mouse.v
===================================================================
--- tags/rel_2/rtl/verilog/ps2_mouse.v (nonexistent)
+++ tags/rel_2/rtl/verilog/ps2_mouse.v (revision 16)
@@ -0,0 +1,495 @@
+//-------------------------------------------------------------------------------------
+//
+// 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
+ );
+
+// 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;
+
+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;
+
+ // 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.
+
+//--------------------------------------------------------------------------
+// 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_s <= ps2_clk_i;
+ ps2_data_s <= ps2_data_i;
+end
+
+// State register
+always @(posedge clk)
+begin : m1_state_register
+ if (reset) m1_state <= m1_rx_clk_h;
+ else m1_state <= m1_next_state;
+end
+
+// State transition logic
+always @(m1_state
+ or q
+ or tx_shifting_done
+ or tx_write
+ or ps2_clk_s
+ or ps2_data_s
+ or timer_60usec_done
+ or timer_5usec_done
+ )
+begin : m1_state_logic
+
+ // Output signals default to this value, unless changed in a state condition.
+ ps2_clk_hi_z <= 1;
+ ps2_data_hi_z <= 1;
+ tx_error_no_ack <= 0;
+ enable_timer_60usec <= 0;
+ enable_timer_5usec <= 0;
+
+ case (m1_state)
+
+ m1_rx_clk_h :
+ begin
+ enable_timer_60usec <= 1;
+ if (tx_write) m1_next_state <= m1_tx_reset_timer;
+ else if (~ps2_clk_s) m1_next_state <= m1_rx_falling_edge_marker;
+ else m1_next_state <= m1_rx_clk_h;
+ end
+
+ m1_rx_falling_edge_marker :
+ begin
+ enable_timer_60usec <= 0;
+ m1_next_state <= m1_rx_clk_l;
+ end
+
+ m1_rx_rising_edge_marker :
+ begin
+ enable_timer_60usec <= 0;
+ m1_next_state <= m1_rx_clk_h;
+ end
+
+
+ m1_rx_clk_l :
+ begin
+ enable_timer_60usec <= 1;
+ if (tx_write) m1_next_state <= m1_tx_reset_timer;
+ else if (ps2_clk_s) m1_next_state <= m1_rx_rising_edge_marker;
+ else m1_next_state <= m1_rx_clk_l;
+ end
+
+ m1_tx_reset_timer:
+ begin
+ enable_timer_60usec <= 0;
+ m1_next_state <= m1_tx_force_clk_l;
+ end
+
+ m1_tx_force_clk_l :
+ begin
+ enable_timer_60usec <= 1;
+ ps2_clk_hi_z <= 0; // Force the ps2_clk line low.
+ if (timer_60usec_done) m1_next_state <= m1_tx_first_wait_clk_h;
+ else m1_next_state <= m1_tx_force_clk_l;
+ end
+
+ m1_tx_first_wait_clk_h :
+ begin
+ enable_timer_5usec <= 1;
+ ps2_data_hi_z <= 0; // Start bit.
+ if (~ps2_clk_s && timer_5usec_done)
+ m1_next_state <= m1_tx_clk_l;
+ else
+ m1_next_state <= m1_tx_first_wait_clk_h;
+ end
+
+ // This state must be included because the device might possibly
+ // delay for up to 10 milliseconds before beginning its clock pulses.
+ // During that waiting time, we cannot drive the data (q[0]) because it
+ // is possibly 1, which would cause the keyboard to abort its receive
+ // and the expected clocks would then never be generated.
+ m1_tx_first_wait_clk_l :
+ begin
+ ps2_data_hi_z <= 0;
+ if (~ps2_clk_s) m1_next_state <= m1_tx_clk_l;
+ else m1_next_state <= m1_tx_first_wait_clk_l;
+ end
+
+ m1_tx_wait_clk_h :
+ begin
+ enable_timer_5usec <= 1;
+ ps2_data_hi_z <= q[0];
+ if (ps2_clk_s && timer_5usec_done)
+ m1_next_state <= m1_tx_rising_edge_marker;
+ else
+ m1_next_state <= m1_tx_wait_clk_h;
+ end
+
+ m1_tx_rising_edge_marker :
+ begin
+ ps2_data_hi_z <= q[0];
+ m1_next_state <= m1_tx_clk_h;
+ end
+
+ m1_tx_clk_h :
+ begin
+ ps2_data_hi_z <= q[0];
+ if (tx_shifting_done) m1_next_state <= m1_tx_wait_ack;
+ else if (~ps2_clk_s) m1_next_state <= m1_tx_clk_l;
+ else m1_next_state <= m1_tx_clk_h;
+ end
+
+ m1_tx_clk_l :
+ begin
+ ps2_data_hi_z <= q[0];
+ if (ps2_clk_s) m1_next_state <= m1_tx_wait_clk_h;
+ else m1_next_state <= m1_tx_clk_l;
+ end
+
+ m1_tx_wait_ack :
+ begin
+ if (~ps2_clk_s && ps2_data_s)
+ m1_next_state <= m1_tx_error_no_ack;
+ else if (~ps2_clk_s && ~ps2_data_s)
+ m1_next_state <= m1_tx_done_recovery;
+ else m1_next_state <= m1_tx_wait_ack;
+ end
+
+ m1_tx_done_recovery :
+ begin
+ if (ps2_clk_s && ps2_data_s) m1_next_state <= m1_rx_clk_h;
+ else m1_next_state <= m1_tx_done_recovery;
+ end
+
+ m1_tx_error_no_ack :
+ begin
+ tx_error_no_ack <= 1;
+ if (ps2_clk_s && ps2_data_s) m1_next_state <= m1_rx_clk_h;
+ else m1_next_state <= m1_tx_error_no_ack;
+ end
+
+ default : m1_next_state <= m1_rx_clk_h;
+ endcase
+end
+
+// State register
+always @(posedge clk)
+begin : m2_state_register
+ if (reset) m2_state <= m2_rx_data_ready_ack;
+ else m2_state <= m2_next_state;
+end
+
+// State transition logic
+always @(m2_state or rx_output_strobe or rx_read)
+begin : m2_state_logic
+ case (m2_state)
+ m2_rx_data_ready_ack:
+ begin
+ rx_data_ready <= 1'b0;
+ if (rx_output_strobe) m2_next_state <= m2_rx_data_ready;
+ else m2_next_state <= m2_rx_data_ready_ack;
+ end
+ m2_rx_data_ready:
+ begin
+ rx_data_ready <= 1'b1;
+ if (rx_read) m2_next_state <= m2_rx_data_ready_ack;
+ else m2_next_state <= m2_rx_data_ready;
+ end
+ default : m2_next_state <= m2_rx_data_ready_ack;
+ endcase
+end
+
+// This is the bit counter
+always @(posedge clk)
+begin
+ if ( reset
+ || rx_shifting_done
+ || (m1_state == m1_tx_wait_ack) // After tx is done.
+ ) bit_count <= 0; // normal reset
+ else if (timer_60usec_done
+ && (m1_state == m1_rx_clk_h)
+ && (ps2_clk_s)
+ ) bit_count <= 0; // rx watchdog timer reset
+ else if ( (m1_state == m1_rx_falling_edge_marker) // increment for rx
+ ||(m1_state == m1_tx_rising_edge_marker) // increment for tx
+ )
+ bit_count <= bit_count + 1;
+end
+// This signal is high for one clock at the end of the timer count.
+assign rx_shifting_done = (bit_count == `TOTAL_BITS);
+assign tx_shifting_done = (bit_count == `TOTAL_BITS-1);
+
+// This is the signal which enables loading of the shift register.
+// It also indicates "ack" to the device writing to the transmitter.
+assign tx_write_ack_o = ( (tx_write && (m1_state == m1_rx_clk_h))
+ ||(tx_write && (m1_state == m1_rx_clk_l))
+ );
+
+// This is the ODD parity bit for the transmitted word.
+assign tx_parity_bit = ~^tx_data;
+
+// This is the shift register
+always @(posedge clk)
+begin
+ if (reset) q <= 0;
+ else if (tx_write_ack_o) q <= {1'b1,tx_parity_bit,tx_data,1'b0};
+ else if ( (m1_state == m1_rx_falling_edge_marker)
+ ||(m1_state == m1_tx_rising_edge_marker) )
+ q <= {ps2_data_s,q[`TOTAL_BITS-1:1]};
+end
+
+// This is the 60usec timer counter
+always @(posedge clk)
+begin
+ if (~enable_timer_60usec) timer_60usec_count <= 0;
+ else if (~timer_60usec_done) timer_60usec_count <= timer_60usec_count + 1;
+end
+assign timer_60usec_done = (timer_60usec_count == (TIMER_60USEC_VALUE_PP - 1));
+
+// This is the 5usec timer counter
+always @(posedge clk)
+begin
+ if (~enable_timer_5usec) timer_5usec_count <= 0;
+ else if (~timer_5usec_done) timer_5usec_count <= timer_5usec_count + 1;
+end
+assign timer_5usec_done = (timer_5usec_count == TIMER_5USEC_VALUE_PP - 1);
+
+always @(posedge clk)
+begin
+ if (reset)
+ begin
+ rx_scan_code <= 0;
+ end
+ else if (rx_output_strobe)
+ begin
+ rx_scan_code <= 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
\ No newline at end of file
tags/rel_2/rtl/verilog/ps2_mouse.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: tags/rel_2/rtl/verilog/timescale.v
===================================================================
--- tags/rel_2/rtl/verilog/timescale.v (nonexistent)
+++ tags/rel_2/rtl/verilog/timescale.v (revision 16)
@@ -0,0 +1 @@
+`timescale 1ns/1ps
\ No newline at end of file
Index: tags/rel_2/sim/rtl_sim/run/run_ps2_sim.scr
===================================================================
--- tags/rel_2/sim/rtl_sim/run/run_ps2_sim.scr (nonexistent)
+++ tags/rel_2/sim/rtl_sim/run/run_ps2_sim.scr (revision 16)
@@ -0,0 +1,137 @@
+#!/bin/csh -f
+
+#//////////////////////////////////////////////////////////////////////
+#//// ////
+#//// run_ps2_sim.scr ////
+#//// ////
+#//// 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/02/20 15:20:11 mihad
+#// Little/big endian changes incorporated
+#//
+#// Revision 1.1.1.1 2002/02/18 16:16:55 mihad
+#// Initial project import - working
+#//
+#//
+
+echo "-MESSAGES" > ./ncvlog.args
+echo "-NOCOPYRIGHT" >> ./ncvlog.args
+echo "-CDSLIB ../bin/cds.lib" >> ./ncvlog.args
+echo "-HDLVAR ../bin/hdl.var" >> ./ncvlog.args
+echo "-INCDIR ../../../bench/verilog" >> ./ncvlog.args
+echo "-INCDIR ../../../rtl/verilog" >> ./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
+
+set current_par = 0
+set output_waveform = 0
+set xilinx = 0
+while ( $current_par < $# )
+ @ current_par = $current_par + 1
+ switch ( $argv[$current_par] )
+ case xilinx:
+ echo '-DEFINE "XILINX"' >> ./ncvlog.args
+ @ xilinx = 1
+ breaksw
+ case wave:
+ @ output_waveform = 1
+ breaksw
+ default:
+ echo 'Unknown option "'$argv[$current_par]'"!'
+ exit
+ breaksw
+ endsw
+end
+
+echo "-LOGFILE ../log/ncvlog.log" >> ./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
+
+if ( $xilinx ) then
+ foreach filename ( `cat ../bin/xilinx_file_list` )
+ echo "../../../../xilinx_blocks/"$filename >> ./ncvlog.args
+ end
+endif
+
+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 "-SNAPSHOT worklib.ps2_test_bench:rtl" >> ./ncelab.args
+echo "-ACCESS +RWC" >> ./ncelab.args
+echo "worklib.ps2_test_bench" >> ./ncelab.args
+
+if ( $xilinx ) then
+ echo "worklib.glbl" >> ./ncelab.args
+endif
+
+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 -f ./ncsim.args
tags/rel_2/sim/rtl_sim/run/run_ps2_sim.scr
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: tags/rel_2/sim/rtl_sim/bin/rtl_file_list
===================================================================
--- tags/rel_2/sim/rtl_sim/bin/rtl_file_list (nonexistent)
+++ tags/rel_2/sim/rtl_sim/bin/rtl_file_list (revision 16)
@@ -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
Index: tags/rel_2/sim/rtl_sim/bin/sim_file_list
===================================================================
--- tags/rel_2/sim/rtl_sim/bin/sim_file_list (nonexistent)
+++ tags/rel_2/sim/rtl_sim/bin/sim_file_list (revision 16)
@@ -0,0 +1,5 @@
+ps2_keyboard_model.v
+ps2_test_bench.v
+wb_master32.v
+wb_master_behavioral.v
+ps2_sim_top.v
Index: tags/rel_2/sim/rtl_sim/bin/xilinx_file_list
===================================================================
--- tags/rel_2/sim/rtl_sim/bin/xilinx_file_list (nonexistent)
+++ tags/rel_2/sim/rtl_sim/bin/xilinx_file_list (revision 16)
@@ -0,0 +1,2 @@
+RAMB4_S8.v
+glbl.v
Index: tags/rel_2/sim/rtl_sim/bin/cds.lib
===================================================================
--- tags/rel_2/sim/rtl_sim/bin/cds.lib (nonexistent)
+++ tags/rel_2/sim/rtl_sim/bin/cds.lib (revision 16)
@@ -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
Index: tags/rel_2/sim/rtl_sim/bin/hdl.var
===================================================================
--- tags/rel_2/sim/rtl_sim/bin/hdl.var (nonexistent)
+++ tags/rel_2/sim/rtl_sim/bin/hdl.var (revision 16)
@@ -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)
Index: tags/rel_2/syn/xilinx/constraints/ps2.ucf
===================================================================
--- tags/rel_2/syn/xilinx/constraints/ps2.ucf (nonexistent)
+++ tags/rel_2/syn/xilinx/constraints/ps2.ucf (revision 16)
@@ -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_2/syn/xilinx/constraints/ps2.ucf
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: tags/rel_2/syn/xilinx/constraints/ps2.sdc
===================================================================
--- tags/rel_2/syn/xilinx/constraints/ps2.sdc (nonexistent)
+++ tags/rel_2/syn/xilinx/constraints/ps2.sdc (revision 16)
@@ -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_2/syn/xilinx/constraints/ps2.sdc
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: tags/rel_2/misc/scancode_translation_values
===================================================================
--- tags/rel_2/misc/scancode_translation_values (nonexistent)
+++ tags/rel_2/misc/scancode_translation_values (revision 16)
@@ -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_2/misc/scancode_translation_values
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property