From bc293896b6803b86d5337bebf738fbcbd7ce6510 Mon Sep 17 00:00:00 2001 From: Alan Garfield Date: Thu, 12 Apr 2018 22:33:39 +1000 Subject: [PATCH] added prelim ukp USB keyboard support --- boards/ice40hx8k-b-evn/ice40hx8k.pcf | 4 + boards/ice40hx8k-b-evn/yosys/Makefile | 4 + rtl/apple1.v | 23 + rtl/boards/ice40hx8k-b-evn/apple1_hx8k.v | 7 + rtl/ukp/keymap.v | 154 ++++++ rtl/ukp/ukp.s | 599 +++++++++++++++++++++ rtl/ukp/ukp.v | 265 ++++++++++ rtl/ukp/ukpram.v | 77 +++ rtl/ukp/ukprom.v | 641 +++++++++++++++++++++++ tools/iverilog/run_ukp_tb.sh | 2 + tools/iverilog/ukp_files.txt | 4 + tools/iverilog/ukp_tb.v | 104 ++++ 12 files changed, 1884 insertions(+) create mode 100644 rtl/ukp/keymap.v create mode 100644 rtl/ukp/ukp.s create mode 100644 rtl/ukp/ukp.v create mode 100644 rtl/ukp/ukpram.v create mode 100644 rtl/ukp/ukprom.v create mode 100755 tools/iverilog/run_ukp_tb.sh create mode 100644 tools/iverilog/ukp_files.txt create mode 100644 tools/iverilog/ukp_tb.v diff --git a/boards/ice40hx8k-b-evn/ice40hx8k.pcf b/boards/ice40hx8k-b-evn/ice40hx8k.pcf index 6734d0a..20a5548 100644 --- a/boards/ice40hx8k-b-evn/ice40hx8k.pcf +++ b/boards/ice40hx8k-b-evn/ice40hx8k.pcf @@ -23,6 +23,10 @@ set_io led[0] C3 set_io ps2_clk N3 set_io ps2_din N2 +### USB Keyboard +set_io usb_dp P15 +set_io usb_dm R15 + ### VGA Display set_io vga_h_sync C2 set_io vga_v_sync D1 diff --git a/boards/ice40hx8k-b-evn/yosys/Makefile b/boards/ice40hx8k-b-evn/yosys/Makefile index 8556722..fcce260 100644 --- a/boards/ice40hx8k-b-evn/yosys/Makefile +++ b/boards/ice40hx8k-b-evn/yosys/Makefile @@ -65,6 +65,10 @@ $(BUILDDIR)/apple1.blif: $(SOURCEDIR)/apple1.v \ $(SOURCEDIR)/vga/font_rom.v \ $(SOURCEDIR)/ps2keyboard/debounce.v \ $(SOURCEDIR)/ps2keyboard/ps2keyboard.v \ + $(SOURCEDIR)/ukp/ukp.v \ + $(SOURCEDIR)/ukp/ukpram.v \ + $(SOURCEDIR)/ukp/ukprom.v \ + $(SOURCEDIR)/ukp/keymap.v \ $(SOURCEDIR)/boards/ice40hx8k-b-evn/apple1_hx8k.v \ $(BUILDDIR)/pll.sv diff --git a/rtl/apple1.v b/rtl/apple1.v index 9800030..9c53844 100644 --- a/rtl/apple1.v +++ b/rtl/apple1.v @@ -30,6 +30,7 @@ module apple1 #( parameter WOZMON_ROM_FILENAME = "../../../roms/wozmon.hex" ) ( input clk25, // 25 MHz master clock + input clkusb, // 12 MHz usb clock input rst_n, // active low synchronous reset (needed for simulation) // I/O interface to computer @@ -42,6 +43,10 @@ module apple1 #( input ps2_din, // PS/2 keyboard serial data input input ps2_select, // Input to select the PS/2 keyboard instead of the UART + // I/O interface to USB keyboard + inout usb_dm, // USB keyboard minus pin + inout usb_dp, // USB keyboard plus pin + // Outputs to VGA display output vga_h_sync, // hozizontal VGA sync pulse output vga_v_sync, // vertical VGA sync pulse @@ -104,6 +109,9 @@ module apple1 #( wire ram_cs = (ab[15:13] == 3'b000); // 0x0000 -> 0x1FFF + // ukp + wire ukp_cs = (ab[15:12] == 4'b1011); // 0xB000 -> 0xBFFF + // font mode, background and foreground colour wire vga_mode_cs = (ab[15:2] == 14'b11000000000000); // 0xC000 -> 0xC003 @@ -226,6 +234,20 @@ module apple1 #( .clr_screen(vga_cls) ); + // USB keyboard interface + wire [7:0] ukp_dout; + wire usb_int; + ukp my_ukp( + .clk25(clk25), + .clkusb(clkusb), + .rst(rst), + .usb_dm(usb_dm), + .usb_dp(usb_dp), + .record_n(usb_int), + .kbd_adr(ab[3:0]), + .kbd_data(ukp_dout) + ); + // Handle font mode and foreground and background // colours. This so isn't Apple One authentic, but // it can't hurt to have some fun. :D @@ -274,5 +296,6 @@ module apple1 #( uart_cs ? uart_dout : ps2kb_cs ? ps2_dout : vga_mode_cs ? vga_mode_dout : + ukp_cs ? ukp_dout : 8'hFF; endmodule diff --git a/rtl/boards/ice40hx8k-b-evn/apple1_hx8k.v b/rtl/boards/ice40hx8k-b-evn/apple1_hx8k.v index e6d00e9..8791a29 100644 --- a/rtl/boards/ice40hx8k-b-evn/apple1_hx8k.v +++ b/rtl/boards/ice40hx8k-b-evn/apple1_hx8k.v @@ -40,6 +40,10 @@ module apple1_top #( input ps2_clk, // PS/2 keyboard serial clock input input ps2_din, // PS/2 keyboard serial data input + // I/O interface to USB keyboard + inout usb_dm, // USB keyboard minus pin + inout usb_dp, // USB keyboard plus pin + // Outputs to VGA display output vga_h_sync, // hozizontal VGA sync pulse output vga_v_sync, // vertical VGA sync pulse @@ -138,6 +142,7 @@ module apple1_top #( .WOZMON_ROM_FILENAME (WOZMON_ROM_FILENAME) ) my_apple1( .clk25(clk25), + .clkusb(clk), .rst_n(reset_n), .uart_rx(uart_rx), .uart_tx(uart_tx), @@ -145,6 +150,8 @@ module apple1_top #( .ps2_clk(ps2__clk), .ps2_din(ps2__din), .ps2_select(ps2_select), + .usb_dm(usb_dm), + .usb_dp(usb_dp), .vga_h_sync(vga_h_sync), .vga_v_sync(vga_v_sync), .vga_red(vga_red), diff --git a/rtl/ukp/keymap.v b/rtl/ukp/keymap.v new file mode 100644 index 0000000..4bb1116 --- /dev/null +++ b/rtl/ukp/keymap.v @@ -0,0 +1,154 @@ +module keymap( + clk, + adr, + data +); + input clk; + input [7:0] adr; + output [7:0] data; + + reg [7:0] data; + + always @(posedge clk) + begin + case (adr) + 8'h00: data <= 8'b00000000; + 8'h01: data <= 8'b00000000; + 8'h02: data <= 8'b00000000; + 8'h03: data <= 8'b00000000; + 8'h04: data <= 8'b10010001; + 8'h05: data <= 8'b10010010; + 8'h06: data <= 8'b10010011; + 8'h07: data <= 8'b10010100; + 8'h08: data <= 8'b10010101; + 8'h09: data <= 8'b10010110; + 8'h0a: data <= 8'b10010111; + 8'h0b: data <= 8'b10011000; + 8'h0c: data <= 8'b10011001; + 8'h0d: data <= 8'b10011010; + 8'h0e: data <= 8'b10011011; + 8'h0f: data <= 8'b10011100; + 8'h10: data <= 8'b10011101; + 8'h11: data <= 8'b10011110; + 8'h12: data <= 8'b10011111; + 8'h13: data <= 8'b10100000; + 8'h14: data <= 8'b10100001; + 8'h15: data <= 8'b10100010; + 8'h16: data <= 8'b10100011; + 8'h17: data <= 8'b10100100; + 8'h18: data <= 8'b10100101; + 8'h19: data <= 8'b10100110; + 8'h1a: data <= 8'b10100111; + 8'h1b: data <= 8'b10101000; + 8'h1c: data <= 8'b10101001; + 8'h1d: data <= 8'b10101010; + 8'h1e: data <= 8'b10110001; + 8'h1f: data <= 8'b10110010; + 8'h20: data <= 8'b10110011; + 8'h21: data <= 8'b10110100; + 8'h22: data <= 8'b10110101; + 8'h23: data <= 8'b10110110; + 8'h24: data <= 8'b10110111; + 8'h25: data <= 8'b10111000; + 8'h26: data <= 8'b10111001; + 8'h27: data <= 8'b10110000; + 8'h28: data <= 8'b10001111; + 8'h29: data <= 8'b11001111; + 8'h2a: data <= 8'b11000011; + 8'h2b: data <= 8'b00000000; + 8'h2c: data <= 8'b11001110; + 8'h2d: data <= 8'b10101111; + 8'h2e: data <= 8'b10101110; + 8'h2f: data <= 8'b10010000; + 8'h30: data <= 8'b10101011; + 8'h31: data <= 8'b10101100; + 8'h32: data <= 8'b00000000; + 8'h33: data <= 8'b10111011; + 8'h34: data <= 8'b10111010; + 8'h35: data <= 8'b00000000; + 8'h36: data <= 8'b10111100; + 8'h37: data <= 8'b10111101; + 8'h38: data <= 8'b10111110; + 8'h39: data <= 8'b00000001; + 8'h3a: data <= 8'b11001001; + 8'h3b: data <= 8'b11001010; + 8'h3c: data <= 8'b11001011; + 8'h3d: data <= 8'b11001100; + 8'h3e: data <= 8'b11001101; + 8'h3f: data <= 8'b00000000; + 8'h40: data <= 8'b00000000; + 8'h41: data <= 8'b00000000; + 8'h42: data <= 8'b00000000; + 8'h43: data <= 8'b00000000; + 8'h44: data <= 8'b00000000; + 8'h45: data <= 8'b11001000; + 8'h46: data <= 8'b00000000; + 8'h47: data <= 8'b00000000; + 8'h48: data <= 8'b00000000; + 8'h49: data <= 8'b00000000; + 8'h4a: data <= 8'b00000000; + 8'h4b: data <= 8'b00000000; + 8'h4c: data <= 8'b00000000; + 8'h4d: data <= 8'b00000000; + 8'h4e: data <= 8'b00000000; + 8'h4f: data <= 8'b11000010; + 8'h50: data <= 8'b00000000; + 8'h51: data <= 8'b00000000; + 8'h52: data <= 8'b11000001; + 8'h53: data <= 8'b11000000; + 8'h54: data <= 8'b00000000; + 8'h55: data <= 8'b10001010; + 8'h56: data <= 8'b00000000; + 8'h57: data <= 8'b10001011; + 8'h58: data <= 8'b10001111; + 8'h59: data <= 8'b10000001; + 8'h5a: data <= 8'b10000010; + 8'h5b: data <= 8'b10000011; + 8'h5c: data <= 8'b10000100; + 8'h5d: data <= 8'b10000101; + 8'h5e: data <= 8'b10000110; + 8'h5f: data <= 8'b10000111; + 8'h60: data <= 8'b10001000; + 8'h61: data <= 8'b10001001; + 8'h62: data <= 8'b10000000; + 8'h63: data <= 8'b10001110; + 8'h64: data <= 8'b00000000; + 8'h65: data <= 8'b00000000; + 8'h66: data <= 8'b00000000; + 8'h67: data <= 8'b10001100; + 8'h68: data <= 8'b00000000; + 8'h69: data <= 8'b00000000; + 8'h6a: data <= 8'b00000000; + 8'h6b: data <= 8'b00000000; + 8'h6c: data <= 8'b00000000; + 8'h6d: data <= 8'b00000000; + 8'h6e: data <= 8'b00000000; + 8'h6f: data <= 8'b00000000; + 8'h70: data <= 8'b00000000; + 8'h71: data <= 8'b00000000; + 8'h72: data <= 8'b00000000; + 8'h73: data <= 8'b00000000; + 8'h74: data <= 8'b00000000; + 8'h75: data <= 8'b00000000; + 8'h76: data <= 8'b00000000; + 8'h77: data <= 8'b00000000; + 8'h78: data <= 8'b00000000; + 8'h79: data <= 8'b00000000; + 8'h7a: data <= 8'b00000000; + 8'h7b: data <= 8'b00000000; + 8'h7c: data <= 8'b00000000; + 8'h7d: data <= 8'b00000000; + 8'h7e: data <= 8'b00000000; + 8'h7f: data <= 8'b00000000; + 8'h80: data <= 8'b00000000; + 8'h81: data <= 8'b00000000; + 8'h9b: data <= 8'b11111111; + 8'h9d: data <= 8'b11111000; + 8'hda: data <= 8'b11111110; + 8'hdc: data <= 8'b11111011; + 8'hde: data <= 8'b11111101; + 8'he0: data <= 8'b11111100; + default: data <= 8'bXXXXXXXX; + endcase + end +endmodule diff --git a/rtl/ukp/ukp.s b/rtl/ukp/ukp.s new file mode 100644 index 0000000..499b8e1 --- /dev/null +++ b/rtl/ukp/ukp.s @@ -0,0 +1,599 @@ +; USB keyboard interface for UKP + +label0: + ldi 9 ; inturrupt transfer interval (10-1mS) +label1: + wait + bc label11 + bz label0 + + ; wait 200mS after device attached + + ldi 200 +label2: + wait + djnz label2 + + ; USB bus reset + + out0 + ldi 10 +label3: + wait + djnz label3 + hiz + + ; 40mS wait + + ldi 40 +label4: + wait + out0 + out0 + out2 + out2 + hiz + djnz label4 + + wait + + ; send set address 1 + + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out1 + out1 + out2 + out2 + out2 + out1 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out1 + out2 + out1 + out2 + out0 + out0 + out2 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out1 + out1 + out1 + out2 + out1 + out2 + out1 + out1 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out1 + out2 + out2 + out1 + out2 + out1 + out2 + out1 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out2 + out2 + out1 + out1 + out2 + out2 + out2 + out2 + out2 + out1 + out1 + out2 + out1 + out1 + out2 + out1 + out0 + out0 + out2 + out2 + hiz + + ; recieve + + ldi 64 + start + in +label5: + ldi 8 +label6: + bz label5 + djnz label6 + + ; send IN(0,0) +label7: + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out1 + out1 + out2 + out1 + out1 + out2 + out2 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out1 + out2 + out1 + out2 + out0 + out0 + out2 + out2 + hiz + + ; recieve + + ldi 64 + start + in +label8: + ldi 8 +label9: + bz label8 + djnz label9 + bnak label7 + + ; send ACK + + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out1 + out2 + out2 + out1 + out2 + out2 + out1 + out1 + out1 + out0 + out0 + out2 + out2 + hiz + + ; wait 1mS + + wait + + ; send set configuration 1 + + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out1 + out1 + out2 + out2 + out2 + out1 + out1 + out2 + out1 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out1 + out2 + out2 + out2 + out2 + out0 + out0 + out2 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out1 + out1 + out1 + out2 + out1 + out2 + out1 + out1 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out1 + out2 + out1 + out1 + out2 + out1 + out2 + out1 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out2 + out2 + out2 + out1 + out2 + out2 + out1 + out2 + out2 + out1 + out1 + out2 + out1 + out1 + out2 + out1 + out0 + out0 + out2 + out2 + hiz + + ; recieve + + ldi 64 + start + in +label18: + ldi 8 +label19: + bz label18 + djnz label19 + + ; send IN(1,0) +label10: + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out1 + out1 + out2 + out1 + out1 + out2 + out2 + out2 + out1 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out1 + out2 + out2 + out2 + out2 + out0 + out0 + out2 + out2 + hiz + + ; recieve + + ldi 64 + start + in +label28: + ldi 8 +label29: + bz label28 + djnz label29 + bnak label10 + + ; send ACK + + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out1 + out2 + out2 + out1 + out2 + out2 + out1 + out1 + out1 + out0 + out0 + out2 + out2 + hiz + + toggle + ldi 0 + djnz label0 + + ; when connected + +label11: + bz label12 + + out0 + out0 + out2 + out2 + hiz + djnz label1 + + wait + + ; IN(1,1) (interrupt transfer) + + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out1 + out1 + out2 + out1 + out1 + out2 + out2 + out2 + out1 + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out1 + out2 + out1 + out2 + out2 + out2 + out1 + out1 + out2 + out0 + out0 + out2 + out2 + hiz + + ; recieve + + ldi 64 + start + in +label38: + ldi 8 +label39: + bz label38 + djnz label39 + bnak label0 + + ; send ACK + + out1 + out2 + out1 + out2 + out1 + out2 + out1 + out1 + out2 + out2 + out1 + out2 + out2 + out1 + out1 + out1 + out0 + out0 + out2 + out2 + hiz + + ldi 0 + djnz label0 + +label12: + toggle + ldi 0 + djnz label0 + diff --git a/rtl/ukp/ukp.v b/rtl/ukp/ukp.v new file mode 100644 index 0000000..7b39cec --- /dev/null +++ b/rtl/ukp/ukp.v @@ -0,0 +1,265 @@ +module ukp( + clk25, + clkusb, + rst, + usb_dm, + usb_dp, + record_n, + kbd_adr, + kbd_data +); + input clk25; + input clkusb; + input rst; + output record_n; + inout usb_dm; + inout usb_dp; + input [3:0] kbd_adr; + output [7:0] kbd_data; + + parameter S_OPCODE = 0; + parameter S_LDI0 = 1; + parameter S_LDI1 = 2; + parameter S_B0 = 3; + parameter S_B1 = 4; + + parameter LDI = 4'b0001; + parameter START = 4'b0010; + + parameter OUT0 = 4'b0100; + parameter OUT1 = 4'b0101; + parameter OUT2 = 4'b0110; + parameter HZ = 4'b0111; + + parameter BZ = 4'b1000; + parameter BC = 4'b1001; + parameter BNAK = 4'b1010; + parameter DJNZ = 4'b1011; + + parameter TOGGLE = 4'b1100; + parameter IN = 4'b1101; + parameter WAIT = 4'b1110; + + function sel4; + input [1:0] sel; + input [3:0] a; + case (sel) + 2'b00: sel4 = a[3]; + 2'b01: sel4 = a[2]; + 2'b10: sel4 = a[1]; + 2'b11: sel4 = a[0]; + endcase + endfunction + + function [3:0] decode4; + input [1:0] sel; + input g; + if (g) + case (sel) + 2'b00: decode4 = 4'b0001; + 2'b01: decode4 = 4'b0010; + 2'b10: decode4 = 4'b0100; + 2'b11: decode4 = 4'b1000; + endcase + else decode4 = 4'b0000; + endfunction + + wire [3:0] inst; + wire sample; + reg connected = 0; + reg inst_ready = 0; + reg g = 0; + reg p = 0; + reg m = 0; + reg cond = 0; + reg nak = 0; + reg dm1 = 0; + reg bank = 0; + reg record1 = 0; + reg [2:0] state = 0; + reg [7:0] w = 0; + reg [9:0] pc = 0; + reg [2:0] timing = 0; + reg [3:0] tmp = 0; + reg [13:0] interval = 0; + reg [5:0] bitadr = 0; + reg [7:0] data = 0; + + ukprom ukprom( + .clk(clkusb), + .adr(pc), + .data(inst) + ); + + wire interval_cy = interval == 12001; + wire next = ~(state == S_OPCODE & ( + ~inst[3] & inst[2] & timing != 0 | + ~inst[3] & ~inst[2] & inst[1] & usb_dm | + inst == 4'b1110 & ~interval_cy | + inst == 4'b1101 & (~sample | (usb_dp | usb_dm) & w != 1) + )); + wire branch = state == S_B1 & cond; + wire record; + wire [7:0] map; + wire [3:0] keydata; + + always @(posedge clkusb or posedge rst) + begin + if (rst) + begin + connected <= 0; + inst_ready <= 0; + g <= 0; + p <= 0; + m <= 0; + cond <= 0; + nak <= 0; + dm1 <= 0; + bank <= 0; + record1 <= 0; + state <= 3'd0; + w <= 8'd0; + pc <= 10'd0; + timing <= 3'd0; + tmp <= 4'd0; + interval <= 14'd0; + bitadr <= 6'd0; + data <= 8'd0; + end + else + begin + if (inst_ready) + begin + if (state == S_OPCODE) + begin + if (inst == 4'b0001) state <= S_LDI0; + if (inst == 4'b1100) connected <= ~connected; + if (~inst[3] & inst[2] & timing == 0) + begin + g <= ~inst[1] | ~inst[0]; + p <= ~inst[1] & inst[0]; + m <= inst[1] & ~inst[0]; + end + if (inst[3] & ~inst[2]) + begin + state <= S_B0; + cond <= sel4(inst[1:0], {~usb_dm, connected, nak, w != 1}); + end + if (inst == 4'b1011 | inst == 4'b1101 & sample) w <= w - 1; + end + + if (state == S_LDI0) + begin + w[3:0] <= inst; + state <= S_LDI1; + end + + if (state == S_LDI1) + begin + w[7:4] <= inst; + state <= S_OPCODE; + end + + if (state == S_B0) + begin + tmp <= inst; + state <= S_B1; + end + + if (state == S_B1) + begin + state <= S_OPCODE; + end + + if (next | branch) + begin + pc <= branch ? { inst, tmp, 2'b00 } : pc + 1; + inst_ready <= 0; + end + end + else + begin + inst_ready <= 1; + end + + if (inst_ready & state == S_OPCODE & inst == 4'b0010) + begin + timing <= 0; + bitadr <= 0; + nak <= 1; + end + else + begin + timing <= timing + 1; + end + + if (sample) + begin + if (bitadr == 8) nak <= usb_dm; + data[6:0] <= data[7:1]; + data[7] <= dm1 ~^ usb_dm; + dm1 <= usb_dm; + bitadr <= bitadr + 1; + end + + interval <= interval_cy ? 0 : interval + 1; + record1 <= record; + + if (~record & record1) + begin + bank <= ~bank; + end + end + end + + assign usb_dp = g ? p : 1'bZ; + assign usb_dm = g ? m : 1'bZ; + assign sample = inst_ready & state == S_OPCODE & inst == 4'b1101 & timing == 1; + assign record = connected & ~nak; + assign record_n = ~record; + + keymap keymap( + .clk(clkusb), + .adr({ ~timing[0], data[6:0] }), + .data(map) + ); + + wire mod = bitadr == 24; + assign keydata = mod ? { data[0] | data[4], data[1] | data[5], data[2] | data[6], data[3] | data[7] } : decode4(map[1:0], record1); + + wire [4:0] kbd_adr_in = record1 ? mod ? 5'b10001 : map[6:2] : interval[4:0]; + + ukpram my_ukpram( + .clk25(clk25), + .read_addr({~bank, kbd_adr}), + .r_en(1'b1), + .dout(kbd_data), + + .clkusb(clkusb), + .write_addr({bank, kbd_adr_in}), + .w_en( + (~record1 | (mod | bitadr == 40 | bitadr == 48) & (timing == 0 | timing == 1)) && + (~record1 | mod | map[7]) + ), + .din(keydata) + ); + + //RAMB4_S4_S8 keyboard( + //.WEA(~record1 | (mod | bitadr == 40 | bitadr == 48) & (timing == 0 | timing == 1)), + //.ENA(~record1 | mod | map[7]), + + //.RSTA(1'b0), + //.CLKA(clk12), + //.ADDRA({ 4'b0000, bank, kbd_adr_in }), + //.DIA(keydata), + + //.WEB(1'b0), + //.ENB(1'b1), + + //.RSTB(1'b0), + //.CLKB(clk12), + //.ADDRB({ 4'b0000, ~bank, kbd_adr}), + //.DIB(8'h00), + //.DOB(kbd_data) + //); +endmodule diff --git a/rtl/ukp/ukpram.v b/rtl/ukp/ukpram.v new file mode 100644 index 0000000..0651599 --- /dev/null +++ b/rtl/ukp/ukpram.v @@ -0,0 +1,77 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// +// Description: RAM for ukp +// +// Author.....: Alan Garfield +// Date.......: 11-4-2018 +// + +module ukpram #( + parameter UKPRAM_FILENAME = "../../../roms/ukp_ram.bin" +) ( + input clk25, // clock signal + input clkusb, // USB clock signal + input [4:0] read_addr, // read address bus + input [5:0] write_addr, // write address bus + input r_en, // active high read enable strobe + input w_en, // active high write enable strobe + input [3:0] din, // 4-bit data bus (input) + output reg [7:0] dout // 8-bit data bus (output) +); + + reg [3:0] ram_data[0:63]; + + //initial + // $readmemb(UKPRAM_FILENAME, ram_data, 0, 63); + + always @(posedge clkusb) + begin + if (w_en) ram_data[write_addr] <= din; + end + + always @(posedge clk25) + begin + if (r_en) dout <= { + ram_data[{read_addr, 1'b1}], + ram_data[{read_addr, 1'b0}] + }; + end + +endmodule + +// BANK A +// 0000 000001 +// 000000 +// 0001 000011 +// 000010 +// 0010 +// 0011 +// 0100 +// 0101 +// 0110 +// 0111 +// +// BANK B +// 1000 +// 1001 +// 1010 +// 1011 +// 1100 +// 1101 +// 1110 +// 1111 diff --git a/rtl/ukp/ukprom.v b/rtl/ukp/ukprom.v new file mode 100644 index 0000000..46f1701 --- /dev/null +++ b/rtl/ukp/ukprom.v @@ -0,0 +1,641 @@ +module ukprom( + clk, + adr, + data +); + input clk; + input [9:0] adr; + output [3:0] data; + + reg [3:0] data; + + always @(posedge clk) + begin + case (adr) + 10'h000: data <= 4'h1; + 10'h001: data <= 4'h9; + 10'h002: data <= 4'h0; + 10'h003: data <= 4'h0; + 10'h004: data <= 4'he; + 10'h005: data <= 4'h9; + 10'h006: data <= 4'h2; + 10'h007: data <= 4'h8; + 10'h008: data <= 4'h8; + 10'h009: data <= 4'h0; + 10'h00a: data <= 4'h0; + 10'h00b: data <= 4'h1; + 10'h00c: data <= 4'h8; + 10'h00d: data <= 4'hc; + 10'h00e: data <= 4'h0; + 10'h00f: data <= 4'h0; + 10'h010: data <= 4'he; + 10'h011: data <= 4'hb; + 10'h012: data <= 4'h4; + 10'h013: data <= 4'h0; + 10'h014: data <= 4'h4; + 10'h015: data <= 4'h1; + 10'h016: data <= 4'ha; + 10'h017: data <= 4'h0; + 10'h018: data <= 4'he; + 10'h019: data <= 4'hb; + 10'h01a: data <= 4'h6; + 10'h01b: data <= 4'h0; + 10'h01c: data <= 4'h7; + 10'h01d: data <= 4'h1; + 10'h01e: data <= 4'h8; + 10'h01f: data <= 4'h2; + 10'h020: data <= 4'he; + 10'h021: data <= 4'h4; + 10'h022: data <= 4'h4; + 10'h023: data <= 4'h6; + 10'h024: data <= 4'h6; + 10'h025: data <= 4'h7; + 10'h026: data <= 4'hb; + 10'h027: data <= 4'h8; + 10'h028: data <= 4'h0; + 10'h029: data <= 4'he; + 10'h02a: data <= 4'h5; + 10'h02b: data <= 4'h6; + 10'h02c: data <= 4'h5; + 10'h02d: data <= 4'h6; + 10'h02e: data <= 4'h5; + 10'h02f: data <= 4'h6; + 10'h030: data <= 4'h5; + 10'h031: data <= 4'h5; + 10'h032: data <= 4'h5; + 10'h033: data <= 4'h6; + 10'h034: data <= 4'h6; + 10'h035: data <= 4'h6; + 10'h036: data <= 4'h5; + 10'h037: data <= 4'h5; + 10'h038: data <= 4'h6; + 10'h039: data <= 4'h5; + 10'h03a: data <= 4'h6; + 10'h03b: data <= 4'h5; + 10'h03c: data <= 4'h6; + 10'h03d: data <= 4'h5; + 10'h03e: data <= 4'h6; + 10'h03f: data <= 4'h5; + 10'h040: data <= 4'h6; + 10'h041: data <= 4'h5; + 10'h042: data <= 4'h6; + 10'h043: data <= 4'h5; + 10'h044: data <= 4'h6; + 10'h045: data <= 4'h5; + 10'h046: data <= 4'h5; + 10'h047: data <= 4'h6; + 10'h048: data <= 4'h5; + 10'h049: data <= 4'h6; + 10'h04a: data <= 4'h4; + 10'h04b: data <= 4'h4; + 10'h04c: data <= 4'h6; + 10'h04d: data <= 4'h6; + 10'h04e: data <= 4'h5; + 10'h04f: data <= 4'h6; + 10'h050: data <= 4'h5; + 10'h051: data <= 4'h6; + 10'h052: data <= 4'h5; + 10'h053: data <= 4'h6; + 10'h054: data <= 4'h5; + 10'h055: data <= 4'h5; + 10'h056: data <= 4'h5; + 10'h057: data <= 4'h5; + 10'h058: data <= 4'h6; + 10'h059: data <= 4'h5; + 10'h05a: data <= 4'h6; + 10'h05b: data <= 4'h5; + 10'h05c: data <= 4'h5; + 10'h05d: data <= 4'h5; + 10'h05e: data <= 4'h6; + 10'h05f: data <= 4'h5; + 10'h060: data <= 4'h6; + 10'h061: data <= 4'h5; + 10'h062: data <= 4'h6; + 10'h063: data <= 4'h5; + 10'h064: data <= 4'h6; + 10'h065: data <= 4'h5; + 10'h066: data <= 4'h5; + 10'h067: data <= 4'h6; + 10'h068: data <= 4'h6; + 10'h069: data <= 4'h5; + 10'h06a: data <= 4'h6; + 10'h06b: data <= 4'h5; + 10'h06c: data <= 4'h6; + 10'h06d: data <= 4'h5; + 10'h06e: data <= 4'h5; + 10'h06f: data <= 4'h6; + 10'h070: data <= 4'h5; + 10'h071: data <= 4'h6; + 10'h072: data <= 4'h5; + 10'h073: data <= 4'h6; + 10'h074: data <= 4'h5; + 10'h075: data <= 4'h6; + 10'h076: data <= 4'h5; + 10'h077: data <= 4'h6; + 10'h078: data <= 4'h5; + 10'h079: data <= 4'h6; + 10'h07a: data <= 4'h5; + 10'h07b: data <= 4'h6; + 10'h07c: data <= 4'h5; + 10'h07d: data <= 4'h6; + 10'h07e: data <= 4'h5; + 10'h07f: data <= 4'h6; + 10'h080: data <= 4'h5; + 10'h081: data <= 4'h6; + 10'h082: data <= 4'h5; + 10'h083: data <= 4'h6; + 10'h084: data <= 4'h5; + 10'h085: data <= 4'h6; + 10'h086: data <= 4'h5; + 10'h087: data <= 4'h6; + 10'h088: data <= 4'h5; + 10'h089: data <= 4'h6; + 10'h08a: data <= 4'h5; + 10'h08b: data <= 4'h6; + 10'h08c: data <= 4'h5; + 10'h08d: data <= 4'h6; + 10'h08e: data <= 4'h5; + 10'h08f: data <= 4'h6; + 10'h090: data <= 4'h5; + 10'h091: data <= 4'h6; + 10'h092: data <= 4'h5; + 10'h093: data <= 4'h6; + 10'h094: data <= 4'h5; + 10'h095: data <= 4'h6; + 10'h096: data <= 4'h5; + 10'h097: data <= 4'h6; + 10'h098: data <= 4'h5; + 10'h099: data <= 4'h6; + 10'h09a: data <= 4'h5; + 10'h09b: data <= 4'h6; + 10'h09c: data <= 4'h5; + 10'h09d: data <= 4'h6; + 10'h09e: data <= 4'h6; + 10'h09f: data <= 4'h6; + 10'h0a0: data <= 4'h5; + 10'h0a1: data <= 4'h5; + 10'h0a2: data <= 4'h6; + 10'h0a3: data <= 4'h6; + 10'h0a4: data <= 4'h6; + 10'h0a5: data <= 4'h6; + 10'h0a6: data <= 4'h6; + 10'h0a7: data <= 4'h5; + 10'h0a8: data <= 4'h5; + 10'h0a9: data <= 4'h6; + 10'h0aa: data <= 4'h5; + 10'h0ab: data <= 4'h5; + 10'h0ac: data <= 4'h6; + 10'h0ad: data <= 4'h5; + 10'h0ae: data <= 4'h4; + 10'h0af: data <= 4'h4; + 10'h0b0: data <= 4'h6; + 10'h0b1: data <= 4'h6; + 10'h0b2: data <= 4'h7; + 10'h0b3: data <= 4'h1; + 10'h0b4: data <= 4'h0; + 10'h0b5: data <= 4'h4; + 10'h0b6: data <= 4'h2; + 10'h0b7: data <= 4'hd; + 10'h0b8: data <= 4'h1; + 10'h0b9: data <= 4'h8; + 10'h0ba: data <= 4'h0; + 10'h0bb: data <= 4'h0; + 10'h0bc: data <= 4'h8; + 10'h0bd: data <= 4'he; + 10'h0be: data <= 4'h2; + 10'h0bf: data <= 4'hb; + 10'h0c0: data <= 4'hf; + 10'h0c1: data <= 4'h2; + 10'h0c2: data <= 4'h0; + 10'h0c3: data <= 4'h0; + 10'h0c4: data <= 4'h5; + 10'h0c5: data <= 4'h6; + 10'h0c6: data <= 4'h5; + 10'h0c7: data <= 4'h6; + 10'h0c8: data <= 4'h5; + 10'h0c9: data <= 4'h6; + 10'h0ca: data <= 4'h5; + 10'h0cb: data <= 4'h5; + 10'h0cc: data <= 4'h5; + 10'h0cd: data <= 4'h6; + 10'h0ce: data <= 4'h5; + 10'h0cf: data <= 4'h5; + 10'h0d0: data <= 4'h6; + 10'h0d1: data <= 4'h6; + 10'h0d2: data <= 4'h6; + 10'h0d3: data <= 4'h5; + 10'h0d4: data <= 4'h6; + 10'h0d5: data <= 4'h5; + 10'h0d6: data <= 4'h6; + 10'h0d7: data <= 4'h5; + 10'h0d8: data <= 4'h6; + 10'h0d9: data <= 4'h5; + 10'h0da: data <= 4'h6; + 10'h0db: data <= 4'h5; + 10'h0dc: data <= 4'h6; + 10'h0dd: data <= 4'h5; + 10'h0de: data <= 4'h6; + 10'h0df: data <= 4'h5; + 10'h0e0: data <= 4'h5; + 10'h0e1: data <= 4'h6; + 10'h0e2: data <= 4'h5; + 10'h0e3: data <= 4'h6; + 10'h0e4: data <= 4'h4; + 10'h0e5: data <= 4'h4; + 10'h0e6: data <= 4'h6; + 10'h0e7: data <= 4'h6; + 10'h0e8: data <= 4'h7; + 10'h0e9: data <= 4'h1; + 10'h0ea: data <= 4'h0; + 10'h0eb: data <= 4'h4; + 10'h0ec: data <= 4'h2; + 10'h0ed: data <= 4'hd; + 10'h0ee: data <= 4'h0; + 10'h0ef: data <= 4'h0; + 10'h0f0: data <= 4'h1; + 10'h0f1: data <= 4'h8; + 10'h0f2: data <= 4'h0; + 10'h0f3: data <= 4'h0; + 10'h0f4: data <= 4'h8; + 10'h0f5: data <= 4'hc; + 10'h0f6: data <= 4'h3; + 10'h0f7: data <= 4'hb; + 10'h0f8: data <= 4'hd; + 10'h0f9: data <= 4'h3; + 10'h0fa: data <= 4'ha; + 10'h0fb: data <= 4'h1; + 10'h0fc: data <= 4'h3; + 10'h0fd: data <= 4'h5; + 10'h0fe: data <= 4'h6; + 10'h0ff: data <= 4'h5; + 10'h100: data <= 4'h6; + 10'h101: data <= 4'h5; + 10'h102: data <= 4'h6; + 10'h103: data <= 4'h5; + 10'h104: data <= 4'h5; + 10'h105: data <= 4'h6; + 10'h106: data <= 4'h6; + 10'h107: data <= 4'h5; + 10'h108: data <= 4'h6; + 10'h109: data <= 4'h6; + 10'h10a: data <= 4'h5; + 10'h10b: data <= 4'h5; + 10'h10c: data <= 4'h5; + 10'h10d: data <= 4'h4; + 10'h10e: data <= 4'h4; + 10'h10f: data <= 4'h6; + 10'h110: data <= 4'h6; + 10'h111: data <= 4'h7; + 10'h112: data <= 4'he; + 10'h113: data <= 4'h5; + 10'h114: data <= 4'h6; + 10'h115: data <= 4'h5; + 10'h116: data <= 4'h6; + 10'h117: data <= 4'h5; + 10'h118: data <= 4'h6; + 10'h119: data <= 4'h5; + 10'h11a: data <= 4'h5; + 10'h11b: data <= 4'h5; + 10'h11c: data <= 4'h6; + 10'h11d: data <= 4'h6; + 10'h11e: data <= 4'h6; + 10'h11f: data <= 4'h5; + 10'h120: data <= 4'h5; + 10'h121: data <= 4'h6; + 10'h122: data <= 4'h5; + 10'h123: data <= 4'h5; + 10'h124: data <= 4'h6; + 10'h125: data <= 4'h5; + 10'h126: data <= 4'h6; + 10'h127: data <= 4'h5; + 10'h128: data <= 4'h6; + 10'h129: data <= 4'h5; + 10'h12a: data <= 4'h6; + 10'h12b: data <= 4'h5; + 10'h12c: data <= 4'h6; + 10'h12d: data <= 4'h5; + 10'h12e: data <= 4'h5; + 10'h12f: data <= 4'h6; + 10'h130: data <= 4'h6; + 10'h131: data <= 4'h6; + 10'h132: data <= 4'h6; + 10'h133: data <= 4'h4; + 10'h134: data <= 4'h4; + 10'h135: data <= 4'h6; + 10'h136: data <= 4'h6; + 10'h137: data <= 4'h5; + 10'h138: data <= 4'h6; + 10'h139: data <= 4'h5; + 10'h13a: data <= 4'h6; + 10'h13b: data <= 4'h5; + 10'h13c: data <= 4'h6; + 10'h13d: data <= 4'h5; + 10'h13e: data <= 4'h5; + 10'h13f: data <= 4'h5; + 10'h140: data <= 4'h5; + 10'h141: data <= 4'h6; + 10'h142: data <= 4'h5; + 10'h143: data <= 4'h6; + 10'h144: data <= 4'h5; + 10'h145: data <= 4'h5; + 10'h146: data <= 4'h5; + 10'h147: data <= 4'h6; + 10'h148: data <= 4'h5; + 10'h149: data <= 4'h6; + 10'h14a: data <= 4'h5; + 10'h14b: data <= 4'h6; + 10'h14c: data <= 4'h5; + 10'h14d: data <= 4'h6; + 10'h14e: data <= 4'h5; + 10'h14f: data <= 4'h5; + 10'h150: data <= 4'h6; + 10'h151: data <= 4'h5; + 10'h152: data <= 4'h5; + 10'h153: data <= 4'h6; + 10'h154: data <= 4'h5; + 10'h155: data <= 4'h6; + 10'h156: data <= 4'h5; + 10'h157: data <= 4'h5; + 10'h158: data <= 4'h6; + 10'h159: data <= 4'h5; + 10'h15a: data <= 4'h6; + 10'h15b: data <= 4'h5; + 10'h15c: data <= 4'h6; + 10'h15d: data <= 4'h5; + 10'h15e: data <= 4'h6; + 10'h15f: data <= 4'h5; + 10'h160: data <= 4'h6; + 10'h161: data <= 4'h5; + 10'h162: data <= 4'h6; + 10'h163: data <= 4'h5; + 10'h164: data <= 4'h6; + 10'h165: data <= 4'h5; + 10'h166: data <= 4'h6; + 10'h167: data <= 4'h5; + 10'h168: data <= 4'h6; + 10'h169: data <= 4'h5; + 10'h16a: data <= 4'h6; + 10'h16b: data <= 4'h5; + 10'h16c: data <= 4'h6; + 10'h16d: data <= 4'h5; + 10'h16e: data <= 4'h6; + 10'h16f: data <= 4'h5; + 10'h170: data <= 4'h6; + 10'h171: data <= 4'h5; + 10'h172: data <= 4'h6; + 10'h173: data <= 4'h5; + 10'h174: data <= 4'h6; + 10'h175: data <= 4'h5; + 10'h176: data <= 4'h6; + 10'h177: data <= 4'h5; + 10'h178: data <= 4'h6; + 10'h179: data <= 4'h5; + 10'h17a: data <= 4'h6; + 10'h17b: data <= 4'h5; + 10'h17c: data <= 4'h6; + 10'h17d: data <= 4'h5; + 10'h17e: data <= 4'h6; + 10'h17f: data <= 4'h5; + 10'h180: data <= 4'h6; + 10'h181: data <= 4'h5; + 10'h182: data <= 4'h6; + 10'h183: data <= 4'h5; + 10'h184: data <= 4'h6; + 10'h185: data <= 4'h5; + 10'h186: data <= 4'h6; + 10'h187: data <= 4'h6; + 10'h188: data <= 4'h6; + 10'h189: data <= 4'h6; + 10'h18a: data <= 4'h5; + 10'h18b: data <= 4'h6; + 10'h18c: data <= 4'h6; + 10'h18d: data <= 4'h5; + 10'h18e: data <= 4'h6; + 10'h18f: data <= 4'h6; + 10'h190: data <= 4'h5; + 10'h191: data <= 4'h5; + 10'h192: data <= 4'h6; + 10'h193: data <= 4'h5; + 10'h194: data <= 4'h5; + 10'h195: data <= 4'h6; + 10'h196: data <= 4'h5; + 10'h197: data <= 4'h4; + 10'h198: data <= 4'h4; + 10'h199: data <= 4'h6; + 10'h19a: data <= 4'h6; + 10'h19b: data <= 4'h7; + 10'h19c: data <= 4'h1; + 10'h19d: data <= 4'h0; + 10'h19e: data <= 4'h4; + 10'h19f: data <= 4'h2; + 10'h1a0: data <= 4'hd; + 10'h1a1: data <= 4'h0; + 10'h1a2: data <= 4'h0; + 10'h1a3: data <= 4'h0; + 10'h1a4: data <= 4'h1; + 10'h1a5: data <= 4'h8; + 10'h1a6: data <= 4'h0; + 10'h1a7: data <= 4'h0; + 10'h1a8: data <= 4'h8; + 10'h1a9: data <= 4'h9; + 10'h1aa: data <= 4'h6; + 10'h1ab: data <= 4'hb; + 10'h1ac: data <= 4'ha; + 10'h1ad: data <= 4'h6; + 10'h1ae: data <= 4'h0; + 10'h1af: data <= 4'h0; + 10'h1b0: data <= 4'h5; + 10'h1b1: data <= 4'h6; + 10'h1b2: data <= 4'h5; + 10'h1b3: data <= 4'h6; + 10'h1b4: data <= 4'h5; + 10'h1b5: data <= 4'h6; + 10'h1b6: data <= 4'h5; + 10'h1b7: data <= 4'h5; + 10'h1b8: data <= 4'h5; + 10'h1b9: data <= 4'h6; + 10'h1ba: data <= 4'h5; + 10'h1bb: data <= 4'h5; + 10'h1bc: data <= 4'h6; + 10'h1bd: data <= 4'h6; + 10'h1be: data <= 4'h6; + 10'h1bf: data <= 4'h5; + 10'h1c0: data <= 4'h5; + 10'h1c1: data <= 4'h6; + 10'h1c2: data <= 4'h5; + 10'h1c3: data <= 4'h6; + 10'h1c4: data <= 4'h5; + 10'h1c5: data <= 4'h6; + 10'h1c6: data <= 4'h5; + 10'h1c7: data <= 4'h6; + 10'h1c8: data <= 4'h5; + 10'h1c9: data <= 4'h6; + 10'h1ca: data <= 4'h5; + 10'h1cb: data <= 4'h5; + 10'h1cc: data <= 4'h6; + 10'h1cd: data <= 4'h6; + 10'h1ce: data <= 4'h6; + 10'h1cf: data <= 4'h6; + 10'h1d0: data <= 4'h4; + 10'h1d1: data <= 4'h4; + 10'h1d2: data <= 4'h6; + 10'h1d3: data <= 4'h6; + 10'h1d4: data <= 4'h7; + 10'h1d5: data <= 4'h1; + 10'h1d6: data <= 4'h0; + 10'h1d7: data <= 4'h4; + 10'h1d8: data <= 4'h2; + 10'h1d9: data <= 4'hd; + 10'h1da: data <= 4'h0; + 10'h1db: data <= 4'h0; + 10'h1dc: data <= 4'h1; + 10'h1dd: data <= 4'h8; + 10'h1de: data <= 4'h0; + 10'h1df: data <= 4'h0; + 10'h1e0: data <= 4'h8; + 10'h1e1: data <= 4'h7; + 10'h1e2: data <= 4'h7; + 10'h1e3: data <= 4'hb; + 10'h1e4: data <= 4'h8; + 10'h1e5: data <= 4'h7; + 10'h1e6: data <= 4'ha; + 10'h1e7: data <= 4'hc; + 10'h1e8: data <= 4'h6; + 10'h1e9: data <= 4'h5; + 10'h1ea: data <= 4'h6; + 10'h1eb: data <= 4'h5; + 10'h1ec: data <= 4'h6; + 10'h1ed: data <= 4'h5; + 10'h1ee: data <= 4'h6; + 10'h1ef: data <= 4'h5; + 10'h1f0: data <= 4'h5; + 10'h1f1: data <= 4'h6; + 10'h1f2: data <= 4'h6; + 10'h1f3: data <= 4'h5; + 10'h1f4: data <= 4'h6; + 10'h1f5: data <= 4'h6; + 10'h1f6: data <= 4'h5; + 10'h1f7: data <= 4'h5; + 10'h1f8: data <= 4'h5; + 10'h1f9: data <= 4'h4; + 10'h1fa: data <= 4'h4; + 10'h1fb: data <= 4'h6; + 10'h1fc: data <= 4'h6; + 10'h1fd: data <= 4'h7; + 10'h1fe: data <= 4'hc; + 10'h1ff: data <= 4'h1; + 10'h200: data <= 4'h0; + 10'h201: data <= 4'h0; + 10'h202: data <= 4'hb; + 10'h203: data <= 4'h0; + 10'h204: data <= 4'h0; + 10'h205: data <= 4'h0; + 10'h206: data <= 4'h0; + 10'h207: data <= 4'h0; + 10'h208: data <= 4'h8; + 10'h209: data <= 4'ha; + 10'h20a: data <= 4'h9; + 10'h20b: data <= 4'h4; + 10'h20c: data <= 4'h4; + 10'h20d: data <= 4'h6; + 10'h20e: data <= 4'h6; + 10'h20f: data <= 4'h7; + 10'h210: data <= 4'hb; + 10'h211: data <= 4'h1; + 10'h212: data <= 4'h0; + 10'h213: data <= 4'he; + 10'h214: data <= 4'h5; + 10'h215: data <= 4'h6; + 10'h216: data <= 4'h5; + 10'h217: data <= 4'h6; + 10'h218: data <= 4'h5; + 10'h219: data <= 4'h6; + 10'h21a: data <= 4'h5; + 10'h21b: data <= 4'h5; + 10'h21c: data <= 4'h5; + 10'h21d: data <= 4'h6; + 10'h21e: data <= 4'h5; + 10'h21f: data <= 4'h5; + 10'h220: data <= 4'h6; + 10'h221: data <= 4'h6; + 10'h222: data <= 4'h6; + 10'h223: data <= 4'h5; + 10'h224: data <= 4'h5; + 10'h225: data <= 4'h6; + 10'h226: data <= 4'h5; + 10'h227: data <= 4'h6; + 10'h228: data <= 4'h5; + 10'h229: data <= 4'h6; + 10'h22a: data <= 4'h5; + 10'h22b: data <= 4'h5; + 10'h22c: data <= 4'h6; + 10'h22d: data <= 4'h5; + 10'h22e: data <= 4'h6; + 10'h22f: data <= 4'h6; + 10'h230: data <= 4'h6; + 10'h231: data <= 4'h5; + 10'h232: data <= 4'h5; + 10'h233: data <= 4'h6; + 10'h234: data <= 4'h4; + 10'h235: data <= 4'h4; + 10'h236: data <= 4'h6; + 10'h237: data <= 4'h6; + 10'h238: data <= 4'h7; + 10'h239: data <= 4'h1; + 10'h23a: data <= 4'h0; + 10'h23b: data <= 4'h4; + 10'h23c: data <= 4'h2; + 10'h23d: data <= 4'hd; + 10'h23e: data <= 4'h0; + 10'h23f: data <= 4'h0; + 10'h240: data <= 4'h1; + 10'h241: data <= 4'h8; + 10'h242: data <= 4'h0; + 10'h243: data <= 4'h0; + 10'h244: data <= 4'h8; + 10'h245: data <= 4'h0; + 10'h246: data <= 4'h9; + 10'h247: data <= 4'hb; + 10'h248: data <= 4'h1; + 10'h249: data <= 4'h9; + 10'h24a: data <= 4'ha; + 10'h24b: data <= 4'h0; + 10'h24c: data <= 4'h0; + 10'h24d: data <= 4'h5; + 10'h24e: data <= 4'h6; + 10'h24f: data <= 4'h5; + 10'h250: data <= 4'h6; + 10'h251: data <= 4'h5; + 10'h252: data <= 4'h6; + 10'h253: data <= 4'h5; + 10'h254: data <= 4'h5; + 10'h255: data <= 4'h6; + 10'h256: data <= 4'h6; + 10'h257: data <= 4'h5; + 10'h258: data <= 4'h6; + 10'h259: data <= 4'h6; + 10'h25a: data <= 4'h5; + 10'h25b: data <= 4'h5; + 10'h25c: data <= 4'h5; + 10'h25d: data <= 4'h4; + 10'h25e: data <= 4'h4; + 10'h25f: data <= 4'h6; + 10'h260: data <= 4'h6; + 10'h261: data <= 4'h7; + 10'h262: data <= 4'h1; + 10'h263: data <= 4'h0; + 10'h264: data <= 4'h0; + 10'h265: data <= 4'hb; + 10'h266: data <= 4'h0; + 10'h267: data <= 4'h0; + 10'h268: data <= 4'hc; + 10'h269: data <= 4'h1; + 10'h26a: data <= 4'h0; + 10'h26b: data <= 4'h0; + 10'h26c: data <= 4'hb; + 10'h26d: data <= 4'h0; + 10'h26e: data <= 4'h0; + default: data <= 4'hX; + endcase + end +endmodule diff --git a/tools/iverilog/run_ukp_tb.sh b/tools/iverilog/run_ukp_tb.sh new file mode 100755 index 0000000..6402344 --- /dev/null +++ b/tools/iverilog/run_ukp_tb.sh @@ -0,0 +1,2 @@ +iverilog -DSIM -g2005 -s ukp_tb -o ukp_tb -c ukp_files.txt +vvp ukp_tb diff --git a/tools/iverilog/ukp_files.txt b/tools/iverilog/ukp_files.txt new file mode 100644 index 0000000..8b02961 --- /dev/null +++ b/tools/iverilog/ukp_files.txt @@ -0,0 +1,4 @@ +../../rtl/ukp/ukp.v +../../rtl/ukp/ukprom.v +../../rtl/ukp/keymap.v +ukp_tb.v diff --git a/tools/iverilog/ukp_tb.v b/tools/iverilog/ukp_tb.v new file mode 100644 index 0000000..a8e6800 --- /dev/null +++ b/tools/iverilog/ukp_tb.v @@ -0,0 +1,104 @@ + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// +// Description: Top level test bench for apple1_top +// +// Author.....: Niels A. Moseley +// Date.......: 26-1-2018 +// + +`timescale 1ns/1ps + +module ukp_tb; + + reg clk12; + reg rst, enable; + reg usb_dm_out, usb_dp_out; + reg [3:0] kbd_adr; + + inout usb_dm, usb_dp; + + wire usb_dm_in, usb_dp_in; + wire record_n; + wire [7:0] kbd_data; + + assign usb_dm = (enable) ? usb_dm_out : 1'bZ; + assign usb_dp = (enable) ? usb_dp_out : 1'bZ; + assign usb_dm_in = usb_dm; + assign usb_dp_in = usb_dp; + + ////////////////////////////////////////////////////////////////////////// + // Setup dumping of data for inspection + + initial begin + + clk12 = 1'b0; + enable = 1'b1; + usb_dm_out = 1'b0; + usb_dp_out = 1'b0; + kbd_adr = 1'b0; + rst = 1'b1; + + $display("Starting..."); + $dumpfile("ukp_tb.vcd"); + $dumpvars; + #5 + rst = 1'b0; + + #48000 + usb_dm_out = 1'b1; + #1000 + enable = 1'b0; + + #3267997 + usb_dm_out = 1'b1; + enable = 1'b1; + + #10 + usb_dm_out = 1'b0; + usb_dp_out = 1'b1; + #10 + usb_dm_out = 1'b1; + usb_dp_out = 1'b0; + #10 + usb_dm_out = 1'b0; + usb_dp_out = 1'b1; + + #50000 $display("Stopping..."); + $finish; + end + + ////////////////////////////////////////////////////////////////////////// + // Clock + + always + #2 clk12 = !clk12; + + ////////////////////////////////////////////////////////////////////////// + // Core of system + ukp my_ukp ( + .clk12(clk12), + .rst(rst), + .usb_dm(usb_dm), + .usb_dp(usb_dp), + .record_n(record_n), + .kbd_adr(kbd_adr), + .kbd_data(kbd_data) + ); + +endmodule