mirror of https://github.com/zxdos/zxuno.git
SamCoupe a test2
This commit is contained in:
parent
5bf160631a
commit
9b683eb5f6
|
|
@ -88,12 +88,19 @@ module asic (
|
|||
VBPORCH +
|
||||
TBORDER;
|
||||
|
||||
// Start of vertical sync, horizontal counter (last 4 scanlines)
|
||||
parameter BEGINVSYNCH = HACTIVEREGION + RBORDER + HFPORCH + HSYNC + HBPORCH;
|
||||
parameter BEGINVINTH = HACTIVEREGION + RBORDER + HFPORCH;
|
||||
|
||||
// Start and end of vertical retrace interrupt, horizontal counter
|
||||
parameter BEGINVINTH = BEGINVSYNCH; //HACTIVEREGION + RBORDER + HFPORCH;
|
||||
parameter ENDVINTH = (BEGINVINTH + 256)%HTOTAL;
|
||||
|
||||
// Start and end of vertical retrace interrupt, vertical counter
|
||||
parameter BEGINVINTV = VACTIVEREGION + BBORDER + VFPORCH - 1;
|
||||
parameter ENDVINTV = VACTIVEREGION + BBORDER + VFPORCH;
|
||||
parameter ENDVINTH = (BEGINVINTH + 256)%HTOTAL;
|
||||
parameter BEGINHINTH = HACTIVEREGION + RBORDER + HFPORCH;
|
||||
|
||||
// Start and end of raster interrupt, horizontal counter
|
||||
parameter BEGINHINTH = HACTIVEREGION + RBORDER;
|
||||
parameter ENDHINTH = (BEGINHINTH + 256)%HTOTAL;
|
||||
|
||||
parameter IOADDR_VMPR = 8'd252,
|
||||
|
|
@ -103,7 +110,8 @@ module asic (
|
|||
IOADDR_LINEINT = 8'd249,
|
||||
IOADDR_STATUS = 8'd249,
|
||||
IOADDR_BASECLUT = 8'd248,
|
||||
IOADDR_ATTRIB = 8'd255;
|
||||
IOADDR_ATTRIB = 8'd255,
|
||||
IOADDR_HLPEN = 8'd248;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// IO regs
|
||||
|
|
@ -122,7 +130,7 @@ module asic (
|
|||
wire rom_in_section_d = lmpr[6];
|
||||
wire write_protect_section_a = lmpr[7];
|
||||
|
||||
reg [7:0] hmpr = 8'h02; // port 251. Bit 7 is not used for now. R/W
|
||||
reg [7:0] hmpr = 8'h00; // port 251. Bit 7 is not used for now. R/W
|
||||
wire [4:0] high_page = hmpr[4:0];
|
||||
wire [1:0] clut_mode_3_hi = hmpr[6:5];
|
||||
|
||||
|
|
@ -134,6 +142,9 @@ module asic (
|
|||
|
||||
reg [7:0] lineint = 8'hFF; // port 249 write only
|
||||
|
||||
reg [7:0] hpen = 8'h00;
|
||||
reg [7:0] lpen = 8'h00;
|
||||
|
||||
reg [6:0] clut[0:15]; // Port xF8h where x=0..F
|
||||
initial begin
|
||||
clut[ 0] = 7'b000_0_000;
|
||||
|
|
@ -171,6 +182,23 @@ module asic (
|
|||
end
|
||||
end
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// HPEN and LPEN counters
|
||||
always @(posedge clk) begin
|
||||
if (hc[0] == 1'b0) begin
|
||||
if (hc == HACTIVEREGION) begin
|
||||
if (vc == VTOTAL-1)
|
||||
hpen <= 8'h00;
|
||||
else if (vc < VACTIVEREGION)
|
||||
hpen <= hpen + 1;
|
||||
end
|
||||
if (hc < HACTIVEREGION)
|
||||
lpen <= lpen + 1;
|
||||
else
|
||||
lpen <= 8'h00;
|
||||
end
|
||||
end
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Syncs and vertical retrace/raster line int generation
|
||||
reg vint_n;
|
||||
|
|
@ -189,18 +217,29 @@ module asic (
|
|||
csync = ~csync;
|
||||
if ( (vc == BEGINVINTV && hc >= BEGINVINTH) ||
|
||||
(vc == ENDVINTV && hc < ENDVINTH) )
|
||||
vint_n = 1'b0;
|
||||
// if (vc == BEGINVINTV && hc >= BEGINVINTH)
|
||||
vint_n = 1'b0;
|
||||
if (lineint >= 8'd0 && lineint <= 8'd191) begin
|
||||
// if (lineint == 8'd0) begin
|
||||
// if (vc == VTOTAL-1 && hc >= BEGINHINTH ||
|
||||
// vc == 9'd0 && hc < ENDHINTH)
|
||||
// rint_n = 1'b0;
|
||||
// end
|
||||
// else begin
|
||||
// if ({1'b0, lineint} == vc-1 && hc >= BEGINHINTH ||
|
||||
// {1'b0, lineint} == vc && hc < ENDHINTH)
|
||||
// rint_n = 1'b0;
|
||||
// end
|
||||
// end
|
||||
if (lineint == 8'd0) begin
|
||||
if (vc == VTOTAL-1 && hc >= BEGINHINTH ||
|
||||
vc == 9'd0 && hc < ENDHINTH)
|
||||
rint_n = 1'b0;
|
||||
if (vc == VTOTAL-1 && hc >= BEGINHINTH)
|
||||
rint_n = 1'b0;
|
||||
end
|
||||
else begin
|
||||
if ({1'b0, lineint} == vc-1 && hc >= BEGINHINTH ||
|
||||
{1'b0, lineint} == vc && hc < ENDHINTH)
|
||||
rint_n = 1'b0;
|
||||
if ({1'b0, lineint} == vc-1 && hc >= BEGINHINTH)
|
||||
rint_n = 1'b0;
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
assign int_n = vint_n & rint_n;
|
||||
|
|
@ -233,41 +272,47 @@ module asic (
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Contention signal (risk of)
|
||||
reg contention;
|
||||
reg mem_contention;
|
||||
reg io_contention;
|
||||
|
||||
always @* begin
|
||||
contention = 1'b0;
|
||||
mem_contention = 1'b0;
|
||||
|
||||
if (hc[3:0]<4'd10)
|
||||
io_contention = 1'b1;
|
||||
else
|
||||
io_contention = 1'b0;
|
||||
|
||||
if (fetching_pixels == 1'b1 && hc[3:0]<4'd10)
|
||||
contention = 1'b1;
|
||||
mem_contention = 1'b1;
|
||||
else if (fetching_pixels == 1'b0 && (hc[3:0]==4'd0 ||
|
||||
hc[3:0]==4'd1 ||
|
||||
hc[3:0]==4'd8 ||
|
||||
hc[3:0]==4'd9) )
|
||||
contention = 1'b1;
|
||||
mem_contention = 1'b1;
|
||||
if (screen_mode == 2'b00 && hc[3:0]<4'd10 && hc[9:4]<6'd40)
|
||||
contention = 1'b1;
|
||||
mem_contention = 1'b1; // extra contention for MODE 1
|
||||
end
|
||||
assign asic_is_using_ram = contention & fetching_pixels;
|
||||
assign asic_is_using_ram = mem_contention & fetching_pixels;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// WAIT signal with contention applied
|
||||
always @* begin
|
||||
wait_n = 1'b1;
|
||||
if (cpuaddr<16'h4000 && rom_in_section_a==1'b1)
|
||||
if (mreq_n == 1'b0 && cpuaddr<16'h4000 && rom_in_section_a==1'b1)
|
||||
wait_n = 1'b1;
|
||||
else if (cpuaddr>=16'hC000 && rom_in_section_d==1'b1)
|
||||
else if (mreq_n == 1'b0 && cpuaddr>=16'hC000 && rom_in_section_d==1'b1)
|
||||
wait_n = 1'b1;
|
||||
else if (contention == 1'b1) begin
|
||||
if (mreq_n == 1'b0)
|
||||
wait_n = 1'b0;
|
||||
else if (iorq_n == 1'b0)
|
||||
if (rd_n == 1'b0 || wr_n == 1'b0)
|
||||
wait_n = 1'b0;
|
||||
end
|
||||
else if (mem_contention == 1'b1 && mreq_n == 1'b0)
|
||||
wait_n = 1'b0;
|
||||
else if (io_contention == 1'b1 && iorq_n == 1'b0)
|
||||
wait_n = 1'b0;
|
||||
end
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// VRAM address generation
|
||||
reg [14:0] screen_offs = 15'h0000;
|
||||
reg [4:0] screen_column = 5'h00;
|
||||
always @* begin
|
||||
if (screen_mode == 2'd0) begin
|
||||
if (hc[2] == 1'b0)
|
||||
|
|
@ -282,13 +327,11 @@ module asic (
|
|||
vramaddr = {screen_page, 1'b1, screen_offs[12:0]};
|
||||
end
|
||||
else
|
||||
vramaddr = {screen_page[4:0], 14'b00000000000000} + {3'b000, screen_offs};
|
||||
vramaddr = {screen_page[4:1], screen_offs};
|
||||
end
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// FSM for fetching pixels from RAM and shift registers
|
||||
reg [15:0] screen_offs = 16'h0000;
|
||||
reg [4:0] screen_column = 5'h00;
|
||||
reg [7:0] vram_byte1, vram_byte2, vram_byte3, vram_byte4;
|
||||
reg [7:0] sregm12 = 8'h00;
|
||||
reg [7:0] attrreg = 8'h00;
|
||||
|
|
@ -300,7 +343,7 @@ module asic (
|
|||
always @(posedge clk) begin
|
||||
// a good time to reset pixel address counters and advance flash counter for modes 1 and 2
|
||||
if (vc==(VTOTAL-1) && hc==(HTOTAL-1)) begin
|
||||
screen_offs <= 16'h0000;
|
||||
screen_offs <= 15'h0000;
|
||||
screen_column <= 5'h00;
|
||||
flash_counter <= flash_counter + 1;
|
||||
end
|
||||
|
|
@ -433,15 +476,14 @@ module asic (
|
|||
// Write to IO ports from CPU
|
||||
always @(posedge clk) begin
|
||||
if (rst_n == 1'b0) begin
|
||||
`ifdef SYNTH
|
||||
`ifdef SYNTH
|
||||
vmpr <= 8'h00;
|
||||
`else
|
||||
vmpr <= 8'b01100000;
|
||||
`endif
|
||||
lmpr <= 8'h00;
|
||||
hmpr <= 8'h02;
|
||||
hmpr <= 8'h00;
|
||||
border <= 8'h00;
|
||||
lineint <= 8'hFF;
|
||||
end
|
||||
else begin
|
||||
if (iorq_n == 1'b0 && wr_n == 1'b0) begin
|
||||
|
|
@ -481,6 +523,10 @@ module asic (
|
|||
data_to_cpu = hmpr;
|
||||
else if (cpuaddr[7:0] == IOADDR_LMPR)
|
||||
data_to_cpu = lmpr;
|
||||
else if (cpuaddr[8:0] == {1'b0, IOADDR_HLPEN} )
|
||||
data_to_cpu = lpen;
|
||||
else if (cpuaddr[8:0] == {1'b1, IOADDR_HLPEN} )
|
||||
data_to_cpu = hpen;
|
||||
else if (cpuaddr[7:0]>=8'd224 && cpuaddr[7:0]<=8'd231) begin
|
||||
disc1_n = 1'b0;
|
||||
data_enable_n = 1'b1;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,473 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef unsigned char BYTE;
|
||||
/*
|
||||
12 12 3 3 2
|
||||
AAAA DDDDDDDD AAAA DDDDDDDD MRN MMM XX
|
||||
|
||||
AAAA = semifila del teclado a modificar | esta información está
|
||||
DDDDDDDD = dato (AND negado con lo que haya) de esa semifila | repetida para dos teclas
|
||||
MRN = Master reset, Reset de usuario, NMI
|
||||
MMM = la tecla es un modificador
|
||||
XX = Reservado para uso futuro
|
||||
|
||||
Ej: en la dirección de memoria correspondiente al código de la tecla ESC,
|
||||
que correspondería la tecla ESC del SAM, pondríamos:
|
||||
1000 00100000 0000 00000000 000 000 00
|
||||
En la dirección de memoria correspondiente al código de la tecla < que se
|
||||
corresponde con la pulsación SYMBOL+Q pondríamos:
|
||||
0111 00000010 0010 00000001 000 000 00
|
||||
|
||||
256 codigos + E0 = 512 codigos
|
||||
SHIFT, CTRL, ALT = 8 combinaciones
|
||||
|
||||
512*8=4096 direcciones x 32 bits = 16384 bytes
|
||||
En el core se dispondrá como una memoria de 16384x8 bits
|
||||
|
||||
Cada tecla ocupará cuatro direcciones consecutivas según el esquema anterior.
|
||||
*/
|
||||
|
||||
// You shouldn't have to touch these defs unless your Spectrum has a different keyboard
|
||||
// layout (because, for example, you are using a different ROM
|
||||
|
||||
// CCCC BBBBAAAA -- hex digits for coding
|
||||
#define SAM_1 0x301 // 0011 00000001
|
||||
#define SAM_2 0x302 // 0011 00000010
|
||||
#define SAM_3 0x304 // 0011 00000100
|
||||
#define SAM_4 0x308 // 0011 00001000
|
||||
#define SAM_5 0x310 // 0011 00010000
|
||||
#define SAM_ESC 0x320 // 0011 00100000
|
||||
#define SAM_TAB 0x340 // 0011 01000000
|
||||
#define SAM_CAPS 0x380 // 0011 10000000
|
||||
|
||||
#define SAM_0 0x401 // 0100 00000001
|
||||
#define SAM_9 0x402 // 0100 00000010
|
||||
#define SAM_8 0x404 // 0100 00000100
|
||||
#define SAM_7 0x408 // 0100 00001000
|
||||
#define SAM_6 0x410 // 0100 00010000
|
||||
#define SAM_MINUS 0x420 // 0100 00100000
|
||||
#define SAM_PLUS 0x440 // 0100 01000000
|
||||
#define SAM_DELETE 0x480 // 0100 10000000
|
||||
|
||||
#define SAM_Q 0x201 // 0010 00000001
|
||||
#define SAM_W 0x202 // 0010 00000010
|
||||
#define SAM_E 0x204 // 0010 00000100
|
||||
#define SAM_R 0x208 // 0010 00001000
|
||||
#define SAM_T 0x210 // 0010 00010000
|
||||
#define SAM_F7 0x220 // 0010 00100000
|
||||
#define SAM_F8 0x240 // 0010 01000000
|
||||
#define SAM_F9 0x280 // 0010 10000000
|
||||
|
||||
#define SAM_P 0x501 // 0101 00000001
|
||||
#define SAM_O 0x502 // 0101 00000010
|
||||
#define SAM_I 0x504 // 0101 00000100
|
||||
#define SAM_U 0x508 // 0101 00001000
|
||||
#define SAM_Y 0x510 // 0101 00010000
|
||||
#define SAM_EQUAL 0x520 // 0101 00100000
|
||||
#define SAM_QUOTE 0x540 // 0101 01000000
|
||||
#define SAM_F0 0x580 // 0101 10000000
|
||||
|
||||
#define SAM_A 0x101 // 0001 00000001
|
||||
#define SAM_S 0x102 // 0001 00000010
|
||||
#define SAM_D 0x104 // 0001 00000100
|
||||
#define SAM_F 0x108 // 0001 00001000
|
||||
#define SAM_G 0x110 // 0001 00010000
|
||||
#define SAM_F4 0x120 // 0001 00100000
|
||||
#define SAM_F5 0x140 // 0001 01000000
|
||||
#define SAM_F6 0x180 // 0001 10000000
|
||||
|
||||
#define SAM_RETURN 0x601 // 0110 00000001
|
||||
#define SAM_L 0x602 // 0110 00000010
|
||||
#define SAM_K 0x604 // 0110 00000100
|
||||
#define SAM_J 0x608 // 0110 00001000
|
||||
#define SAM_H 0x610 // 0110 00010000
|
||||
#define SAM_SEMICOL 0x620 //0110 00100000
|
||||
#define SAM_COLON 0x640 // 0110 01000000
|
||||
#define SAM_EDIT 0x680 // 0110 10000000
|
||||
|
||||
#define SAM_SHIFT 0x001 // 0000 00000001
|
||||
#define SAM_Z 0x002 // 0000 00000010
|
||||
#define SAM_X 0x004 // 0000 00000100
|
||||
#define SAM_C 0x008 // 0000 00001000
|
||||
#define SAM_V 0x010 // 0000 00010000
|
||||
#define SAM_F1 0x020 // 0000 00100000
|
||||
#define SAM_F2 0x040 // 0000 01000000
|
||||
#define SAM_F3 0x080 // 0000 10000000
|
||||
|
||||
#define SAM_SPACE 0x701 // 0111 00000001
|
||||
#define SAM_SYMBOL 0x702 // 0111 00000010
|
||||
#define SAM_M 0x704 // 0111 00000100
|
||||
#define SAM_N 0x708 // 0111 00001000
|
||||
#define SAM_B 0x710 // 0111 00010000
|
||||
#define SAM_COMMA 0x720 // 0111 00100000
|
||||
#define SAM_DOT 0x740 // 0111 01000000
|
||||
#define SAM_INV 0x780 // 0111 10000000
|
||||
|
||||
#define SAM_CTRL 0x801 // 1000 00000001
|
||||
#define SAM_UP 0x802 // 1000 00000010
|
||||
#define SAM_DOWN 0x804 // 1000 00000100
|
||||
#define SAM_LEFT 0x808 // 1000 00001000
|
||||
#define SAM_RIGHT 0x810 // 1000 00010000
|
||||
|
||||
#define SAM_BANG ((SAM_SHIFT<<12) | SAM_1)
|
||||
#define SAM_AT ((SAM_SHIFT<<12) | SAM_2)
|
||||
#define SAM_HASH ((SAM_SHIFT<<12) | SAM_3)
|
||||
#define SAM_DOLLAR ((SAM_SHIFT<<12) | SAM_4)
|
||||
#define SAM_PERCEN ((SAM_SHIFT<<12) | SAM_5)
|
||||
#define SAM_AMP ((SAM_SHIFT<<12) | SAM_6)
|
||||
#define SAM_APOSTRO ((SAM_SHIFT<<12) | SAM_7)
|
||||
#define SAM_PAROPEN ((SAM_SHIFT<<12) | SAM_8)
|
||||
#define SAM_PARCLOS ((SAM_SHIFT<<12) | SAM_9)
|
||||
#define SAM_TILDE ((SAM_SHIFT<<12) | SAM_0)
|
||||
#define SAM_SLASH ((SAM_SHIFT<<12) | SAM_MINUS)
|
||||
#define SAM_STAR ((SAM_SHIFT<<12) | SAM_PLUS)
|
||||
#define SAM_LESS ((SAM_SYMBOL<<12) | SAM_Q)
|
||||
#define SAM_GREATER ((SAM_SYMBOL<<12) | SAM_W)
|
||||
#define SAM_BRAOPEN ((SAM_SYMBOL<<12) | SAM_R)
|
||||
#define SAM_BRACLOS ((SAM_SYMBOL<<12) | SAM_T)
|
||||
#define SAM_UNDERSC ((SAM_SHIFT<<12) | SAM_EQUAL)
|
||||
#define SAM_COPY ((SAM_SHIFT<<12) | SAM_QUOTE)
|
||||
#define SAM_PIPE ((SAM_SYMBOL<<12) | SAM_9)
|
||||
#define SAM_BACKSLA ((SAM_SYMBOL<<12) | SAM_INV)
|
||||
#define SAM_CUROPEN ((SAM_SYMBOL<<12) | SAM_F)
|
||||
#define SAM_CURCLOS ((SAM_SYMBOL<<12) | SAM_G)
|
||||
#define SAM_CARET ((SAM_SYMBOL<<12) | SAM_H)
|
||||
#define SAM_POUND ((SAM_SYMBOL<<12) | SAM_L)
|
||||
#define SAM_QUEST ((SAM_SYMBOL<<12) | SAM_X)
|
||||
|
||||
// END of SAM Coupé key definitions
|
||||
|
||||
// Definitions for additional signals generated by the keyboard core
|
||||
// AAAADDDDDDDD AAAADDDDDDDD MRN MMM XX
|
||||
#define MODIFIER1 0x04
|
||||
#define MODIFIER2 0x08
|
||||
#define MODIFIER3 0x10
|
||||
|
||||
#define MRESET 0x80
|
||||
#define URESET 0x40
|
||||
#define NMI 0x20
|
||||
|
||||
#define USER2 0x02
|
||||
#define USER1 0x01
|
||||
// End of additional signals
|
||||
|
||||
// A key can be pressed with up to three key modifiers
|
||||
// which generates 8 combinations for each key
|
||||
#define EXT 0x100
|
||||
#define MD1 0x200
|
||||
#define MD2 0x400
|
||||
#define MD3 0x800
|
||||
|
||||
// Scan code 2 list. First, non localized keys
|
||||
#define PC_A 0x1C
|
||||
#define PC_B 0x32
|
||||
#define PC_C 0x21
|
||||
#define PC_D 0x23
|
||||
#define PC_E 0x24
|
||||
#define PC_F 0x2B
|
||||
#define PC_G 0x34
|
||||
#define PC_H 0x33
|
||||
#define PC_I 0x43
|
||||
#define PC_J 0x3B
|
||||
#define PC_K 0x42
|
||||
#define PC_L 0x4B
|
||||
#define PC_M 0x3A
|
||||
#define PC_N 0x31
|
||||
#define PC_O 0x44
|
||||
#define PC_P 0x4D
|
||||
#define PC_Q 0x15
|
||||
#define PC_R 0x2D
|
||||
#define PC_S 0x1B
|
||||
#define PC_T 0x2C
|
||||
#define PC_U 0x3C
|
||||
#define PC_V 0x2A
|
||||
#define PC_W 0x1D
|
||||
#define PC_X 0x22
|
||||
#define PC_Y 0x35
|
||||
#define PC_Z 0x1A
|
||||
|
||||
#define PC_0 0x45
|
||||
#define PC_1 0x16
|
||||
#define PC_2 0x1E
|
||||
#define PC_3 0x26
|
||||
#define PC_4 0x25
|
||||
#define PC_5 0x2E
|
||||
#define PC_6 0x36
|
||||
#define PC_7 0x3D
|
||||
#define PC_8 0x3E
|
||||
#define PC_9 0x46
|
||||
|
||||
#define PC_F1 0x05
|
||||
#define PC_F2 0x06
|
||||
#define PC_F3 0x04
|
||||
#define PC_F4 0x0C
|
||||
#define PC_F5 0x03
|
||||
#define PC_F6 0x0B
|
||||
#define PC_F7 0x83
|
||||
#define PC_F8 0x0A
|
||||
#define PC_F9 0x01
|
||||
#define PC_F10 0x09
|
||||
#define PC_F11 0x78
|
||||
#define PC_F12 0x07
|
||||
|
||||
#define PC_ESC 0x76
|
||||
#define PC_SPACE 0x29
|
||||
#define PC_LCTRL 0x14
|
||||
#define PC_RCTRL 0x14 | EXT
|
||||
#define PC_LSHIFT 0x12
|
||||
#define PC_RSHIFT 0x59
|
||||
#define PC_LALT 0x11
|
||||
#define PC_RALT 0x11 | EXT
|
||||
#define PC_LWIN 0x1F | EXT
|
||||
#define PC_RWIN 0x27 | EXT
|
||||
#define PC_APPS 0x2F | EXT
|
||||
|
||||
#define PC_TAB 0x0D
|
||||
#define PC_CPSLOCK 0x58
|
||||
#define PC_SCRLOCK 0x7E
|
||||
|
||||
#define PC_INSERT 0x70 | EXT
|
||||
#define PC_DELETE 0x71 | EXT
|
||||
#define PC_HOME 0x6C | EXT
|
||||
#define PC_END 0x69 | EXT
|
||||
#define PC_PGUP 0x7D | EXT
|
||||
#define PC_PGDOWN 0x7A | EXT
|
||||
#define PC_BKSPACE 0x66
|
||||
#define PC_ENTER 0x5A
|
||||
#define PC_UP 0x75 | EXT
|
||||
#define PC_DOWN 0x72 | EXT
|
||||
#define PC_LEFT 0x6B | EXT
|
||||
#define PC_RIGHT 0x74 | EXT
|
||||
|
||||
#define PC_NUMLOCK 0x77
|
||||
#define PC_KP_DIVIS 0x4A | EXT
|
||||
#define PC_KP_MULT 0x7C
|
||||
#define PC_KP_MINUS 0x7B
|
||||
#define PC_KP_PLUS 0x79
|
||||
#define PC_KP_ENTER 0x5A | EXT
|
||||
#define PC_KP_DOT 0x71
|
||||
#define PC_KP_0 0x70
|
||||
#define PC_KP_1 0x69
|
||||
#define PC_KP_2 0x72
|
||||
#define PC_KP_3 0x7A
|
||||
#define PC_KP_4 0x6B
|
||||
#define PC_KP_5 0x73
|
||||
#define PC_KP_6 0x74
|
||||
#define PC_KP_7 0x6C
|
||||
#define PC_KP_8 0x75
|
||||
#define PC_KP_9 0x7D
|
||||
|
||||
// Localized keyboards start to differenciate from here
|
||||
|
||||
// Localized keyboard ES (Spain)
|
||||
#define PC_BACKSLA 0x0E
|
||||
#define PC_APOSTRO 0x4E
|
||||
#define PC_OPNBANG 0x55
|
||||
#define PC_GRAVEAC 0x54
|
||||
#define PC_PLUS 0x5B
|
||||
#define PC_EGNE 0x4C
|
||||
#define PC_ACUTEAC 0x52
|
||||
#define PC_CEDILLA 0x5D
|
||||
#define PC_LESS 0x61
|
||||
#define PC_COMMA 0x41
|
||||
#define PC_DOT 0x49
|
||||
#define PC_MINUS 0x4A
|
||||
|
||||
#define MAP(pc,sam,rmu) { \
|
||||
rom[(pc)*4] = (((sam)>>16)&0xFF); \
|
||||
rom[(pc)*4+1] = (((sam)>>8)&0xFF); \
|
||||
rom[(pc)*4+2] = (((sam))&0xFF); \
|
||||
rom[(pc)*4+3] = (rmu); \
|
||||
}
|
||||
|
||||
#define MAPANY(pc,sam,rmu) { \
|
||||
MAP(pc,sam,rmu); \
|
||||
MAP(MD1|pc,sam,rmu); \
|
||||
MAP(MD2|pc,sam,rmu); \
|
||||
MAP(MD3|pc,sam,rmu); \
|
||||
MAP(MD1|MD2|pc,sam,rmu); \
|
||||
MAP(MD1|MD3|pc,sam,rmu); \
|
||||
MAP(MD2|MD3|pc,sam,rmu); \
|
||||
MAP(MD1|MD2|MD3|pc,sam,rmu); \
|
||||
}
|
||||
|
||||
#define CLEANMAP { \
|
||||
int i; \
|
||||
for (i=0;i<(sizeof(rom)/sizeof(rom[0]));i++) \
|
||||
rom[i] = 0; \
|
||||
}
|
||||
#define SAVEMAPHEX(name) { \
|
||||
FILE *f; \
|
||||
int i; \
|
||||
f=fopen(name,"w"); \
|
||||
for(i=0;i<(sizeof(rom)/sizeof(rom[0]));i++) \
|
||||
fprintf(f,"%.2X\n",rom[i]); \
|
||||
fclose(f); \
|
||||
}
|
||||
|
||||
#define SAVEMAPBIN(name) { \
|
||||
FILE *f; \
|
||||
int i; \
|
||||
f=fopen(name,"wb"); \
|
||||
fwrite (rom, 1, sizeof(rom), f); \
|
||||
fclose(f); \
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
BYTE rom[16384];
|
||||
|
||||
CLEANMAP;
|
||||
|
||||
MAPANY(PC_LSHIFT,0,MODIFIER1); // MD1 is SHIFT
|
||||
MAPANY(PC_RSHIFT,0,MODIFIER1); // MD1 is SHIFT
|
||||
MAPANY(PC_LCTRL,SAM_CTRL,MODIFIER2); // MD2 is CTRL
|
||||
MAPANY(PC_RCTRL,SAM_CTRL,MODIFIER2); // MD2 is CTRL
|
||||
MAPANY(PC_LALT,SAM_SHIFT,MODIFIER3); // MD3 is ALT.
|
||||
MAPANY(PC_RALT,SAM_SYMBOL,MODIFIER3); // MD3 is ALT.
|
||||
|
||||
MAPANY(PC_RWIN,SAM_EDIT,0); // EDIT key
|
||||
|
||||
// Basic mapping: each key from PC is mapped to a key in the SAM
|
||||
MAP(PC_1,SAM_1,0);
|
||||
MAP(PC_2,SAM_2,0);
|
||||
MAP(PC_3,SAM_3,0);
|
||||
MAP(PC_4,SAM_4,0);
|
||||
MAP(PC_5,SAM_5,0);
|
||||
MAP(PC_6,SAM_6,0);
|
||||
MAP(PC_7,SAM_7,0);
|
||||
MAP(PC_8,SAM_8,0);
|
||||
MAP(PC_9,SAM_9,0);
|
||||
MAP(PC_0,SAM_0,0);
|
||||
|
||||
MAP(PC_Q,SAM_Q,0);
|
||||
MAP(PC_W,SAM_W,0);
|
||||
MAP(PC_E,SAM_E,0);
|
||||
MAP(PC_R,SAM_R,0);
|
||||
MAP(PC_T,SAM_T,0);
|
||||
MAP(PC_Y,SAM_Y,0);
|
||||
MAP(PC_U,SAM_U,0);
|
||||
MAP(PC_I,SAM_I,0);
|
||||
MAP(PC_O,SAM_O,0);
|
||||
MAP(PC_P,SAM_P,0);
|
||||
MAP(PC_A,SAM_A,0);
|
||||
MAP(PC_S,SAM_S,0);
|
||||
MAP(PC_D,SAM_D,0);
|
||||
MAP(PC_F,SAM_F,0);
|
||||
MAP(PC_G,SAM_G,0);
|
||||
MAP(PC_H,SAM_H,0);
|
||||
MAP(PC_J,SAM_J,0);
|
||||
MAP(PC_K,SAM_K,0);
|
||||
MAP(PC_L,SAM_L,0);
|
||||
MAP(PC_Z,SAM_Z,0);
|
||||
MAP(PC_X,SAM_X,0);
|
||||
MAP(PC_C,SAM_C,0);
|
||||
MAP(PC_V,SAM_V,0);
|
||||
MAP(PC_B,SAM_B,0);
|
||||
MAP(PC_N,SAM_N,0);
|
||||
MAP(PC_M,SAM_M,0);
|
||||
|
||||
MAP(MD1|PC_Q,SAM_SHIFT<<12|SAM_Q,0);
|
||||
MAP(MD1|PC_W,SAM_SHIFT<<12|SAM_W,0);
|
||||
MAP(MD1|PC_E,SAM_SHIFT<<12|SAM_E,0);
|
||||
MAP(MD1|PC_R,SAM_SHIFT<<12|SAM_R,0);
|
||||
MAP(MD1|PC_T,SAM_SHIFT<<12|SAM_T,0);
|
||||
MAP(MD1|PC_Y,SAM_SHIFT<<12|SAM_Y,0);
|
||||
MAP(MD1|PC_U,SAM_SHIFT<<12|SAM_U,0);
|
||||
MAP(MD1|PC_I,SAM_SHIFT<<12|SAM_I,0);
|
||||
MAP(MD1|PC_O,SAM_SHIFT<<12|SAM_O,0);
|
||||
MAP(MD1|PC_P,SAM_SHIFT<<12|SAM_P,0);
|
||||
MAP(MD1|PC_A,SAM_SHIFT<<12|SAM_A,0);
|
||||
MAP(MD1|PC_S,SAM_SHIFT<<12|SAM_S,0);
|
||||
MAP(MD1|PC_D,SAM_SHIFT<<12|SAM_D,0);
|
||||
MAP(MD1|PC_F,SAM_SHIFT<<12|SAM_F,0);
|
||||
MAP(MD1|PC_G,SAM_SHIFT<<12|SAM_G,0);
|
||||
MAP(MD1|PC_H,SAM_SHIFT<<12|SAM_H,0);
|
||||
MAP(MD1|PC_J,SAM_SHIFT<<12|SAM_J,0);
|
||||
MAP(MD1|PC_K,SAM_SHIFT<<12|SAM_K,0);
|
||||
MAP(MD1|PC_L,SAM_SHIFT<<12|SAM_L,0);
|
||||
MAP(MD1|PC_Z,SAM_SHIFT<<12|SAM_Z,0);
|
||||
MAP(MD1|PC_X,SAM_SHIFT<<12|SAM_X,0);
|
||||
MAP(MD1|PC_C,SAM_SHIFT<<12|SAM_C,0);
|
||||
MAP(MD1|PC_V,SAM_SHIFT<<12|SAM_V,0);
|
||||
MAP(MD1|PC_B,SAM_SHIFT<<12|SAM_B,0);
|
||||
MAP(MD1|PC_N,SAM_SHIFT<<12|SAM_N,0);
|
||||
MAP(MD1|PC_M,SAM_SHIFT<<12|SAM_M,0);
|
||||
|
||||
MAPANY(PC_SPACE,SAM_SPACE,0);
|
||||
MAPANY(PC_ENTER,SAM_RETURN,0);
|
||||
|
||||
//Complex mapping. This is for the spanish keyboard although many
|
||||
//combos can be used with any other PC keyboard
|
||||
MAPANY(PC_ESC,SAM_ESC,0);
|
||||
MAPANY(PC_CPSLOCK,SAM_CAPS,0);
|
||||
MAPANY(PC_TAB,SAM_TAB,0);
|
||||
MAP(PC_BKSPACE,SAM_DELETE,0);
|
||||
MAPANY(PC_UP,SAM_UP,0);
|
||||
MAPANY(PC_DOWN,SAM_DOWN,0);
|
||||
MAPANY(PC_LEFT,SAM_LEFT,0);
|
||||
MAPANY(PC_RIGHT,SAM_RIGHT,0);
|
||||
|
||||
MAP(PC_F5|MD2|MD3,0,NMI); // Ctrl-Alt-F5 for NMI
|
||||
MAP(PC_DELETE|MD2|MD3,0,URESET); //
|
||||
MAP(PC_KP_DOT|MD2|MD3,0,URESET); // Ctrl-Alt-Del for user reset
|
||||
MAP(PC_BKSPACE|MD2|MD3,0,MRESET); // Ctrl-Alt-BkSpace for master reset
|
||||
|
||||
//keypad
|
||||
MAPANY(PC_KP_DIVIS,SAM_SLASH,0);
|
||||
MAPANY(PC_KP_MULT,SAM_STAR,0);
|
||||
MAPANY(PC_KP_MINUS,SAM_MINUS,0);
|
||||
MAPANY(PC_KP_PLUS,SAM_PLUS,0);
|
||||
MAPANY(PC_KP_ENTER,SAM_RETURN,0);
|
||||
MAPANY(PC_KP_0,SAM_F0,0);
|
||||
MAPANY(PC_KP_1,SAM_F1,0);
|
||||
MAPANY(PC_KP_2,SAM_F2,0);
|
||||
MAPANY(PC_KP_3,SAM_F3,0);
|
||||
MAPANY(PC_KP_4,SAM_F4,0);
|
||||
MAPANY(PC_KP_5,SAM_F5,0);
|
||||
MAPANY(PC_KP_6,SAM_F6,0);
|
||||
MAPANY(PC_KP_7,SAM_F7,0);
|
||||
MAPANY(PC_KP_8,SAM_F8,0);
|
||||
MAPANY(PC_KP_9,SAM_F9,0);
|
||||
|
||||
//Some shift+key mappings for the ES keyboard
|
||||
MAP(MD1|PC_1,SAM_BANG,0);
|
||||
MAP(MD1|PC_2,SAM_QUOTE,0);
|
||||
MAP(MD1|PC_3,SAM_HASH,0);
|
||||
MAP(MD1|PC_4,SAM_DOLLAR,0);
|
||||
MAP(MD1|PC_5,SAM_PERCEN,0);
|
||||
MAP(MD1|PC_6,SAM_AMP,0);
|
||||
MAP(MD1|PC_7,SAM_SLASH,0);
|
||||
MAP(MD1|PC_8,SAM_PAROPEN,0);
|
||||
MAP(MD1|PC_9,SAM_PARCLOS,0);
|
||||
MAP(MD1|PC_0,SAM_EQUAL,0);
|
||||
MAP(PC_APOSTRO,SAM_APOSTRO,0);
|
||||
MAP(MD1|PC_APOSTRO,SAM_QUEST,0);
|
||||
MAP(PC_GRAVEAC,SAM_POUND,0);
|
||||
MAP(MD1|PC_GRAVEAC,SAM_CARET,0);
|
||||
MAP(PC_PLUS,SAM_PLUS,0);
|
||||
MAP(MD1|PC_PLUS,SAM_STAR,0);
|
||||
MAP(PC_ACUTEAC,SAM_CUROPEN,0);
|
||||
MAP(MD1|PC_ACUTEAC,SAM_CUROPEN,0);
|
||||
MAP(PC_ACUTEAC,SAM_CUROPEN,0);
|
||||
MAP(MD1|PC_ACUTEAC,SAM_CUROPEN,0);
|
||||
MAP(PC_CEDILLA,SAM_CURCLOS,0);
|
||||
MAP(MD1|PC_CEDILLA,SAM_COPY,0);
|
||||
MAP(PC_COMMA,SAM_COMMA,0);
|
||||
MAP(MD1|PC_COMMA,SAM_SEMICOL,0);
|
||||
MAP(PC_DOT,SAM_DOT,0);
|
||||
MAP(MD1|PC_DOT,SAM_COLON,0);
|
||||
MAP(PC_MINUS,SAM_MINUS,0);
|
||||
MAP(MD1|PC_MINUS,SAM_UNDERSC,0);
|
||||
MAP(PC_BACKSLA,SAM_BACKSLA,0);
|
||||
MAP(MD1|PC_BACKSLA,SAM_BACKSLA,0);
|
||||
MAP(PC_EGNE,SAM_TILDE,0);
|
||||
MAP(PC_LESS,SAM_LESS,0);
|
||||
MAP(MD1|PC_LESS,SAM_GREATER,0);
|
||||
|
||||
// End of mapping. Save .HEX file for Verilog
|
||||
SAVEMAPHEX("keyb_es_hex.txt");
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,126 @@
|
|||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Company:
|
||||
// Engineer:
|
||||
//
|
||||
// Create Date: 15:18:53 06/03/2015
|
||||
// Design Name:
|
||||
// Module Name: ps2_keyb
|
||||
// Project Name:
|
||||
// Target Devices:
|
||||
// Tool versions:
|
||||
// Description:
|
||||
//
|
||||
// Dependencies:
|
||||
//
|
||||
// Revision:
|
||||
// Revision 0.01 - File Created
|
||||
// Additional Comments:
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
module ps2_keyb(
|
||||
input wire clk,
|
||||
inout wire clkps2,
|
||||
inout wire dataps2,
|
||||
//---------------------------------
|
||||
input wire [8:0] rows,
|
||||
output wire [7:0] cols,
|
||||
output wire rst_out_n,
|
||||
output wire nmi_out_n,
|
||||
output wire mrst_out_n,
|
||||
output wire [1:0] user_toggles,
|
||||
//---------------------------------
|
||||
input wire [7:0] zxuno_addr,
|
||||
input wire zxuno_regrd,
|
||||
input wire zxuno_regwr,
|
||||
input wire regaddr_changed,
|
||||
input wire [7:0] din,
|
||||
output wire [7:0] keymap_dout,
|
||||
output wire oe_n_keymap,
|
||||
output wire [7:0] scancode_dout,
|
||||
output wire oe_n_scancode,
|
||||
output reg [7:0] kbstatus_dout,
|
||||
output wire oe_n_kbstatus
|
||||
);
|
||||
|
||||
parameter SCANCODE = 8'h04;
|
||||
parameter KBSTATUS = 8'h05;
|
||||
parameter KEYMAP = 8'h07;
|
||||
|
||||
wire master_reset, user_reset, user_nmi;
|
||||
assign mrst_out_n = ~master_reset;
|
||||
assign rst_out_n = ~user_reset;
|
||||
assign nmi_out_n = ~user_nmi;
|
||||
|
||||
assign oe_n_keymap = ~(zxuno_addr == KEYMAP && zxuno_regrd == 1'b1);
|
||||
assign oe_n_scancode = ~(zxuno_addr == SCANCODE && zxuno_regrd == 1'b1);
|
||||
assign oe_n_kbstatus = ~(zxuno_addr == KBSTATUS && zxuno_regrd == 1'b1);
|
||||
|
||||
wire [7:0] kbcode;
|
||||
wire ps2busy;
|
||||
wire kberror;
|
||||
wire nueva_tecla;
|
||||
wire extended;
|
||||
wire released;
|
||||
assign scancode_dout = kbcode;
|
||||
|
||||
/*
|
||||
| BSY | x | x | x | ERR | RLS | EXT | PEN |
|
||||
*/
|
||||
reg reading_kbstatus = 1'b0;
|
||||
always @(posedge clk) begin
|
||||
kbstatus_dout[7:1] <= {ps2busy, 3'b000, kberror, released, extended};
|
||||
if (nueva_tecla == 1'b1)
|
||||
kbstatus_dout[0] <= 1'b1;
|
||||
if (oe_n_kbstatus == 1'b0)
|
||||
reading_kbstatus <= 1'b1;
|
||||
else if (reading_kbstatus == 1'b1) begin
|
||||
kbstatus_dout[0] <= 1'b0;
|
||||
reading_kbstatus <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
ps2_port lectura_de_teclado (
|
||||
.clk(clk),
|
||||
.enable_rcv(~ps2busy),
|
||||
.kb_or_mouse(1'b0),
|
||||
.ps2clk_ext(clkps2),
|
||||
.ps2data_ext(dataps2),
|
||||
.kb_interrupt(nueva_tecla),
|
||||
.scancode(kbcode),
|
||||
.released(released),
|
||||
.extended(extended)
|
||||
);
|
||||
|
||||
scancode_to_sam traductor (
|
||||
.clk(clk),
|
||||
.rst(1'b0),
|
||||
.scan_received(nueva_tecla),
|
||||
.scan(kbcode),
|
||||
.extended(extended),
|
||||
.released(released),
|
||||
.sam_row(rows),
|
||||
.sam_col(cols),
|
||||
.master_reset(master_reset),
|
||||
.user_reset(user_reset),
|
||||
.user_nmi(user_nmi),
|
||||
.user_toggles(user_toggles),
|
||||
.din(din),
|
||||
.dout(keymap_dout),
|
||||
.cpuwrite(zxuno_addr == KEYMAP && zxuno_regwr == 1'b1),
|
||||
.cpuread(zxuno_addr == KEYMAP && zxuno_regrd == 1'b1),
|
||||
.rewind(regaddr_changed == 1'b1 && zxuno_addr == KEYMAP)
|
||||
);
|
||||
|
||||
ps2_host_to_kb escritura_a_teclado (
|
||||
.clk(clk),
|
||||
.ps2clk_ext(clkps2),
|
||||
.ps2data_ext(dataps2),
|
||||
.data(din),
|
||||
.dataload(zxuno_addr == SCANCODE && zxuno_regwr== 1'b1),
|
||||
.ps2busy(ps2busy),
|
||||
.ps2error(kberror)
|
||||
);
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,275 @@
|
|||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Company:
|
||||
// Engineer:
|
||||
//
|
||||
// Create Date: 20:16:31 12/26/2014
|
||||
// Design Name:
|
||||
// Module Name: ps2_port
|
||||
// Project Name:
|
||||
// Target Devices:
|
||||
// Tool versions:
|
||||
// Description:
|
||||
//
|
||||
// Dependencies:
|
||||
//
|
||||
// Revision:
|
||||
// Revision 0.01 - File Created
|
||||
// Additional Comments:
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
module ps2_port (
|
||||
input wire clk, // se recomienda 1 MHz <= clk <= 600 MHz
|
||||
input wire enable_rcv, // habilitar la maquina de estados de recepcion
|
||||
input wire kb_or_mouse, // 0: kb, 1: mouse
|
||||
input wire ps2clk_ext,
|
||||
input wire ps2data_ext,
|
||||
output wire kb_interrupt, // a 1 durante 1 clk para indicar nueva tecla recibida
|
||||
output reg [7:0] scancode, // make o breakcode de la tecla
|
||||
output wire released, // soltada=1, pulsada=0
|
||||
output wire extended // extendida=1, no extendida=0
|
||||
);
|
||||
|
||||
`define RCVSTART 2'b00
|
||||
`define RCVDATA 2'b01
|
||||
`define RCVPARITY 2'b10
|
||||
`define RCVSTOP 2'b11
|
||||
|
||||
reg [7:0] key = 8'h00;
|
||||
|
||||
// Fase de sincronizacion de señales externas con el reloj del sistema
|
||||
reg [1:0] ps2clk_synchr;
|
||||
reg [1:0] ps2dat_synchr;
|
||||
wire ps2clk = ps2clk_synchr[1];
|
||||
wire ps2data = ps2dat_synchr[1];
|
||||
always @(posedge clk) begin
|
||||
ps2clk_synchr[0] <= ps2clk_ext;
|
||||
ps2clk_synchr[1] <= ps2clk_synchr[0];
|
||||
ps2dat_synchr[0] <= ps2data_ext;
|
||||
ps2dat_synchr[1] <= ps2dat_synchr[0];
|
||||
end
|
||||
|
||||
// De-glitcher. Sólo detecto flanco de bajada
|
||||
reg [15:0] negedgedetect = 16'h0000;
|
||||
always @(posedge clk) begin
|
||||
negedgedetect <= {negedgedetect[14:0], ps2clk};
|
||||
end
|
||||
wire ps2clkedge = (negedgedetect == 16'hF000)? 1'b1 : 1'b0;
|
||||
|
||||
// Paridad instantánea de los bits recibidos
|
||||
wire paritycalculated = ^key;
|
||||
|
||||
// Contador de time-out. Al llegar a 65536 ciclos sin que ocurra
|
||||
// un flanco de bajada en PS2CLK, volvemos al estado inicial
|
||||
reg [15:0] timeoutcnt = 16'h0000;
|
||||
|
||||
reg [1:0] state = `RCVSTART;
|
||||
reg [1:0] regextended = 2'b00;
|
||||
reg [1:0] regreleased = 2'b00;
|
||||
reg rkb_interrupt = 1'b0;
|
||||
assign released = regreleased[1];
|
||||
assign extended = regextended[1];
|
||||
assign kb_interrupt = rkb_interrupt;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rkb_interrupt == 1'b1) begin
|
||||
rkb_interrupt <= 1'b0;
|
||||
end
|
||||
if (ps2clkedge && enable_rcv) begin
|
||||
timeoutcnt <= 16'h0000;
|
||||
case (state)
|
||||
`RCVSTART: begin
|
||||
if (ps2data == 1'b0) begin
|
||||
state <= `RCVDATA;
|
||||
key <= 8'h80;
|
||||
end
|
||||
end
|
||||
`RCVDATA: begin
|
||||
key <= {ps2data, key[7:1]};
|
||||
if (key[0] == 1'b1) begin
|
||||
state <= `RCVPARITY;
|
||||
end
|
||||
end
|
||||
`RCVPARITY: begin
|
||||
if (ps2data^paritycalculated == 1'b1) begin
|
||||
state <= `RCVSTOP;
|
||||
end
|
||||
else begin
|
||||
state <= `RCVSTART;
|
||||
end
|
||||
end
|
||||
`RCVSTOP: begin
|
||||
state <= `RCVSTART;
|
||||
if (ps2data == 1'b1) begin
|
||||
scancode <= key;
|
||||
if (kb_or_mouse == 1'b1) begin
|
||||
rkb_interrupt <= 1'b1; // no se requiere mirar E0 o F0
|
||||
end
|
||||
else begin
|
||||
if (key == 8'hE0) begin
|
||||
regextended <= 2'b01;
|
||||
end
|
||||
else if (key == 8'hF0) begin
|
||||
regreleased <= 2'b01;
|
||||
end
|
||||
else begin
|
||||
regextended <= {regextended[0], 1'b0};
|
||||
regreleased <= {regreleased[0], 1'b0};
|
||||
rkb_interrupt <= 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
default: state <= `RCVSTART;
|
||||
endcase
|
||||
end
|
||||
else begin
|
||||
timeoutcnt <= timeoutcnt + 1;
|
||||
if (timeoutcnt == 16'hFFFF) begin
|
||||
state <= `RCVSTART;
|
||||
end
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
||||
module ps2_host_to_kb (
|
||||
input wire clk, // se recomienda 1 MHz <= clk <= 600 MHz
|
||||
inout wire ps2clk_ext,
|
||||
inout wire ps2data_ext,
|
||||
input wire [7:0] data,
|
||||
input wire dataload,
|
||||
output wire ps2busy,
|
||||
output wire ps2error
|
||||
);
|
||||
|
||||
`define PULLCLKLOW 3'b000
|
||||
`define PULLDATALOW 3'b001
|
||||
`define SENDDATA 3'b010
|
||||
`define SENDPARITY 3'b011
|
||||
`define RCVACK 3'b100
|
||||
`define RCVIDLE 3'b101
|
||||
`define SENDFINISHED 3'b110
|
||||
|
||||
reg busy = 1'b0;
|
||||
reg error = 1'b0;
|
||||
assign ps2busy = busy;
|
||||
assign ps2error = error;
|
||||
|
||||
// Fase de sincronizacion de señales externas con el reloj del sistema
|
||||
reg [1:0] ps2clk_synchr;
|
||||
reg [1:0] ps2dat_synchr;
|
||||
wire ps2clk = ps2clk_synchr[1];
|
||||
wire ps2data_in = ps2dat_synchr[1];
|
||||
always @(posedge clk) begin
|
||||
ps2clk_synchr[0] <= ps2clk_ext;
|
||||
ps2clk_synchr[1] <= ps2clk_synchr[0];
|
||||
ps2dat_synchr[0] <= ps2data_ext;
|
||||
ps2dat_synchr[1] <= ps2dat_synchr[0];
|
||||
end
|
||||
|
||||
// De-glitcher. Sólo detecto flanco de bajada
|
||||
reg [15:0] edgedetect = 16'h0000;
|
||||
always @(posedge clk) begin
|
||||
edgedetect <= {edgedetect[14:0], ps2clk};
|
||||
end
|
||||
wire ps2clknedge = (edgedetect == 16'hF000)? 1'b1 : 1'b0;
|
||||
wire ps2clkpedge = (edgedetect == 16'h0FFF)? 1'b1 : 1'b0;
|
||||
|
||||
// Contador de time-out. Al llegar a 65536 ciclos sin que ocurra
|
||||
// un flanco de bajada en PS2CLK, volvemos al estado inicial
|
||||
reg [15:0] timeoutcnt = 16'h0000;
|
||||
|
||||
reg [2:0] state = `SENDFINISHED;
|
||||
reg [7:0] shiftreg = 8'h00;
|
||||
reg [2:0] cntbits = 3'd0;
|
||||
|
||||
// Dato a enviar se guarda en rdata
|
||||
reg [7:0] rdata = 8'h00;
|
||||
|
||||
// Paridad instantánea de los bits a enviar
|
||||
wire paritycalculated = ~(^rdata);
|
||||
|
||||
always @(posedge clk) begin
|
||||
// Carga de rdata desde el exterior
|
||||
if (dataload) begin
|
||||
rdata <= data;
|
||||
busy <= 1'b1;
|
||||
error <= 1'b0;
|
||||
timeoutcnt <= 16'h0000;
|
||||
state <= `PULLCLKLOW;
|
||||
end
|
||||
|
||||
if (!ps2clknedge) begin
|
||||
timeoutcnt <= timeoutcnt + 1;
|
||||
if (timeoutcnt == 16'hFFFF && state != `SENDFINISHED) begin
|
||||
error <= 1'b1;
|
||||
state <= `SENDFINISHED;
|
||||
end
|
||||
end
|
||||
|
||||
case (state)
|
||||
`PULLCLKLOW: begin // 40000 cuentas es poco más de 10ms
|
||||
if (timeoutcnt >= 16'd40000) begin
|
||||
state <= `PULLDATALOW;
|
||||
shiftreg <= rdata;
|
||||
cntbits <= 3'd0;
|
||||
timeoutcnt <= 16'h0000;
|
||||
end
|
||||
end
|
||||
`PULLDATALOW: begin
|
||||
if (ps2clknedge) begin
|
||||
state <= `SENDDATA;
|
||||
timeoutcnt <= 16'h0000;
|
||||
end
|
||||
end
|
||||
`SENDDATA: begin
|
||||
if (ps2clknedge) begin
|
||||
timeoutcnt <= 16'h0000;
|
||||
shiftreg <= {1'b0, shiftreg[7:1]};
|
||||
cntbits <= cntbits + 1;
|
||||
if (cntbits == 3'd7)
|
||||
state <= `SENDPARITY;
|
||||
end
|
||||
end
|
||||
`SENDPARITY: begin
|
||||
if (ps2clknedge) begin
|
||||
state <= `RCVIDLE;
|
||||
timeoutcnt <= 16'h0000;
|
||||
end
|
||||
end
|
||||
`RCVIDLE: begin
|
||||
if (ps2clknedge) begin
|
||||
state <= `RCVACK;
|
||||
timeoutcnt <= 16'h0000;
|
||||
end
|
||||
end
|
||||
`RCVACK: begin
|
||||
if (ps2clknedge) begin
|
||||
state <= `SENDFINISHED;
|
||||
timeoutcnt <= 16'h0000;
|
||||
end
|
||||
end
|
||||
`SENDFINISHED: begin
|
||||
busy <= 1'b0;
|
||||
timeoutcnt <= 16'h0000;
|
||||
end
|
||||
default: begin
|
||||
timeoutcnt <= timeoutcnt + 1;
|
||||
if (timeoutcnt == 16'hFFFF && state != `SENDFINISHED) begin
|
||||
error <= 1'b1;
|
||||
state <= `SENDFINISHED;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
assign ps2data_ext = (state == `PULLCLKLOW || state == `PULLDATALOW) ? 1'b0 :
|
||||
(state == `SENDDATA && shiftreg[0] == 1'b0) ? 1'b0 :
|
||||
(state == `SENDPARITY && paritycalculated == 1'b0) ? 1'b0 : // si lo que se va a enviar es un 1
|
||||
1'bZ; // no se manda, sino que se pone la línea a alta impedancia
|
||||
assign ps2clk_ext = (state == `PULLCLKLOW) ? 1'b0 :
|
||||
1'bZ;
|
||||
endmodule
|
||||
|
|
@ -140,9 +140,9 @@ module ram_dual_port (
|
|||
sram_we_n = 1'b1;
|
||||
end
|
||||
else begin
|
||||
sram_a = cpuramaddr;
|
||||
sram_a = cpuramaddr;
|
||||
data_to_cpu = sram_d;
|
||||
if (state == CPU5 || state == CPU6)
|
||||
if (state == CPU6 || state == CPU5)
|
||||
sram_we_n = 1'b0;
|
||||
else
|
||||
sram_we_n = 1'b1;
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ module samcoupe (
|
|||
output wire audio_out_left,
|
||||
output wire audio_out_right,
|
||||
// PS/2 keyoard interface
|
||||
input wire clkps2,
|
||||
input wire dataps2,
|
||||
inout wire clkps2,
|
||||
inout wire dataps2,
|
||||
// SRAM interface
|
||||
output wire [18:0] sram_addr,
|
||||
inout wire [7:0] sram_data,
|
||||
|
|
@ -82,7 +82,7 @@ module samcoupe (
|
|||
|
||||
// Audio signals
|
||||
wire mic, beep;
|
||||
assign audio_out_left = mic;
|
||||
assign audio_out_left = ear;
|
||||
assign audio_out_right = beep;
|
||||
|
||||
// MUX from memory/devices to Z80 data bus
|
||||
|
|
@ -138,7 +138,7 @@ module samcoupe (
|
|||
.mic(mic),
|
||||
.beep(beep),
|
||||
// keyboard I/O
|
||||
.keyboard({3'b111,kbcolumns[4:0]}),
|
||||
.keyboard(kbcolumns),
|
||||
.rdmsel(rdmsel),
|
||||
// disk I/O
|
||||
.disc1_n(),
|
||||
|
|
@ -191,17 +191,41 @@ module samcoupe (
|
|||
.sram_d(sram_data)
|
||||
);
|
||||
|
||||
ps2k el_teclado (
|
||||
.clk(clk6),
|
||||
.ps2clk(clkps2),
|
||||
.ps2data(dataps2),
|
||||
.rows(kbrows[7:0]),
|
||||
.cols(kbcolumns[4:0]),
|
||||
.joy(), // Implementación joystick kempston en teclado numerico
|
||||
.scancode(), // El scancode original desde el teclado
|
||||
.rst(kb_rst_n), // esto son salidas, no entradas
|
||||
.nmi(kb_nmi_n), // Señales de reset y NMI
|
||||
.mrst() // generadas por pulsaciones especiales del teclado
|
||||
);
|
||||
// ps2k el_teclado (
|
||||
// .clk(clk6),
|
||||
// .ps2clk(clkps2),
|
||||
// .ps2data(dataps2),
|
||||
// .rows(kbrows[7:0]),
|
||||
// .cols(kbcolumns[4:0]),
|
||||
// .joy(), // Implementación joystick kempston en teclado numerico
|
||||
// .scancode(), // El scancode original desde el teclado
|
||||
// .rst(kb_rst_n), // esto son salidas, no entradas
|
||||
// .nmi(kb_nmi_n), // Señales de reset y NMI
|
||||
// .mrst() // generadas por pulsaciones especiales del teclado
|
||||
// );
|
||||
|
||||
ps2_keyb el_teclado (
|
||||
.clk(clk6),
|
||||
.clkps2(clkps2),
|
||||
.dataps2(dataps2),
|
||||
//---------------------------------
|
||||
.rows(kbrows),
|
||||
.cols(kbcolumns),
|
||||
.rst_out_n(kb_rst_n),
|
||||
.nmi_out_n(kb_nmi_n),
|
||||
.mrst_out_n(),
|
||||
.user_toggles(),
|
||||
//---------------------------------
|
||||
.zxuno_addr(8'h00),
|
||||
.zxuno_regrd(1'b0),
|
||||
.zxuno_regwr(1'b0),
|
||||
.regaddr_changed(1'b0),
|
||||
.din(data_from_cpu),
|
||||
.keymap_dout(),
|
||||
.oe_n_keymap(),
|
||||
.scancode_dout(),
|
||||
.oe_n_scancode(),
|
||||
.kbstatus_dout(),
|
||||
.oe_n_kbstatus()
|
||||
);
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -43,14 +43,6 @@
|
|||
<file xil_pn:name="pines_zxuno.ucf" xil_pn:type="FILE_UCF">
|
||||
<association xil_pn:name="Implementation"/>
|
||||
</file>
|
||||
<file xil_pn:name="mapa_teclado_es.vhd" xil_pn:type="FILE_VHDL">
|
||||
<association xil_pn:name="BehavioralSimulation"/>
|
||||
<association xil_pn:name="Implementation"/>
|
||||
</file>
|
||||
<file xil_pn:name="ps2k.vhd" xil_pn:type="FILE_VHDL">
|
||||
<association xil_pn:name="BehavioralSimulation"/>
|
||||
<association xil_pn:name="Implementation"/>
|
||||
</file>
|
||||
<file xil_pn:name="relojes.v" xil_pn:type="FILE_VERILOG">
|
||||
<association xil_pn:name="BehavioralSimulation"/>
|
||||
<association xil_pn:name="Implementation"/>
|
||||
|
|
@ -81,6 +73,18 @@
|
|||
<association xil_pn:name="BehavioralSimulation"/>
|
||||
<association xil_pn:name="Implementation"/>
|
||||
</file>
|
||||
<file xil_pn:name="ps2_keyb.v" xil_pn:type="FILE_VERILOG">
|
||||
<association xil_pn:name="BehavioralSimulation"/>
|
||||
<association xil_pn:name="Implementation"/>
|
||||
</file>
|
||||
<file xil_pn:name="ps2_port.v" xil_pn:type="FILE_VERILOG">
|
||||
<association xil_pn:name="BehavioralSimulation"/>
|
||||
<association xil_pn:name="Implementation"/>
|
||||
</file>
|
||||
<file xil_pn:name="scancode_to_speccy.v" xil_pn:type="FILE_VERILOG">
|
||||
<association xil_pn:name="BehavioralSimulation"/>
|
||||
<association xil_pn:name="Implementation"/>
|
||||
</file>
|
||||
</files>
|
||||
|
||||
<properties>
|
||||
|
|
@ -107,7 +111,7 @@
|
|||
<property xil_pn:name="Change Device Speed To" xil_pn:value="-2" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Change Device Speed To Post Trace" xil_pn:value="-2" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Combinatorial Logic Optimization" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Compile EDK Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Compile EDK Simulation Library" xil_pn:value="true" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Compile SIMPRIM (Timing) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Compile UNISIM (Functional) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Compile XilinxCoreLib (CORE Generator) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,269 @@
|
|||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Company:
|
||||
// Engineer:
|
||||
//
|
||||
// Create Date: 17:42:40 06/01/2015
|
||||
// Design Name:
|
||||
// Module Name: scancode_to_speccy
|
||||
// Project Name:
|
||||
// Target Devices:
|
||||
// Tool versions:
|
||||
// Description:
|
||||
//
|
||||
// Dependencies:
|
||||
//
|
||||
// Revision:
|
||||
// Revision 0.01 - File Created
|
||||
// Additional Comments:
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
module scancode_to_sam (
|
||||
input wire clk, // el mismo clk de ps/2
|
||||
input wire rst,
|
||||
input wire scan_received,
|
||||
input wire [7:0] scan,
|
||||
input wire extended,
|
||||
input wire released,
|
||||
//------------------------
|
||||
input wire [8:0] sam_row,
|
||||
output wire [7:0] sam_col,
|
||||
output wire user_reset,
|
||||
output wire master_reset,
|
||||
output wire user_nmi,
|
||||
output wire [1:0] user_toggles,
|
||||
//------------------------
|
||||
input wire [7:0] din,
|
||||
output reg [7:0] dout,
|
||||
input wire cpuwrite,
|
||||
input wire cpuread,
|
||||
input wire rewind
|
||||
);
|
||||
|
||||
// las teclas del SAM. Se inicializan a "no pulsadas".
|
||||
reg [7:0] row[0:8];
|
||||
initial begin
|
||||
row[0] = 8'hFF;
|
||||
row[1] = 8'hFF;
|
||||
row[2] = 8'hFF;
|
||||
row[3] = 8'hFF;
|
||||
row[4] = 8'hFF;
|
||||
row[5] = 8'hFF;
|
||||
row[6] = 8'hFF;
|
||||
row[7] = 8'hFF;
|
||||
row[8] = 8'hFF;
|
||||
end
|
||||
|
||||
// El gran mapa de teclado y sus registros de acceso
|
||||
reg [7:0] keymap[0:16383]; // 16K x 8 bits
|
||||
reg [13:0] addr = 14'h0000;
|
||||
reg [13:0] cpuaddr = 14'h0000; // Dirección E/S desde la CPU. Se autoincrementa en cada acceso
|
||||
initial begin
|
||||
$readmemh ("keyb_es_hex.txt", keymap);
|
||||
end
|
||||
|
||||
reg [3:0] keyrow1 = 4'h0;
|
||||
reg [7:0] keycol1 = 8'h00;
|
||||
reg [3:0] keyrow2 = 4'h0;
|
||||
reg [7:0] keycol2 = 8'h00;
|
||||
reg [2:0] keymodifiers = 3'b000;
|
||||
reg [2:0] signalstate = 3'b000;
|
||||
reg [1:0] togglestate = 2'b00;
|
||||
|
||||
reg rmaster_reset = 1'b0, ruser_reset = 1'b0, ruser_nmi = 1'b0;
|
||||
reg [1:0] ruser_toggles = 2'b00;
|
||||
assign master_reset = rmaster_reset;
|
||||
assign user_reset = ruser_reset;
|
||||
assign user_nmi = ruser_nmi;
|
||||
assign user_toggles = ruser_toggles;
|
||||
|
||||
// Asi funciona la matriz de teclado cuando se piden semifilas
|
||||
// desde la CPU.
|
||||
// Un always @* hubiera quedado más claro en la descripción
|
||||
// pero por algun motivo, el XST no lo ha admitido en este caso
|
||||
assign sam_col = ((sam_row[0] == 1'b0)? row[0] : 8'hFF) &
|
||||
((sam_row[1] == 1'b0)? row[1] : 8'hFF) &
|
||||
((sam_row[2] == 1'b0)? row[2] : 8'hFF) &
|
||||
((sam_row[3] == 1'b0)? row[3] : 8'hFF) &
|
||||
((sam_row[4] == 1'b0)? row[4] : 8'hFF) &
|
||||
((sam_row[5] == 1'b0)? row[5] : 8'hFF) &
|
||||
((sam_row[6] == 1'b0)? row[6] : 8'hFF) &
|
||||
((sam_row[7] == 1'b0)? row[7] : 8'hFF) &
|
||||
((sam_row[8] == 1'b0)? row[8] : 8'hFF);
|
||||
|
||||
reg [2:0] modifiers = 3'b000;
|
||||
reg [3:0] keycount = 4'b0000;
|
||||
|
||||
parameter
|
||||
CLEANMATRIX = 4'd0,
|
||||
IDLE = 4'd1,
|
||||
ADDR0PUT = 4'd2,
|
||||
ADDR1PUT = 4'd3,
|
||||
ADDR2PUT = 4'd4,
|
||||
ADDR3PUT = 4'd5,
|
||||
TRANSLATE1 = 4'd6,
|
||||
TRANSLATE2 = 4'd7,
|
||||
TRANSLATE3 = 4'd8,
|
||||
CPUTIME = 4'd9,
|
||||
CPUREAD = 4'd10,
|
||||
CPUWRITE = 4'd11,
|
||||
CPUINCADD = 4'd12,
|
||||
UPDCOUNTERS1= 4'd13,
|
||||
UPDCOUNTERS2= 4'd14;
|
||||
|
||||
reg [3:0] state = CLEANMATRIX;
|
||||
reg key_is_pending = 1'b0;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (scan_received == 1'b1)
|
||||
key_is_pending <= 1'b1;
|
||||
if (rst == 1'b1)
|
||||
state <= CLEANMATRIX;
|
||||
else begin
|
||||
case (state)
|
||||
CLEANMATRIX: begin
|
||||
modifiers <= 3'b000;
|
||||
keycount <= 4'b0000;
|
||||
row[0] <= 8'hFF;
|
||||
row[1] <= 8'hFF;
|
||||
row[2] <= 8'hFF;
|
||||
row[3] <= 8'hFF;
|
||||
row[4] <= 8'hFF;
|
||||
row[5] <= 8'hFF;
|
||||
row[6] <= 8'hFF;
|
||||
row[7] <= 8'hFF;
|
||||
row[8] <= 8'hFF;
|
||||
state <= IDLE;
|
||||
end
|
||||
IDLE: begin
|
||||
if (key_is_pending == 1'b1) begin
|
||||
addr <= {modifiers, extended, scan, 2'b00}; // 1 scan tiene 8 bits + 1 bit para indicar scan extendido + 3 bits para el modificador usado
|
||||
state <= ADDR0PUT;
|
||||
key_is_pending <= 1'b0;
|
||||
end
|
||||
else if (cpuread == 1'b1 || cpuwrite == 1'b1 || rewind == 1'b1)
|
||||
state <= CPUTIME;
|
||||
end
|
||||
ADDR0PUT: begin
|
||||
{keyrow1,keycol1[7:4]} <= keymap[addr];
|
||||
addr <= {modifiers, extended, scan, 2'b01};
|
||||
state <= ADDR1PUT;
|
||||
end
|
||||
ADDR1PUT: begin
|
||||
{keycol1[3:0],keyrow2} <= keymap[addr];
|
||||
addr <= {modifiers, extended, scan, 2'b10};
|
||||
state <= ADDR2PUT;
|
||||
end
|
||||
ADDR2PUT: begin
|
||||
{keycol2} <= keymap[addr];
|
||||
addr <= {modifiers, extended, scan, 2'b11};
|
||||
state <= ADDR3PUT;
|
||||
end
|
||||
ADDR3PUT: begin
|
||||
{signalstate,keymodifiers,togglestate} <= keymap[addr];
|
||||
state <= TRANSLATE1;
|
||||
end
|
||||
TRANSLATE1: begin
|
||||
// Actualiza las 8 semifilas del teclado con la primera tecla
|
||||
if (~released) begin
|
||||
if (keyrow1[3] == 1'b1)
|
||||
row[8] <= row[8] & ~keycol1;
|
||||
else
|
||||
row[keyrow1[2:0]] <= row[keyrow1[2:0]] & ~keycol1;
|
||||
end
|
||||
else begin
|
||||
if (keyrow1[3] == 1'b1)
|
||||
row[8] <= row[8] | keycol1;
|
||||
else
|
||||
row[keyrow1[2:0]] <= row[keyrow1[2:0]] | keycol1;
|
||||
end
|
||||
state <= TRANSLATE2;
|
||||
end
|
||||
TRANSLATE2: begin
|
||||
// Actualiza las 8 semifilas del teclado con la segunda tecla
|
||||
if (~released) begin
|
||||
if (keyrow2[3] == 1'b1)
|
||||
row[8] <= row[8] & ~keycol2;
|
||||
else
|
||||
row[keyrow2[2:0]] <= row[keyrow2[2:0]] & ~keycol2;
|
||||
end
|
||||
else begin
|
||||
if (keyrow2[3] == 1'b1)
|
||||
row[8] <= row[8] | keycol2;
|
||||
else
|
||||
row[keyrow2[2:0]] <= row[keyrow2[2:0]] | keycol2;
|
||||
end
|
||||
state <= TRANSLATE3;
|
||||
end
|
||||
TRANSLATE3: begin
|
||||
// Actualiza modificadores
|
||||
if (~released)
|
||||
modifiers <= modifiers | keymodifiers;
|
||||
else
|
||||
modifiers <= modifiers & ~keymodifiers;
|
||||
|
||||
// Y de la misma forma tendria que actualizar resets y los user_toogles
|
||||
if (~released)
|
||||
{rmaster_reset,ruser_reset,ruser_nmi} <= {rmaster_reset,ruser_reset,ruser_nmi} | signalstate;
|
||||
else
|
||||
{rmaster_reset,ruser_reset,ruser_nmi} <= {rmaster_reset,ruser_reset,ruser_nmi} & ~signalstate;
|
||||
|
||||
if (~released)
|
||||
ruser_toggles <= ruser_toggles | togglestate;
|
||||
else
|
||||
ruser_toggles <= ruser_toggles & ~togglestate;
|
||||
|
||||
//state <= UPDCOUNTERS1;
|
||||
state <= IDLE;
|
||||
end
|
||||
CPUTIME: begin
|
||||
if (rewind == 1'b1) begin
|
||||
cpuaddr = 14'h0000;
|
||||
state <= IDLE;
|
||||
end
|
||||
else if (cpuread == 1'b1) begin
|
||||
addr <= cpuaddr;
|
||||
state <= CPUREAD;
|
||||
end
|
||||
else if (cpuwrite == 1'b1) begin
|
||||
addr <= cpuaddr;
|
||||
state <= CPUWRITE;
|
||||
end
|
||||
else
|
||||
state <= IDLE;
|
||||
end
|
||||
CPUREAD: begin // CPU wants to read from keymap
|
||||
dout <= keymap[addr];
|
||||
state <= CPUINCADD;
|
||||
end
|
||||
CPUWRITE: begin
|
||||
keymap[addr] <= din;
|
||||
state <= CPUINCADD;
|
||||
end
|
||||
CPUINCADD: begin
|
||||
if (cpuread == 1'b0 && cpuwrite == 1'b0) begin
|
||||
cpuaddr <= cpuaddr + 1;
|
||||
state <= IDLE;
|
||||
end
|
||||
end
|
||||
// else if (state == UPDCOUNTERS1) begin
|
||||
// if (~released)
|
||||
// keycount <= keycount + 4'b0001; // suma 1 al contador de pulsaciones
|
||||
// else if (released && keycount != 4'b0000)
|
||||
// keycount <= keycount + 4'b1111; // o le resta 1 al contador de pulsaciones, pero sin bajar de 0
|
||||
// state <= UPDCOUNTERS2;
|
||||
// end
|
||||
// else if (state == UPDCOUNTERS2) begin
|
||||
// if (keycount == 4'b0000) // si es la última tecla soltada, limpia la matriz de teclado del Spectrum
|
||||
// state <= CLEANMATRIX;
|
||||
// else
|
||||
// state <= IDLE;
|
||||
// end
|
||||
default: begin
|
||||
state <= IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -38,14 +38,10 @@ module tld_sam (
|
|||
inout wire [7:0] sram_data,
|
||||
output wire sram_we_n,
|
||||
// PS/2 keyoard interface
|
||||
input wire clkps2,
|
||||
input wire dataps2
|
||||
inout wire clkps2,
|
||||
inout wire dataps2
|
||||
);
|
||||
|
||||
// Interface with ROM
|
||||
wire [14:0] romaddr;
|
||||
wire [7:0] data_from_rom;
|
||||
|
||||
// Interface with RAM
|
||||
wire [18:0] ramaddr;
|
||||
wire [7:0] data_from_ram;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
`define TV80_REFRESH
|
||||
|
||||
module tv80_core (/*AUTOARG*/
|
||||
// Outputs
|
||||
m1_n, iorq, no_read, write, rfsh_n, halt_n, busak_n, A, dout, mc,
|
||||
|
|
|
|||
Loading…
Reference in New Issue