Compare commits

...

4 Commits

Author SHA1 Message Date
Alan Garfield 9e912a21de
Merge 20950b827e into f1abc56bb1 2024-04-17 15:52:58 +01:00
Alan Garfield f1abc56bb1
Update README.md 2024-04-09 21:22:14 +10:00
Alan Garfield 20950b827e WIP still fixing testbench 2018-04-15 23:25:47 +10:00
Alan Garfield bc293896b6 added prelim ukp USB keyboard support 2018-04-12 22:33:39 +10:00
24 changed files with 2311 additions and 1 deletions

View File

@ -16,7 +16,7 @@ Contributor supported boards (YMMV):
<img src="media/apple-one.png" alt="Apple One Running">
</p>
This project borrows heavily from the *awesome* work of Andrew Holme and his ["Pool"](http://www.aholme.co.uk/6502/Main.htm) project and [Arlet Otten's](https://github.com/Arlet/verilog-6502) tiny 6502 core. Also many special thanks to ["sbprojects.com"](https://www.sbprojects.com/projects/apple1/index.php) for the wealth of information I gleaned from there.
This project borrows heavily from the *awesome* work of Andrew Holme and his ["Pool"](http://www.aholme.co.uk/6502/Main.htm) project and [Arlet Otten's](https://github.com/Arlet/verilog-6502) tiny 6502 core. Also many special thanks to [sbprojects.com](https://www.sbprojects.net/projects/apple1/index.php) for the wealth of information I gleaned from there.
## Memory Map

View File

@ -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

View File

@ -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

View File

@ -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,13 @@ 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
input usb_dm_in, // USB keyboard minus pin
input usb_dp_in, // USB keyboard plus pin
output usb_en,
output usb_dm_out, // USB keyboard minus pin
output usb_dp_out, // 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 +112,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 +237,31 @@ module apple1 #(
.clr_screen(vga_cls)
);
// USB keyboard interface
reg [7:0] ukp_dout;
wire [7:0] ukp_d;
wire usb_int;
ukp my_ukp(
.clk25(clk25),
.clkusb(clkusb),
.rst(rst),
.usb_en(usb_en),
.usb_dm_in(usb_dm_in),
.usb_dp_in(usb_dp_in),
.usb_dm_out(usb_dm_out),
.usb_dp_out(usb_dp_out),
.record_n(usb_int),
.kbd_adr(ab[3:0]),
.kbd_data(ukp_d),
.debug(debug)
);
always @(posedge clk25)
begin
if (usb_int)
ukp_dout <= ukp_d;
end
// 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 +310,6 @@ module apple1 #(
uart_cs ? uart_dout :
ps2kb_cs ? ps2_dout :
vga_mode_cs ? vga_mode_dout :
ukp_cs ? ukp_dout :
8'hFF;
endmodule

View File

@ -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
@ -126,6 +130,28 @@ module apple1_top #(
always @(posedge ps2_toggle)
ps2_select <= ~ps2_select;
wire usb_en;
wire usb_dm_in, usb_dp_in;
wire usb_dm_out, usb_dp_out;
SB_IO #(
.PIN_TYPE(6'b101001),
.PULLUP(1'b1)
) tm_dm_io (
.PACKAGE_PIN(usb_dm),
.OUTPUT_ENABLE(usb_en),
.D_IN_0(usb_dm_in),
.D_OUT_0(usb_dm_out)
);
SB_IO #(
.PIN_TYPE(6'b101001),
.PULLUP(1'b1)
) tm_dp_io (
.PACKAGE_PIN(usb_dp),
.OUTPUT_ENABLE(usb_en),
.D_IN_0(usb_dp_in),
.D_OUT_0(usb_dp_out)
);
//////////////////////////////////////////////////////////////////////////
// Core of system
@ -138,6 +164,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 +172,11 @@ module apple1_top #(
.ps2_clk(ps2__clk),
.ps2_din(ps2__din),
.ps2_select(ps2_select),
.usb_en(usb_en),
.usb_dm_in(usb_dm_in),
.usb_dp_in(usb_dp_in),
.usb_dm_out(usb_dm_out),
.usb_dp_out(usb_dp_out),
.vga_h_sync(vga_h_sync),
.vga_v_sync(vga_v_sync),
.vga_red(vga_red),

154
rtl/ukp/keymap.v Normal file
View File

@ -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

599
rtl/ukp/ukp.s Normal file
View File

@ -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

279
rtl/ukp/ukp.v Normal file
View File

@ -0,0 +1,279 @@
module ukp(
clk25,
clkusb,
rst,
usb_en,
usb_dm_in,
usb_dm_out,
usb_dp_in,
usb_dp_out,
record_n,
kbd_adr,
kbd_data
);
input clk25;
input clkusb;
input rst;
input usb_dm_in;
input usb_dp_in;
input [3:0] kbd_adr;
output usb_en;
output usb_dm_out;
output usb_dp_out;
output record_n;
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 I_LDI = 4'b0001;
parameter I_START = 4'b0010;
parameter I_OUT0 = 4'b0100;
parameter I_OUT1 = 4'b0101;
parameter I_OUT2 = 4'b0110;
parameter I_HZ = 4'b0111;
parameter I_BZ = 4'b1000;
parameter I_BC = 4'b1001;
parameter I_BNAK = 4'b1010;
parameter I_DJNZ = 4'b1011;
parameter I_TOGGLE = 4'b1100;
parameter I_IN = 4'b1101;
parameter I_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;
reg inst_ready;
reg g;
reg p;
reg m;
reg cond;
reg nak;
reg dm1;
reg bank;
reg record1;
reg [2:0] state;
reg [7:0] w;
reg [9:0] pc;
reg [2:0] timing;
reg [3:0] tmp;
reg [13:0] interval;
reg [5:0] bitadr;
reg [7:0] data;
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_in |
inst == 4'b1110 & ~interval_cy |
inst == 4'b1101 & (~sample | (usb_dp_in | usb_dm_in) & 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
// set LDI
if (inst == I_LDI) state <= S_LDI0;
// set connected
if (inst == I_TOGGLE) connected <= ~connected;
// handle USB outputs when timing is 0
if (~inst[3] & inst[2] & timing == 0)
begin
g <= ~inst[1] | ~inst[0];
p <= ~inst[1] & inst[0];
m <= inst[1] & ~inst[0];
end
// handle branching
if (inst[3] & ~inst[2])
begin
state <= S_B0;
cond <= sel4(inst[1:0], {~usb_dm_in, 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_in;
data[6:0] <= data[7:1];
data[7] <= dm1 ~^ usb_dm_in;
dm1 <= usb_dm_in;
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

77
rtl/ukp/ukpram.v Normal file
View File

@ -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

649
rtl/ukp/ukprom.v Normal file
View File

@ -0,0 +1,649 @@
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;
`ifdef SIM
10'h00c: data <= 4'h2;
10'h00d: data <= 4'h0;
`else
10'h00c: data <= 4'h8;
10'h00d: data <= 4'hc;
`endif
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;
`ifdef SIM
10'h016: data <= 4'h1;
10'h017: data <= 4'h0;
`else
10'h016: data <= 4'ha;
10'h017: data <= 4'h0;
`endif
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;
`ifdef SIM
10'h01e: data <= 4'h1;
10'h01f: data <= 4'h0;
`else
10'h01e: data <= 4'h8;
10'h01f: data <= 4'h2;
`endif
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

View File

@ -0,0 +1,19 @@
TESTBENCH = ukp_tb
SRC_DIR = ./ukp
SRC = $(SRC_DIR)/ukp.v \
$(SRC_DIR)/ukpram.v \
$(SRC_DIR)/ukprom.v \
$(SRC_DIR)/keymap.v
all: $(TESTBENCH).vcd
display: $(TESTBENCH).vcd
open $(TESTBENCH).vcd
$(TESTBENCH).vcd: $(TESTBENCH).out
vvp $(TESTBENCH).out
$(TESTBENCH).out: $(TESTBENCH).v $(SRC)
iverilog -DSIM -g2005 -o $(TESTBENCH).out $(TESTBENCH).v $(SRC)

132
tools/iverilog/ukp/asukp.py Executable file
View File

@ -0,0 +1,132 @@
#!/usr/bin/env python
"""
ukp compiler
"""
import re
def putline(pcnt, code):
"""
output a line of verilog
"""
return "\t\t\t10'h{:03x}: data = 4'h{:01x};\n".format(pcnt, code)
def main():
"""
main
"""
label_regex = re.compile(r'^\s*(\w+):')
labels = {}
pcnt = 0
instructions = {
'nop': 0,
'ldi': 1,
'start': 2,
'out0': 4,
'out1': 5,
'out2': 6,
'hiz': 7,
'bz': 8,
'bc': 9,
'bnak': 10,
'djnz': 11,
'toggle': 12,
'in': 13,
'wait': 14
}
with open('ukp.s', 'r') as src:
for line in src:
lbl = label_regex.match(line)
if lbl:
# found label
label = lbl.group(1)
if label.startswith(';'):
# commented label
continue
if label in labels:
print("{} already defined!".format(label))
exit(1)
pcnt = pcnt + 3 & ~3
labels[label] = pcnt
print('pc={:03x}\t{}'.format(pcnt, label))
else:
tokens = line.split()
if not tokens or tokens[0].startswith(';'):
# skip empty lines
continue
if tokens[0] not in instructions:
print('syntax error: {}'.format(tokens[0]))
exit(1)
inst = instructions[tokens[0].lower()]
pcnt += 3 if (inst == 1 or inst >= 8 and inst < 12) else 1
src.seek(0)
pcnt = 0
with open('ukprom2.v', 'w') as dst:
dst.write("module ukprom(clk, adr, data);\n")
dst.write("\tinput clk;\n")
dst.write("\tinput [9:0] adr;\n")
dst.write("\toutput [3:0] data;\n")
dst.write("\treg [3:0] data;\n")
dst.write("\talways @(posedge clk) begin\n")
dst.write("\t\tcase (adr)\n")
for line in src:
lbl = label_regex.match(line)
if lbl:
while pcnt & 3:
dst.write(putline(pcnt, 0))
pcnt += 1
else:
tokens = line.split()
if not tokens or tokens[0].startswith(';'):
# skip empty lines
continue
code = instructions[tokens[0].lower()]
lbl = [k for k, v in labels.items() if v == pcnt]
if lbl:
dst.write("// >>>> {}\n".format(lbl.pop()))
if code >= 8 and code < 12:
dst.write("// {}\n".format(tokens[1]))
dst.write(putline(pcnt, code))
pcnt += 1
if code == 1:
dst.write(putline(pcnt, int(tokens[1]) & 15))
pcnt += 1
dst.write(putline(pcnt, int(tokens[1]) >> 4))
pcnt += 1
elif code >= 8 and code < 12:
if tokens[1] not in labels:
print("{} not defined".format(tokens[1]))
exit(1)
addr = labels[tokens[1]] >> 2
dst.write(putline(pcnt, addr & 15))
pcnt += 1
dst.write(putline(pcnt, addr >> 4))
pcnt += 1
dst.write("\t\t\tdefault: data = 4'hX;\n")
dst.write("\t\tendcase\n\tend\nendmodule\n")
if __name__ == "__main__":
main()

View File

@ -0,0 +1,2 @@
iverilog -DSIM -g2005 -s ukp_tb -o ukp_tb -c ukp_files.txt
vvp ukp_tb

1
tools/iverilog/ukp/ukp Symbolic link
View File

@ -0,0 +1 @@
../../../rtl/ukp/

321
tools/iverilog/ukp/ukp_tb.v Normal file
View File

@ -0,0 +1,321 @@
// 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/100ps
module ukp_tb;
reg clk25;
reg clkusb;
reg rst;
reg [3:0] kbd_adr;
wire usb_dm_out, usb_dp_out;
reg usb_dm_in, usb_dp_in;
wire record_n;
wire [7:0] kbd_data;
//////////////////////////////////////////////////////////////////////////
// Setup dumping of data for inspection
initial begin
clk25 = 1'b0;
clkusb = 1'b0;
usb_dm_in = 1'b1;
usb_dp_in = 1'b0;
kbd_adr = 1'b0;
rst = 1'b1;
$display("Starting...");
$dumpfile("ukp_tb.vcd");
$dumpvars;
#5
rst = 1'b0;
// switch off drive to allow seeing bus reset, real USB bus would have
// pull downs and device would have stronger pull up on the D- pin. To
// reset bus host yanks both D+ and D- to ground, in verilog hiz only
// way to see that. It's not real, but useful to see
#6097910.3
usb_dm_in = 1'b0; // K -- SYNC
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1; // J
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0; // K
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1; // J
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0; // K
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1; // J
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0; // K
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b0; // K --
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1; // J -- ACK 0
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b1; // J 1
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0; // K 0
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1; // J 0
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b1; // J 1
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0; // K 0
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b0; // K 1
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b0; // K -- 1
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b0; // -- SE0
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0; // -- SE0
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b1; // J
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b1; // J
usb_dp_in = 1'b0;
#33776.2
usb_dm_in = 1'b0; // K -- SYNC
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1; // J
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0; // K
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1; // J
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0; // K
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1; // J
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0; // K
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b0; // K --
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1; // J -- NACK 0
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b1; // J 1
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0; // K 0
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b0; // J 1
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b0; // J 1
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1; // K 0
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b1; // K 1
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0; // K -- 0
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b0; // -- SE0
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0; // -- SE0
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b1; // J
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b1; // J
usb_dp_in = 1'b0;
#33776.2
usb_dm_in = 1'b0; // K -- SYNC
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1; // J
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0; // K
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1; // J
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0; // K
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1; // J
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0; // K
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b0; // K --
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b0; // K -- DATA0 1
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b0; // K 1
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1; // J 0
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b1; // J 1
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0; // K 0
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1; // K 0
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b1; // K 1
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0; // K -- 0
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1; // -- CRC
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0;
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1;
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0;
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1;
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0;
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1;
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0;
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1;
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0;
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1;
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0;
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1;
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0;
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b1;
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0;
usb_dp_in = 1'b1;
#667.2
usb_dm_in = 1'b0; // -- SE0
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b0; // -- SE0
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b1; // J
usb_dp_in = 1'b0;
#667.2
usb_dm_in = 1'b1; // J
usb_dp_in = 1'b0;
#1500000 $display("Stopping...");
$finish;
end
//////////////////////////////////////////////////////////////////////////
// Clock
//
always
#20 clk25 = !clk25;
always
#41.665 clkusb <= !clkusb;
//////////////////////////////////////////////////////////////////////////
// Core of system
ukp my_ukp (
.clk25(clk25),
.clkusb(clkusb),
.rst(rst),
.usb_dm_in(usb_dm_in),
.usb_dp_in(usb_dp_in),
.usb_dm_out(usb_dm_out),
.usb_dp_out(usb_dp_out),
.record_n(record_n),
.kbd_adr(kbd_adr),
.kbd_data(kbd_data)
);
endmodule