1
0
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:
UzixLS
2021-05-03 21:31:30 +03:00
parent c963976795
commit 9d66674549
8 changed files with 427 additions and 44 deletions

View File

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

View File

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