mirror of
https://github.com/UzixLS/zx-sizif-xxs.git
synced 2025-07-19 07:11:28 +03:00
fpga: wip
This commit is contained in:
@ -126,8 +126,11 @@ end
|
||||
|
||||
|
||||
assign div_map = div_automap | div_conmem;
|
||||
assign div_ram = (div_conmem == 1 && bus.a[13] == 1) || (div_automap == 1 && bus.a[13] == 1) || (div_conmem == 0 && div_automap == 1 && div_mapram == 1);
|
||||
assign div_ramwr_mask = bus.a[15] == 0 && bus.a[14] == 0 && (bus.a[13] == 0 || div_page == 4'b0011) && div_conmem == 0 && div_automap == 1 && div_mapram == 1;
|
||||
assign div_ram = (div_conmem == 1 && bus.a[13] == 1) ||
|
||||
(div_automap == 1 && bus.a[13] == 1) ||
|
||||
(div_conmem == 0 && div_automap == 1 && div_mapram == 1);
|
||||
assign div_ramwr_mask = bus.a[15] == 0 && bus.a[14] == 0 &&
|
||||
(bus.a[13] == 0 || div_page == 4'b0011) && div_conmem == 0 && div_automap == 1 && div_mapram == 1;
|
||||
|
||||
assign d_out_active = spi_rd;
|
||||
assign d_out = spi_reg;
|
||||
|
150
fpga/rtl/ps2.v
Normal file
150
fpga/rtl/ps2.v
Normal file
@ -0,0 +1,150 @@
|
||||
`include "ps2_codes.vh"
|
||||
|
||||
module ps2#(
|
||||
parameter CLK_FREQ
|
||||
) (
|
||||
input rst_n,
|
||||
input clk,
|
||||
|
||||
input ps2_clk_in,
|
||||
input ps2_dat_in,
|
||||
output ps2_clk_out,
|
||||
output ps2_dat_out,
|
||||
|
||||
input [7:0] zxkb_addr,
|
||||
output [4:0] zxkb_data,
|
||||
output reg key_magic,
|
||||
output reg key_reset
|
||||
);
|
||||
|
||||
|
||||
/* KD0 KD1 KD2 KD3 KD4
|
||||
* KA8(0) cs z x c v
|
||||
* KA9(1) a s d f g
|
||||
* KA10(2) q w e r t
|
||||
* KA11(3) 1 2 3 4 5
|
||||
* KA12(4) 0 9 8 7 6
|
||||
* KA13(5) p o i u y
|
||||
* KA14(6) en l k j h
|
||||
* KA15(7) sp ss m n b
|
||||
*/
|
||||
|
||||
|
||||
reg rxdone;
|
||||
reg rxerr;
|
||||
reg [7:0] rxbyte;
|
||||
ps2_rxtx #(.CLK_FREQ(CLK_FREQ)) ps2_rxtx0(
|
||||
.rst_n(rst_n),
|
||||
.clk(clk),
|
||||
.ps2_clk_in(ps2_clk_in),
|
||||
.ps2_dat_in(ps2_dat_in),
|
||||
.ps2_clk_out(ps2_clk_out),
|
||||
.ps2_dat_out(ps2_dat_out),
|
||||
.dataout(rxbyte),
|
||||
.dataout_valid(rxdone),
|
||||
.dataout_error(rxerr)
|
||||
);
|
||||
|
||||
|
||||
reg is_press;
|
||||
reg is_ext;
|
||||
reg [4:0] zxkb [0:7];
|
||||
always @(posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
integer i;
|
||||
for (i = 0; i < 8; i = i + 1)
|
||||
zxkb[i] <= 0;
|
||||
is_press <= 0;
|
||||
is_ext <= 0;
|
||||
key_magic <= 0;
|
||||
key_reset <= 0;
|
||||
end
|
||||
else begin
|
||||
if (rxerr) begin
|
||||
is_press <= 0;
|
||||
is_ext <= 0;
|
||||
end
|
||||
else if (rxdone) begin
|
||||
is_press <= rxbyte != 8'hF0;
|
||||
is_ext <= rxbyte == 8'hE0 || (rxbyte == 8'hF0 && is_ext);
|
||||
case ({is_ext, rxbyte})
|
||||
`PS2_A: zxkb[1][0] = is_press;
|
||||
`PS2_B: zxkb[7][4] = is_press;
|
||||
`PS2_C: zxkb[0][3] = is_press;
|
||||
`PS2_D: zxkb[1][2] = is_press;
|
||||
`PS2_E: zxkb[2][2] = is_press;
|
||||
`PS2_F: zxkb[1][3] = is_press;
|
||||
`PS2_G: zxkb[1][4] = is_press;
|
||||
`PS2_H: zxkb[6][4] = is_press;
|
||||
`PS2_I: zxkb[5][2] = is_press;
|
||||
`PS2_J: zxkb[6][3] = is_press;
|
||||
`PS2_K: zxkb[6][2] = is_press;
|
||||
`PS2_L: zxkb[6][1] = is_press;
|
||||
`PS2_M: zxkb[7][2] = is_press;
|
||||
`PS2_N: zxkb[7][3] = is_press;
|
||||
`PS2_O: zxkb[5][1] = is_press;
|
||||
`PS2_P: zxkb[5][0] = is_press;
|
||||
`PS2_Q: zxkb[2][0] = is_press;
|
||||
`PS2_R: zxkb[2][3] = is_press;
|
||||
`PS2_S: zxkb[1][1] = is_press;
|
||||
`PS2_T: zxkb[2][4] = is_press;
|
||||
`PS2_U: zxkb[5][3] = is_press;
|
||||
`PS2_V: zxkb[0][4] = is_press;
|
||||
`PS2_W: zxkb[2][1] = is_press;
|
||||
`PS2_X: zxkb[0][2] = is_press;
|
||||
`PS2_Y: zxkb[5][4] = is_press;
|
||||
`PS2_Z: zxkb[0][1] = is_press;
|
||||
`PS2_0: zxkb[4][0] = is_press;
|
||||
`PS2_1: zxkb[3][0] = is_press;
|
||||
`PS2_2: zxkb[3][1] = is_press;
|
||||
`PS2_3: zxkb[3][2] = is_press;
|
||||
`PS2_4: zxkb[3][3] = is_press;
|
||||
`PS2_5: zxkb[3][4] = is_press;
|
||||
`PS2_6: zxkb[4][4] = is_press;
|
||||
`PS2_7: zxkb[4][3] = is_press;
|
||||
`PS2_8: zxkb[4][2] = is_press;
|
||||
`PS2_9: zxkb[4][1] = is_press;
|
||||
|
||||
`PS2_SPACE: zxkb[7][0] = is_press;
|
||||
`PS2_ENTER: zxkb[6][0] = is_press;
|
||||
`PS2_ESC: begin zxkb[0][0] = is_press; zxkb[7][0] = is_press; end
|
||||
`PS2_BACKSPACE: begin zxkb[0][0] = is_press; zxkb[4][0] = is_press; end
|
||||
|
||||
`PS2_PERIOD: begin zxkb[7][1] = is_press; zxkb[7][2] = is_press; end
|
||||
`PS2_COMMA: begin zxkb[7][1] = is_press; zxkb[7][3] = is_press; end
|
||||
`PS2_SLASH: begin zxkb[7][1] = is_press; zxkb[0][4] = is_press; end
|
||||
`PS2_SEMICOLON: begin zxkb[7][1] = is_press; zxkb[5][1] = is_press; end
|
||||
`PS2_QUOTE: begin zxkb[7][1] = is_press; zxkb[5][0] = is_press; end
|
||||
|
||||
`PS2_UP: begin zxkb[0][0] = is_press; zxkb[4][3] = is_press; end
|
||||
`PS2_DOWN: begin zxkb[0][0] = is_press; zxkb[4][4] = is_press; end
|
||||
`PS2_LEFT: begin zxkb[0][0] = is_press; zxkb[3][4] = is_press; end
|
||||
`PS2_RIGHT: begin zxkb[0][0] = is_press; zxkb[4][2] = is_press; end
|
||||
|
||||
`PS2_L_SHIFT: zxkb[7][1] = is_press;
|
||||
`PS2_R_SHIFT: zxkb[7][1] = is_press;
|
||||
`PS2_L_CTRL: zxkb[0][0] = is_press;
|
||||
`PS2_R_CTRL: zxkb[0][0] = is_press;
|
||||
|
||||
`PS2_F5: key_magic = is_press;
|
||||
`PS2_F12: key_reset = is_press;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @* begin
|
||||
zxkb_data <= ~(
|
||||
((~zxkb_addr[0])? zxkb[0] : 5'd0) |
|
||||
((~zxkb_addr[1])? zxkb[1] : 5'd0) |
|
||||
((~zxkb_addr[2])? zxkb[2] : 5'd0) |
|
||||
((~zxkb_addr[3])? zxkb[3] : 5'd0) |
|
||||
((~zxkb_addr[4])? zxkb[4] : 5'd0) |
|
||||
((~zxkb_addr[5])? zxkb[5] : 5'd0) |
|
||||
((~zxkb_addr[6])? zxkb[6] : 5'd0) |
|
||||
((~zxkb_addr[7])? zxkb[7] : 5'd0)
|
||||
);
|
||||
end
|
||||
|
||||
endmodule
|
119
fpga/rtl/ps2_codes.vh
Normal file
119
fpga/rtl/ps2_codes.vh
Normal file
@ -0,0 +1,119 @@
|
||||
// A-Z
|
||||
`define PS2_A 9'h1C
|
||||
`define PS2_B 9'h32
|
||||
`define PS2_C 9'h21
|
||||
`define PS2_D 9'h23
|
||||
`define PS2_E 9'h24
|
||||
`define PS2_F 9'h2B
|
||||
`define PS2_G 9'h34
|
||||
`define PS2_H 9'h33
|
||||
`define PS2_I 9'h43
|
||||
`define PS2_J 9'h3B
|
||||
`define PS2_K 9'h42
|
||||
`define PS2_L 9'h4B
|
||||
`define PS2_M 9'h3A
|
||||
`define PS2_N 9'h31
|
||||
`define PS2_O 9'h44
|
||||
`define PS2_P 9'h4D
|
||||
`define PS2_Q 9'h15
|
||||
`define PS2_R 9'h2D
|
||||
`define PS2_S 9'h1B
|
||||
`define PS2_T 9'h2C
|
||||
`define PS2_U 9'h3C
|
||||
`define PS2_V 9'h2A
|
||||
`define PS2_W 9'h1D
|
||||
`define PS2_X 9'h22
|
||||
`define PS2_Y 9'h35
|
||||
`define PS2_Z 9'h1A
|
||||
|
||||
// 0-9
|
||||
`define PS2_0 9'h45
|
||||
`define PS2_1 9'h16
|
||||
`define PS2_2 9'h1E
|
||||
`define PS2_3 9'h26
|
||||
`define PS2_4 9'h25
|
||||
`define PS2_5 9'h2E
|
||||
`define PS2_6 9'h36
|
||||
`define PS2_7 9'h3D
|
||||
`define PS2_8 9'h3E
|
||||
`define PS2_9 9'h46
|
||||
|
||||
// Others
|
||||
`define PS2_ACCENT 9'h0E // '`'
|
||||
`define PS2_MINUS 9'h4E // '-'
|
||||
`define PS2_EQUALS 9'h55 // '='
|
||||
`define PS2_BACK_SLASH 9'h5D // '\'
|
||||
`define PS2_SPACE 9'h29 // ' '
|
||||
`define PS2_TAB 9'h0D // '\t'
|
||||
`define PS2_L_BRACKET 9'h54 // '['
|
||||
`define PS2_R_BRACKET 9'h5B // ']'
|
||||
`define PS2_SEMICOLON 9'h4C // ';'
|
||||
`define PS2_QUOTE 9'h52 // '''
|
||||
`define PS2_COMMA 9'h41 // ','
|
||||
`define PS2_PERIOD 9'h49 // '.'
|
||||
`define PS2_SLASH 9'h4A // '/'
|
||||
|
||||
// Control
|
||||
`define PS2_BACKSPACE 9'h66
|
||||
`define PS2_CAPS 9'h58
|
||||
`define PS2_SCROLL 9'h7E
|
||||
`define PS2_NUM 9'h77
|
||||
`define PS2_L_SHIFT 9'h12
|
||||
`define PS2_R_SHIFT 9'h59
|
||||
`define PS2_L_CTRL 9'h14
|
||||
`define PS2_R_CTRL 9'h114
|
||||
`define PS2_L_ALT 9'h11
|
||||
`define PS2_R_ALT 9'h111
|
||||
`define PS2_ENTER 9'h5A
|
||||
`define PS2_ESC 9'h76
|
||||
`define PS2_INSERT 9'h170
|
||||
`define PS2_DELETE 9'h171
|
||||
`define PS2_HOME 9'h16C
|
||||
`define PS2_END 9'h169
|
||||
`define PS2_PGUP 9'h17D
|
||||
`define PS2_PGDN 9'h17A
|
||||
`define PS2_UP 9'h175
|
||||
`define PS2_DOWN 9'h172
|
||||
`define PS2_LEFT 9'h16B
|
||||
`define PS2_RIGHT 9'h174
|
||||
`define PS2_PSCR1 9'h112
|
||||
`define PS2_PSCR2 9'h17c
|
||||
`define PS2_L_WIN 9'h11f
|
||||
`define PS2_R_WIN 9'h127
|
||||
`define PS2_MENU 9'h12f
|
||||
`define PS2_PAUSE 9'h177
|
||||
|
||||
|
||||
// F1..F12
|
||||
`define PS2_F1 9'h05
|
||||
`define PS2_F2 9'h06
|
||||
`define PS2_F3 9'h04
|
||||
`define PS2_F4 9'h0C
|
||||
`define PS2_F5 9'h03
|
||||
`define PS2_F6 9'h0B
|
||||
`define PS2_F7 9'h83
|
||||
`define PS2_F8 9'h0A
|
||||
`define PS2_F9 9'h01
|
||||
`define PS2_F10 9'h09
|
||||
`define PS2_F11 9'h78
|
||||
`define PS2_F12 9'h07
|
||||
|
||||
// Keypad
|
||||
`define PS2_NUMLOCK 9'h77
|
||||
`define PS2_KP_SLASH 9'h14A
|
||||
`define PS2_KP_STAR 9'h7C
|
||||
`define PS2_KP_MINUS 9'h7B
|
||||
`define PS2_KP_PLUS 9'h79
|
||||
`define PS2_KP_ENTER 9'h15A
|
||||
`define PS2_KP_PERIOD 9'h71
|
||||
`define PS2_KP_0 9'h70
|
||||
`define PS2_KP_1 9'h69
|
||||
`define PS2_KP_2 9'h72
|
||||
`define PS2_KP_3 9'h7A
|
||||
`define PS2_KP_4 9'h6B
|
||||
`define PS2_KP_5 9'h73
|
||||
`define PS2_KP_6 9'h74
|
||||
`define PS2_KP_7 9'h6C
|
||||
`define PS2_KP_8 9'h75
|
||||
`define PS2_KP_9 9'h7D
|
||||
|
76
fpga/rtl/ps2_rxtx.v
Normal file
76
fpga/rtl/ps2_rxtx.v
Normal file
@ -0,0 +1,76 @@
|
||||
module ps2_rxtx#(
|
||||
parameter CLK_FREQ
|
||||
) (
|
||||
input rst_n,
|
||||
input clk,
|
||||
|
||||
input ps2_clk_in,
|
||||
input ps2_dat_in,
|
||||
output ps2_clk_out,
|
||||
output ps2_dat_out,
|
||||
|
||||
output [7:0] dataout,
|
||||
output reg dataout_valid,
|
||||
output reg dataout_error
|
||||
);
|
||||
|
||||
localparam CLKWAIT_US = 100;
|
||||
localparam CLKWAIT_WIDTH = $clog2(int'(CLKWAIT_US*CLK_FREQ/1e6));
|
||||
|
||||
reg ps2_clk_prev, ps2_clk, ps2_dat;
|
||||
always @(posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
ps2_dat <= 1'b1;
|
||||
ps2_clk <= 1'b1;
|
||||
ps2_clk_prev <= 1'b1;
|
||||
end
|
||||
else begin
|
||||
ps2_dat <= ps2_dat_in;
|
||||
ps2_clk <= ps2_clk_in;
|
||||
ps2_clk_prev <= ps2_clk;
|
||||
end
|
||||
end
|
||||
|
||||
reg [CLKWAIT_WIDTH-1:0] wait_cnt;
|
||||
reg [3:0] bit_cnt;
|
||||
reg [9:0] rxbits;
|
||||
assign dataout = rxbits[8:1];
|
||||
always @(posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
dataout_valid <= 0;
|
||||
dataout_error <= 0;
|
||||
wait_cnt <= 0;
|
||||
bit_cnt <= 0;
|
||||
rxbits <= 0;
|
||||
ps2_clk_out <= 1'b1;
|
||||
ps2_dat_out <= 1'b1;
|
||||
end
|
||||
else begin
|
||||
dataout_valid <= 0;
|
||||
dataout_error <= 0;
|
||||
if (ps2_clk == 0 && ps2_clk_prev == 1'b1) begin
|
||||
if (bit_cnt == 4'd10) begin
|
||||
bit_cnt <= 0;
|
||||
if (rxbits[0] == 0 && ~rxbits[9] == ^rxbits[8:1] && ps2_dat == 1'b1)
|
||||
dataout_valid <= 1'b1;
|
||||
else
|
||||
dataout_error <= 1'b1;
|
||||
end
|
||||
else begin
|
||||
bit_cnt <= bit_cnt + 1'b1;
|
||||
rxbits <= {ps2_dat, rxbits[9:1]};
|
||||
end
|
||||
wait_cnt <= 0;
|
||||
end
|
||||
else if (bit_cnt != 0) begin
|
||||
if (&wait_cnt) begin
|
||||
bit_cnt <= 0;
|
||||
dataout_error <= 1'b1;
|
||||
end
|
||||
wait_cnt <= wait_cnt + 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
@ -77,7 +77,7 @@ reg up_en;
|
||||
reg [1:0] r, g, b;
|
||||
reg hsync;
|
||||
wire blink;
|
||||
wire [2:0] screen_border = {border[2] ^ ~sd_cd, border[1] ^ magic_beeper, border[0] ^ (pause & blink)};
|
||||
wire [2:0] screen_border = {border[2] ^ ~sd_cs, border[1] ^ magic_beeper, border[0] ^ (pause & blink)};
|
||||
wire screen_read, screen_load, screen_read_up;
|
||||
wire [14:0] screen_addr;
|
||||
wire [5:0] screen_up_addr;
|
||||
@ -175,6 +175,26 @@ cpucontrol cpucontrol0(
|
||||
);
|
||||
|
||||
|
||||
/* KEYBOARD */
|
||||
reg ps2_clk_out, ps2_dat_out;
|
||||
reg [4:0] ps2_kd;
|
||||
reg key_magic, key_reset;
|
||||
ps2 #(.CLK_FREQ(28_000_000)) ps2_0 (
|
||||
.rst_n(rst_n),
|
||||
.clk(clk28),
|
||||
.ps2_clk_in(ps2_clk),
|
||||
.ps2_dat_in(ps2_data),
|
||||
.ps2_clk_out(ps2_clk_out),
|
||||
.ps2_dat_out(ps2_dat_out),
|
||||
.zxkb_addr(bus.a[15:8]),
|
||||
.zxkb_data(ps2_kd),
|
||||
.key_magic(key_magic),
|
||||
.key_reset(key_reset)
|
||||
);
|
||||
assign ps2_clk = (ps2_clk_out == 0)? 1'b0 : 1'bz;
|
||||
assign ps2_data = (ps2_dat_out == 0)? 1'b0 : 1'bz;
|
||||
|
||||
|
||||
/* MAGIC */
|
||||
reg magic_mode, magic_map;
|
||||
wire magic_active_next;
|
||||
@ -189,7 +209,7 @@ magic magic0(
|
||||
.n_int_next(n_int_next),
|
||||
.n_nmi(n_nmi),
|
||||
|
||||
.magic_button(0),
|
||||
.magic_button(key_magic),
|
||||
|
||||
.magic_mode(magic_mode),
|
||||
.magic_map(magic_map),
|
||||
@ -234,7 +254,7 @@ ports ports0 (
|
||||
.timings(timings),
|
||||
.screen_load(screen_load),
|
||||
.attr_next(attr_next),
|
||||
.kd(5'b11111),
|
||||
.kd(ps2_kd),
|
||||
.kempston_data(8'b11111111),
|
||||
.joy_sinclair(joy_sinclair),
|
||||
.magic_active_next(magic_active_next),
|
||||
@ -370,7 +390,7 @@ divmmc divmmc0(
|
||||
.d_out(div_dout),
|
||||
.d_out_active(div_dout_active),
|
||||
|
||||
.sd_cd(sd_cd | 1),
|
||||
.sd_cd(sd_cd),
|
||||
.sd_miso(sd_miso_tape_in),
|
||||
.sd_mosi(sd_mosi0),
|
||||
.sd_sck(sd_sck),
|
||||
@ -426,7 +446,7 @@ end
|
||||
|
||||
/* MEMORY INITIALIZER */
|
||||
wire rom2ram_clk = clk35;
|
||||
wire [14:0] rom2ram_ram_address, rom2ram_rom_address;
|
||||
wire [16:0] rom2ram_ram_address, rom2ram_rom_address;
|
||||
wire [7:0] rom2ram_datain, rom2ram_dataout;
|
||||
wire rom2ram_rom_rden;
|
||||
wire rom2ram_rom_data_ready;
|
||||
@ -526,7 +546,7 @@ always @(posedge clk28) begin
|
||||
end
|
||||
|
||||
assign va[18:0] =
|
||||
rom2ram_ram_wren? {4'b0000, rom2ram_ram_address} :
|
||||
rom2ram_ram_wren? {2'b00, rom2ram_ram_address} :
|
||||
screen_read && screen_read_up? {2'b00, 3'b111, 8'b11111111, screen_up_addr} :
|
||||
screen_read && snow? {3'b111, screenpage, screen_addr[14:8], bus.a[7:0]} :
|
||||
screen_read? {3'b111, screenpage, screen_addr} :
|
||||
|
Reference in New Issue
Block a user