mirror of
https://github.com/UzixLS/zx-sizif-xxs.git
synced 2025-07-19 07:11:28 +03:00
merge latest changes from sizif-512
* add 4.4 MHz and 5.2 MHz turbo modes * handle magic key press if initialization wasn't completed before * replace 'timings', 'ram', 'plus3' settings with one 'machine' setting * refactor memory controller * significantly improve classic timings * magic rom: fix 'h' font character * fix hanging of esxdos browser after magic key double press * enable divmmc (esxdos OS) by magic rom on poweron; add NO-OS option * improve pause ('f12' on ps/2 keyboard or 'start' on gamepad) * magic rom: handle C-key on sega gamepad as exit
This commit is contained in:
@ -1,7 +1,8 @@
|
||||
package common;
|
||||
typedef enum { TIMINGS_PENT, TIMINGS_S48, TIMINGS_S128 } timings_t;
|
||||
typedef enum { TURBO_NONE, TURBO_7, TURBO_14 } turbo_t;
|
||||
typedef enum { RAM_512, RAM_48, RAM_128 } rammode_t;
|
||||
typedef enum { MACHINE_S48, MACHINE_S128, MACHINE_S3, MACHINE_PENT } machine_t;
|
||||
typedef enum { TURBO_NONE, TURBO_4, TURBO_5, TURBO_7, TURBO_14 } turbo_t;
|
||||
typedef enum { PANNING_MONO, PANNING_ABC, PANNING_ACB } panning_t;
|
||||
typedef enum { DIVMMC_OFF, DIVMMC_ON, DIVMMC_NOOS } divmmc_t;
|
||||
endpackage
|
||||
|
||||
|
||||
|
@ -5,16 +5,17 @@ module cpucontrol(
|
||||
input clk14,
|
||||
input clk7,
|
||||
input clk35,
|
||||
input ck14,
|
||||
input ck7,
|
||||
|
||||
cpu_bus bus,
|
||||
|
||||
input [8:0] vc,
|
||||
input [8:0] hc,
|
||||
input screen_contention,
|
||||
input [2:0] rampage128,
|
||||
input screen_loading,
|
||||
input machine_t machine,
|
||||
input turbo_t turbo,
|
||||
input timings_t timings,
|
||||
input pause,
|
||||
input ext_wait_cycle,
|
||||
input init_done_in,
|
||||
|
||||
@ -29,17 +30,19 @@ module cpucontrol(
|
||||
|
||||
|
||||
/* CONTENTION */
|
||||
wire iorq_contended = bus.iorq && (~bus.a[0] || (~bus.a[1] && ~bus.a[15]));
|
||||
reg mreq_delayed, iorq_delayed;
|
||||
always @(posedge clkcpu)
|
||||
mreq_delayed <= bus.mreq;
|
||||
always @(posedge clkcpu)
|
||||
iorq_delayed <= bus.iorq;
|
||||
wire contention_mem_addr = bus.a[14] & (~bus.a[15] | (bus.a[15] & rampage128[0]));
|
||||
iorq_delayed <= iorq_contended;
|
||||
wire contention_mem_page = (machine == MACHINE_S3)? rampage128[2] : rampage128[0];
|
||||
wire contention_mem_addr = bus.a[14] & (~bus.a[15] | (bus.a[15] & contention_mem_page));
|
||||
wire contention_mem = iorq_delayed == 1'b0 && mreq_delayed == 1'b0 && contention_mem_addr;
|
||||
wire contention_io = iorq_delayed == 1'b0 && bus.iorq;
|
||||
wire contention0 = screen_loading && (hc[2] || hc[3]) && (contention_mem || contention_io);
|
||||
wire contention = clkcpu && contention0 && turbo == TURBO_NONE && timings != TIMINGS_PENT;
|
||||
assign snow = (timings != TIMINGS_PENT) && bus.a[14] && ~bus.a[15] && bus.rfsh;
|
||||
wire contention_io = iorq_delayed == 1'b0 && iorq_contended;
|
||||
wire contention0 = screen_contention && (contention_mem || contention_io);
|
||||
wire contention = clkcpu && contention0 && turbo == TURBO_NONE && (machine == MACHINE_S48 || machine == MACHINE_S128 || machine == MACHINE_S3);
|
||||
assign snow = bus.a[14] && ~bus.a[15] && bus.rfsh && (machine == MACHINE_S48 || machine == MACHINE_S128);
|
||||
|
||||
|
||||
/* CLOCK */
|
||||
@ -47,35 +50,47 @@ reg [2:0] turbo_wait;
|
||||
wire turbo_wait_trig0 = bus.rd || bus.wr;
|
||||
reg turbo_wait_trig1;
|
||||
always @(posedge clk28) begin
|
||||
turbo_wait_trig1 <= turbo_wait_trig0;
|
||||
turbo_wait[0] <= turbo == TURBO_14 && turbo_wait_trig0 && !turbo_wait_trig1;
|
||||
turbo_wait[1] <= turbo_wait[0] && (bus.iorq || ext_wait_cycle);
|
||||
turbo_wait[2] <= turbo_wait[1];
|
||||
turbo_wait_trig1 <= turbo_wait_trig0;
|
||||
end
|
||||
|
||||
reg clkcpu_prev;
|
||||
assign clkcpu_ck = clkcpu && ! clkcpu_prev;
|
||||
assign clkwait = pause || contention || (|turbo_wait);
|
||||
always @(negedge clk28) begin
|
||||
assign clkcpu_ck = clkcpu && !clkcpu_prev;
|
||||
assign clkwait = contention || (|turbo_wait);
|
||||
always @(posedge clk28) begin
|
||||
clkcpu_prev <= clkcpu;
|
||||
clkcpu <= clkwait? clkcpu : (turbo == TURBO_14)? clk14 : (turbo == TURBO_7)? clk7 : clk35;
|
||||
if (clkwait)
|
||||
clkcpu <= clkcpu;
|
||||
else if (turbo == TURBO_14)
|
||||
clkcpu <= clk14;
|
||||
else if (turbo == TURBO_7 && ck14)
|
||||
clkcpu <= clk7;
|
||||
else if (turbo == TURBO_5 && ck14 && hc[1])
|
||||
clkcpu <= clk7;
|
||||
else if (turbo == TURBO_4 && ck14 && hc[1] && hc[2])
|
||||
clkcpu <= clk7;
|
||||
else if (ck7)
|
||||
clkcpu <= clk35;
|
||||
end
|
||||
|
||||
|
||||
/* INT GENERATOR */
|
||||
localparam INT_V_S48 = 247;
|
||||
localparam INT_H_S48 = 442;
|
||||
localparam INT_V_S128 = 247;
|
||||
localparam INT_H_S128 = 450;
|
||||
localparam INT_V_S48 = 248;
|
||||
localparam INT_H_S48 = 0;
|
||||
localparam INT_V_S128 = 248;
|
||||
localparam INT_H_S128 = 4;
|
||||
localparam INT_V_PENT = 239;
|
||||
localparam INT_H_PENT = 316;
|
||||
localparam INT_H_PENT = 322;
|
||||
wire int_begin =
|
||||
(timings == TIMINGS_PENT)?
|
||||
vc == INT_V_PENT && hc == INT_H_PENT :
|
||||
(timings == TIMINGS_S128)?
|
||||
(machine == MACHINE_S48)?
|
||||
vc == INT_V_S48 && hc == INT_H_S48 :
|
||||
(machine == MACHINE_S128 || machine == MACHINE_S3)?
|
||||
vc == INT_V_S128 && hc == INT_H_S128 :
|
||||
// 48K
|
||||
vc == INT_V_S48 && hc == INT_H_S48 ;
|
||||
// Pentagon
|
||||
vc == INT_V_PENT && hc == INT_H_PENT ;
|
||||
|
||||
reg [4:0] int_cnt;
|
||||
assign n_int_next = (|int_cnt)? 1'b0 : 1'b1;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
@ -98,9 +113,25 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
n_rstcpu <= 0;
|
||||
else if (!init_done_in)
|
||||
n_rstcpu <= 0;
|
||||
else if (vc[0])
|
||||
`ifdef TESTBENCH
|
||||
else if (hc[4])
|
||||
n_rstcpu <= 1'b1;
|
||||
`endif
|
||||
else if (vc[8])
|
||||
n_rstcpu <= 1'b1;
|
||||
end
|
||||
|
||||
|
||||
/* T-STATES COUNTER (for debug) */
|
||||
`ifdef TESTBENCH
|
||||
integer tstate;
|
||||
always @(posedge clkcpu) begin
|
||||
if (!n_int_next && n_int)
|
||||
tstate <= -1;
|
||||
else
|
||||
tstate <= tstate + 1;
|
||||
end
|
||||
`endif
|
||||
|
||||
|
||||
endmodule
|
||||
|
@ -20,25 +20,26 @@ module divmmc(
|
||||
input magic_mode,
|
||||
input magic_map,
|
||||
|
||||
output reg [3:0] div_page,
|
||||
output div_map,
|
||||
output div_ram,
|
||||
output div_ramwr_mask,
|
||||
output div_wait
|
||||
output reg [3:0] page,
|
||||
output map,
|
||||
output reg automap,
|
||||
output ram,
|
||||
output ramwr_mask,
|
||||
output cpuwait
|
||||
);
|
||||
|
||||
reg div_automap, div_automap_next;
|
||||
reg automap_next;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
div_automap_next <= 0;
|
||||
div_automap <= 0;
|
||||
automap_next <= 0;
|
||||
automap <= 0;
|
||||
end
|
||||
else if (bus.m1 && bus.memreq && magic_map == 0) begin
|
||||
else if (bus.m1 && bus.memreq && !magic_map) begin
|
||||
if (!en_hooks || !en || rammap) begin
|
||||
div_automap_next <= 0;
|
||||
automap_next <= 0;
|
||||
end
|
||||
else if (bus.a_reg[15:3] == 13'h3FF) begin // exit vectors 1FF8-1FFF
|
||||
div_automap_next <= 0;
|
||||
automap_next <= 0;
|
||||
end
|
||||
else if (
|
||||
bus.a_reg == 16'h0000 || // power-on/reset/rst0/software restart
|
||||
@ -48,37 +49,37 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
bus.a_reg == 16'h04C6 || // tape save routine
|
||||
bus.a_reg == 16'h0562 // tape load and verify routine
|
||||
) begin
|
||||
div_automap_next <= 1'b1;
|
||||
automap_next <= 1'b1;
|
||||
end
|
||||
else if (bus.a_reg[15:8] == 8'h3D) begin // tr-dos mapping area
|
||||
div_automap_next <= 1'b1;
|
||||
div_automap <= 1'b1;
|
||||
automap_next <= 1'b1;
|
||||
automap <= 1'b1;
|
||||
end
|
||||
end
|
||||
else if (!bus.m1) begin
|
||||
div_automap <= div_automap_next;
|
||||
automap <= automap_next;
|
||||
end
|
||||
end
|
||||
|
||||
reg spi_rd;
|
||||
reg div_conmem, div_mapram;
|
||||
reg conmem, mapram;
|
||||
wire port_e3_cs = en && bus.ioreq && bus.a_reg[7:0] == 8'hE3;
|
||||
wire port_e7_cs = en && bus.ioreq && bus.a_reg[7:0] == 8'hE7;
|
||||
wire port_eb_cs = en && bus.ioreq && bus.a_reg[7:0] == 8'hEB;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
spi_rd <= 0;
|
||||
div_page <= 0;
|
||||
div_mapram <= 0;
|
||||
div_conmem <= 0;
|
||||
page <= 0;
|
||||
mapram <= 0;
|
||||
conmem <= 0;
|
||||
sd_cs <= 1'b1;
|
||||
end
|
||||
else begin
|
||||
spi_rd <= port_eb_cs && bus.rd;
|
||||
if (port_e3_cs && bus.wr) begin
|
||||
div_page <= bus.d_reg[3:0];
|
||||
div_mapram <= bus.d_reg[6] | div_mapram;
|
||||
div_conmem <= bus.d_reg[7];
|
||||
page <= bus.d_reg[3:0];
|
||||
mapram <= bus.d_reg[6] | mapram;
|
||||
conmem <= bus.d_reg[7];
|
||||
end
|
||||
if (port_e7_cs && bus.wr) begin
|
||||
sd_cs <= bus.d_reg[0];
|
||||
@ -88,7 +89,7 @@ end
|
||||
|
||||
reg [3:0] spi_cnt;
|
||||
wire spi_cnt_en = ~spi_cnt[3] | spi_cnt[2] | spi_cnt[1] | spi_cnt[0];
|
||||
assign div_wait = ~spi_cnt[3];
|
||||
assign cpuwait = ~spi_cnt[3];
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n)
|
||||
spi_cnt <= 0;
|
||||
@ -125,12 +126,15 @@ always @(posedge clk28) begin
|
||||
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 map = automap | conmem;
|
||||
assign ram =
|
||||
(automap && bus.a[13]) ||
|
||||
(conmem && bus.a[13]) ||
|
||||
(!conmem && automap && mapram);
|
||||
assign ramwr_mask =
|
||||
!bus.a[15] && !bus.a[14] &&
|
||||
(!bus.a[13] || page == 4'b0011) &&
|
||||
!conmem && automap && mapram;
|
||||
|
||||
assign d_out_active = spi_rd;
|
||||
assign d_out = spi_reg;
|
||||
|
@ -4,26 +4,28 @@ module magic(
|
||||
input clk28,
|
||||
|
||||
cpu_bus bus,
|
||||
output [7:0] d_out,
|
||||
output d_out_active,
|
||||
|
||||
input n_int,
|
||||
input n_int_next,
|
||||
output reg n_nmi,
|
||||
|
||||
input magic_button,
|
||||
input pause_button,
|
||||
input sd_cd,
|
||||
input div_automap,
|
||||
|
||||
output reg magic_mode,
|
||||
output reg magic_map,
|
||||
|
||||
output reg magic_reboot,
|
||||
output reg magic_beeper,
|
||||
output timings_t timings,
|
||||
output machine_t machine,
|
||||
output turbo_t turbo,
|
||||
output rammode_t ram_mode,
|
||||
output panning_t panning,
|
||||
output reg joy_sinclair,
|
||||
output reg rom_plus3,
|
||||
output reg rom_alt48,
|
||||
output reg mix_acb,
|
||||
output reg mix_mono,
|
||||
output reg divmmc_en,
|
||||
output divmmc_t divmmc_en,
|
||||
output reg ulaplus_en,
|
||||
output reg covox_en,
|
||||
output reg sd_en
|
||||
@ -40,7 +42,7 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
magic_unmap_next <= 0;
|
||||
end
|
||||
else begin
|
||||
if (magic_button == 1'b1 && n_int == 1'b1 && n_int_next == 1'b0) begin
|
||||
if ((magic_button || pause_button) && n_int == 1'b1 && n_int_next == 1'b0) begin
|
||||
if (!magic_mode)
|
||||
n_nmi <= 1'b0;
|
||||
magic_mode <= 1'b1;
|
||||
@ -68,20 +70,16 @@ end
|
||||
|
||||
|
||||
/* MAGIC CONFIG */
|
||||
wire config_cs = magic_map && bus.ioreq && bus.a_reg[7:0] == 8'hff;
|
||||
wire config_cs = magic_map && bus.ioreq && bus.a_reg[7:0] == 8'hFF;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
magic_reboot <= 0;
|
||||
magic_beeper <= 0;
|
||||
timings <= TIMINGS_PENT;
|
||||
machine <= MACHINE_PENT;
|
||||
turbo <= TURBO_NONE;
|
||||
mix_acb <= 0;
|
||||
mix_mono <= 0;
|
||||
ram_mode <= RAM_512;
|
||||
rom_plus3 <= 1'b1;
|
||||
rom_alt48 <= 0;
|
||||
panning <= PANNING_ABC;
|
||||
joy_sinclair <= 0;
|
||||
divmmc_en <= 1'b1;
|
||||
divmmc_en <= DIVMMC_NOOS;
|
||||
ulaplus_en <= 1'b1;
|
||||
covox_en <= 1'b1;
|
||||
sd_en <= 1'b1;
|
||||
@ -89,18 +87,29 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
else if (config_cs && bus.wr) case (bus.a_reg[15:8])
|
||||
8'h00: magic_reboot <= bus.d_reg[0];
|
||||
8'h01: magic_beeper <= bus.d_reg[0];
|
||||
8'h02: timings <= timings_t'(bus.d_reg[1:0]);
|
||||
8'h03: turbo <= turbo_t'(bus.d_reg[1:0]);
|
||||
8'h04: {mix_mono, mix_acb} <= bus.d_reg[1:0];
|
||||
8'h05: rom_plus3 <= bus.d_reg[0];
|
||||
8'h06: rom_alt48 <= bus.d_reg[0];
|
||||
8'h02: machine <= machine_t'(bus.d_reg[2:0]);
|
||||
8'h03: turbo <= turbo_t'(bus.d_reg[2:0]);
|
||||
8'h04: panning <= panning_t'(bus.d_reg[1:0]);
|
||||
8'h07: joy_sinclair <= bus.d_reg[0];
|
||||
8'h08: ram_mode <= rammode_t'(bus.d_reg[1:0]);
|
||||
8'h09: divmmc_en <= bus.d_reg[0];
|
||||
8'h09: divmmc_en <= divmmc_t'(bus.d_reg[1:0]);
|
||||
8'h0a: ulaplus_en <= bus.d_reg[0];
|
||||
8'h0b: {sd_en, covox_en} <= bus.d_reg[1:0];
|
||||
endcase
|
||||
end
|
||||
|
||||
reg config_rd;
|
||||
wire [7:0] config_data = {4'b0000, div_automap, sd_cd, pause_button, magic_button};
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n)
|
||||
config_rd <= 0;
|
||||
else
|
||||
config_rd <= config_cs && bus.rd && bus.a_reg[15:8] == 8'hFF;
|
||||
end
|
||||
|
||||
|
||||
/* BUS CONTROLLER */
|
||||
assign d_out_active = config_rd;
|
||||
assign d_out = config_data;
|
||||
|
||||
|
||||
endmodule
|
||||
|
120
fpga/rtl/memcontrol.sv
Normal file
120
fpga/rtl/memcontrol.sv
Normal file
@ -0,0 +1,120 @@
|
||||
import common::*;
|
||||
|
||||
module memcontrol(
|
||||
input rst_n,
|
||||
input clk28,
|
||||
cpu_bus bus,
|
||||
output [18:0] va,
|
||||
inout [7:0] vd,
|
||||
output n_vrd,
|
||||
output n_vwr,
|
||||
|
||||
input machine_t machine,
|
||||
input screenpage,
|
||||
input screen_fetch,
|
||||
input screen_fetch_up,
|
||||
input snow,
|
||||
input [14:0] screen_addr,
|
||||
input magic_map,
|
||||
input [2:0] rampage128,
|
||||
input rompage128,
|
||||
input [2:0] port_1ffd,
|
||||
input [4:0] port_dffd,
|
||||
input [2:0] rampage_ext,
|
||||
input divmmc_en,
|
||||
input div_ram,
|
||||
input div_map,
|
||||
input div_ramwr_mask,
|
||||
input [3:0] div_page,
|
||||
|
||||
input [16:0] rom2ram_ram_address,
|
||||
input rom2ram_ram_wren,
|
||||
input [7:0] rom2ram_dataout,
|
||||
input magic_dout_active,
|
||||
input [7:0] magic_dout,
|
||||
input up_dout_active,
|
||||
input [7:0] up_dout,
|
||||
input div_dout_active,
|
||||
input [7:0] div_dout,
|
||||
input turbosound_dout_active,
|
||||
input [7:0] turbosound_dout,
|
||||
input ports_dout_active,
|
||||
input [7:0] ports_dout
|
||||
);
|
||||
|
||||
|
||||
/* MEMORY CONTROLLER */
|
||||
reg romreq, ramreq, ramreq_wr;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
romreq = 1'b0;
|
||||
ramreq = 1'b0;
|
||||
ramreq_wr = 1'b0;
|
||||
end
|
||||
else begin
|
||||
romreq = bus.mreq && !bus.rfsh && bus.a[14] == 0 && bus.a[15] == 0 &&
|
||||
(magic_map || (!div_ram && div_map) || (!div_ram && !port_dffd[4] && !port_1ffd[0]));
|
||||
ramreq = bus.mreq && !bus.rfsh && !romreq;
|
||||
ramreq_wr = ramreq && bus.wr && div_ramwr_mask == 0;
|
||||
end
|
||||
end
|
||||
|
||||
assign n_vrd = ((((ramreq || romreq) && bus.rd) || screen_fetch) && !rom2ram_ram_wren)? 1'b0 : 1'b1;
|
||||
assign n_vwr = ((ramreq_wr && bus.wr && !screen_fetch) || rom2ram_ram_wren)? 1'b0 : 1'b1;
|
||||
|
||||
/* VA[18:13] map
|
||||
* 00xxxx 128Kb of roms
|
||||
* 00111x 16Kb of magic ram
|
||||
* 01xxxx 128Kb of divmmc memory
|
||||
* 10xxxx 128Kb of extended ram (via port dffd)
|
||||
* 11xxxx 128Kb of main ram
|
||||
*/
|
||||
|
||||
reg [18:13] ram_a;
|
||||
always @(posedge clk28) begin
|
||||
ram_a <=
|
||||
magic_map & bus.a[15] & bus.a[14]? {2'b00, 3'b111, bus.a[13]} :
|
||||
magic_map? {3'b111, screenpage, bus.a[14:13]} :
|
||||
div_map & ~bus.a[14] & ~bus.a[15] & bus.a[13]? {2'b01, div_page} :
|
||||
div_map & ~bus.a[14] & ~bus.a[15]? {2'b01, 4'b0011} :
|
||||
port_dffd[3] & bus.a[15]? {2'b11, bus.a[14], bus.a[15], bus.a[14], bus.a[13]} :
|
||||
port_dffd[3] & bus.a[14]? {1'b1, ~rampage_ext[0], rampage128, bus.a[13]} :
|
||||
(port_1ffd[2] == 1'b0 && port_1ffd[0] == 1'b1)? {2'b11, port_1ffd[1], bus.a[15], bus.a[14], bus.a[13]} :
|
||||
(port_1ffd == 3'b101)? {2'b11, ~(bus.a[15] & bus.a[14]), bus.a[15], bus.a[14]} :
|
||||
(port_1ffd == 3'b111)? {2'b11, ~(bus.a[15] & bus.a[14]), (bus.a[15] | bus.a[14]), bus.a[14]} :
|
||||
bus.a[15] & bus.a[14]? {1'b1, ~rampage_ext[0], rampage128, bus.a[13]} :
|
||||
{2'b11, bus.a[14], bus.a[15], bus.a[14], bus.a[13]} ;
|
||||
end
|
||||
|
||||
reg [16:14] rom_a;
|
||||
always @(posedge clk28) begin
|
||||
rom_a <=
|
||||
magic_map? 3'd2 :
|
||||
div_map? 3'd3 :
|
||||
(machine == MACHINE_S3 && port_1ffd[2] == 1'b0 && rompage128 == 1'b0)? 3'd4 :
|
||||
(machine == MACHINE_S3 && port_1ffd[2] == 1'b0 && rompage128 == 1'b1)? 3'd5 :
|
||||
(machine == MACHINE_S3 && port_1ffd[2] == 1'b1 && rompage128 == 1'b0)? 3'd6 :
|
||||
(rompage128 == 1'b1)? 3'd1 :
|
||||
3'd0;
|
||||
end
|
||||
|
||||
assign va[18:0] =
|
||||
rom2ram_ram_wren? {2'b00, rom2ram_ram_address} :
|
||||
screen_fetch && snow? {3'b111, screenpage, screen_addr[14:8], {8{1'bz}}} :
|
||||
screen_fetch? {3'b111, screenpage, screen_addr} :
|
||||
romreq? {2'b00, rom_a[16:14], bus.a[13], {13{1'bz}}} :
|
||||
{ram_a[18:13], {13{1'bz}}};
|
||||
|
||||
assign vd[7:0] =
|
||||
~n_vrd? {8{1'bz}} :
|
||||
bus.wr? {8{1'bz}} :
|
||||
rom2ram_ram_wren? rom2ram_dataout :
|
||||
magic_dout_active? magic_dout :
|
||||
up_dout_active? up_dout :
|
||||
div_dout_active? div_dout :
|
||||
turbosound_dout_active? turbosound_dout :
|
||||
ports_dout_active? ports_dout :
|
||||
8'hFF;
|
||||
|
||||
|
||||
endmodule
|
@ -2,9 +2,6 @@ import common::*;
|
||||
module ports(
|
||||
input rst_n,
|
||||
input clk28,
|
||||
input en_128k,
|
||||
input en_plus3,
|
||||
input en_profi,
|
||||
input en_kempston,
|
||||
input en_sinclair,
|
||||
|
||||
@ -12,13 +9,12 @@ module ports(
|
||||
output [7:0] d_out,
|
||||
output d_out_active,
|
||||
|
||||
input timings_t timings,
|
||||
input clkcpu_ck,
|
||||
input screen_loading,
|
||||
input [7:0] attr_next,
|
||||
input machine_t machine,
|
||||
input port_ff_active,
|
||||
input [7:0] port_ff_data,
|
||||
input [4:0] kd,
|
||||
input [7:0] kempston_data,
|
||||
input magic_button,
|
||||
input magic_map,
|
||||
input tape_in,
|
||||
|
||||
output reg tape_out,
|
||||
@ -27,21 +23,21 @@ module ports(
|
||||
output reg screenpage,
|
||||
output reg rompage128,
|
||||
output reg [2:0] rampage128,
|
||||
output reg [3:0] rampage_ext,
|
||||
output reg [2:0] rampage_ext,
|
||||
output reg [2:0] port_1ffd,
|
||||
output reg port_dffd_d3,
|
||||
output reg port_dffd_d4
|
||||
output reg [4:0] port_dffd
|
||||
|
||||
);
|
||||
|
||||
|
||||
/* PORT #FF */
|
||||
wire [7:0] port_ff_data = attr_next;
|
||||
reg port_ff_rd;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n)
|
||||
port_ff_rd <= 0;
|
||||
else
|
||||
port_ff_rd <= bus.rd && bus.ioreq && (timings != TIMINGS_PENT || bus.a_reg[7:0] == 8'hFF) && screen_loading;
|
||||
port_ff_rd <= bus.rd && bus.ioreq && !magic_map && port_ff_active &&
|
||||
(machine != MACHINE_S3) && (machine != MACHINE_PENT || bus.a_reg[7:0] == 8'hFF);
|
||||
end
|
||||
|
||||
|
||||
@ -56,14 +52,14 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
end
|
||||
|
||||
reg [4:0] kd0;
|
||||
wire [7:0] port_fe_data = {~magic_button, tape_in, 1'b1, kd0};
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
wire [7:0] port_fe_data = {1'b1, tape_in, 1'b1, kd0};
|
||||
always @(negedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
beeper <= 0;
|
||||
tape_out <= 0;
|
||||
border <= 0;
|
||||
end
|
||||
else if (port_fe_cs && bus.wr && clkcpu_ck) begin // clkcpu_ck to synchronize border
|
||||
else if (port_fe_cs && bus.wr) begin
|
||||
beeper <= bus.d_reg[4];
|
||||
tape_out <= bus.d_reg[3];
|
||||
border <= bus.d_reg[2:0];
|
||||
@ -86,7 +82,9 @@ end
|
||||
|
||||
|
||||
/* PORT #7FFD */
|
||||
wire port_7ffd_cs = en_128k && bus.ioreq && bus.a_reg[1] == 0 && bus.a_reg[15] == 0 && (bus.a_reg[14] == 1'b1 || !en_plus3);
|
||||
wire port_7ffd_cs = bus.ioreq && bus.a_reg[1] == 0 && bus.a_reg[15] == 0 &&
|
||||
(bus.a_reg[14] == 1'b1 || (!magic_map && machine != MACHINE_S3)) &&
|
||||
(machine != MACHINE_S48 || magic_map);
|
||||
reg lock_7ffd;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
@ -95,7 +93,7 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
rompage128 <= 0;
|
||||
lock_7ffd <= 0;
|
||||
end
|
||||
else if (port_7ffd_cs && bus.wr && (lock_7ffd == 0 || port_dffd_d4 == 1'b1)) begin
|
||||
else if (port_7ffd_cs && bus.wr && (lock_7ffd == 0 || port_dffd[4] == 1'b1)) begin
|
||||
rampage128 <= bus.d_reg[2:0];
|
||||
screenpage <= bus.d_reg[3];
|
||||
rompage128 <= bus.d_reg[4];
|
||||
@ -105,23 +103,21 @@ end
|
||||
|
||||
|
||||
/* PORT #DFFD */
|
||||
wire port_dffd_cs = en_profi && bus.ioreq && bus.a_reg == 16'hDFFD;
|
||||
wire port_dffd_cs = bus.ioreq && bus.a_reg == 16'hDFFD && (machine == MACHINE_PENT || magic_map);
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
rampage_ext <= 0;
|
||||
port_dffd_d3 <= 0;
|
||||
port_dffd_d4 <= 0;
|
||||
port_dffd <= 0;
|
||||
end
|
||||
else if (port_dffd_cs && bus.wr) begin
|
||||
rampage_ext <= bus.d_reg[2:0];
|
||||
port_dffd_d3 <= bus.d_reg[3];
|
||||
port_dffd_d4 <= bus.d_reg[4];
|
||||
port_dffd <= bus.d_reg[4:0];
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
/* PORT #1FFD */
|
||||
wire port_1ffd_cs = en_plus3 && bus.ioreq && bus.a_reg == 16'h1FFD;
|
||||
wire port_1ffd_cs = bus.ioreq && bus.a_reg == 16'h1FFD && (machine == MACHINE_S3 || magic_map);
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
port_1ffd <= 0;
|
||||
|
@ -136,8 +136,7 @@ always @(posedge clk or negedge rst_n) begin
|
||||
`PS2_PGDN: key2_pgdn <= is_press;
|
||||
|
||||
`PS2_F5: key_magic <= is_press;
|
||||
`PS2_F11: key_pause <= 1'b0;
|
||||
`PS2_F12: key_pause <= 1'b1;
|
||||
`PS2_F12: key_pause <= is_press;
|
||||
`PS2_DELETE: key2_del <= is_press;
|
||||
|
||||
`PS2_KP_8: joy_up <= is_press;
|
||||
|
@ -4,12 +4,12 @@ module screen(
|
||||
input rst_n,
|
||||
input clk28,
|
||||
|
||||
input timings_t timings,
|
||||
input machine_t machine,
|
||||
input [2:0] border,
|
||||
|
||||
output reg [2:0] r,
|
||||
output reg [2:0] g,
|
||||
output reg [2:0] b,
|
||||
output reg [1:0] b,
|
||||
output reg vsync,
|
||||
output reg hsync,
|
||||
output reg csync,
|
||||
@ -20,9 +20,11 @@ module screen(
|
||||
output [14:0] addr,
|
||||
input [7:0] fetch_data,
|
||||
|
||||
output loading,
|
||||
output contention,
|
||||
output blink,
|
||||
output reg [7:0] attr_next,
|
||||
output reg even_line,
|
||||
output port_ff_active,
|
||||
output [7:0] port_ff_data,
|
||||
|
||||
input up_en,
|
||||
output [5:0] up_ink_addr,
|
||||
@ -43,24 +45,24 @@ module screen(
|
||||
/* SCREEN CONTROLLER */
|
||||
localparam H_AREA = 256;
|
||||
localparam V_AREA = 192;
|
||||
localparam SCREEN_DELAY = 8;
|
||||
localparam SCREEN_DELAY = 13;
|
||||
|
||||
localparam H_LBORDER_S48 = 48 - SCREEN_DELAY;
|
||||
localparam H_RBORDER_S48 = 48 + SCREEN_DELAY;
|
||||
localparam H_BLANK1_S48 = 17;
|
||||
localparam H_LBORDER_S48 = 54 - SCREEN_DELAY;
|
||||
localparam H_RBORDER_S48 = 53 + SCREEN_DELAY;
|
||||
localparam H_BLANK1_S48 = 12;
|
||||
localparam H_SYNC_S48 = 33;
|
||||
localparam H_BLANK2_S48 = 46;
|
||||
localparam H_BLANK2_S48 = 40;
|
||||
localparam H_TOTAL_S48 = H_AREA + H_RBORDER_S48 + H_BLANK1_S48 + H_SYNC_S48 + H_BLANK2_S48 + H_LBORDER_S48;
|
||||
localparam V_BBORDER_S48 = 56;
|
||||
localparam V_SYNC_S48 = 8;
|
||||
localparam V_TBORDER_S48 = 56;
|
||||
localparam V_TOTAL_S48 = V_AREA + V_BBORDER_S48 + V_SYNC_S48 + V_TBORDER_S48;
|
||||
|
||||
localparam H_LBORDER_S128 = 48 - SCREEN_DELAY;
|
||||
localparam H_RBORDER_S128 = 48 + SCREEN_DELAY;
|
||||
localparam H_BLANK1_S128 = 25;
|
||||
localparam H_LBORDER_S128 = 58 - SCREEN_DELAY;
|
||||
localparam H_RBORDER_S128 = 57 + SCREEN_DELAY;
|
||||
localparam H_BLANK1_S128 = 12;
|
||||
localparam H_SYNC_S128 = 33;
|
||||
localparam H_BLANK2_S128 = 46;
|
||||
localparam H_BLANK2_S128 = 40;
|
||||
localparam H_TOTAL_S128 = H_AREA + H_RBORDER_S128 + H_BLANK1_S128 + H_SYNC_S128 + H_BLANK2_S128 + H_LBORDER_S128;
|
||||
localparam V_BBORDER_S128 = 55;
|
||||
localparam V_SYNC_S128 = 8;
|
||||
@ -78,12 +80,13 @@ localparam V_SYNC_PENT = 8;
|
||||
localparam V_TBORDER_PENT = 64;
|
||||
localparam V_TOTAL_PENT = V_AREA + V_BBORDER_PENT + V_SYNC_PENT + V_TBORDER_PENT;
|
||||
|
||||
reg [`CLOG2(`MAX(V_TOTAL_S128, V_TOTAL_PENT))-1:0] vc;
|
||||
reg [`CLOG2(`MAX(H_TOTAL_S128, H_TOTAL_PENT))+1:0] hc0;
|
||||
wire [`CLOG2(`MAX(H_TOTAL_S128, H_TOTAL_PENT))-1:0] hc = hc0[$bits(hc0)-1:2];
|
||||
reg [8:0] vc;
|
||||
reg [10:0] hc0;
|
||||
wire [8:0] hc = hc0[10:2];
|
||||
|
||||
assign vc_out = vc;
|
||||
assign hc_out = hc;
|
||||
|
||||
assign clk14 = hc0[0];
|
||||
assign clk7 = hc0[1];
|
||||
assign clk35 = hc0[2];
|
||||
@ -92,49 +95,49 @@ assign ck7 = hc0[0] & hc0[1];
|
||||
assign ck35 = hc0[0] & hc0[1] & hc0[2];
|
||||
|
||||
wire hc0_reset =
|
||||
(timings == TIMINGS_PENT)?
|
||||
hc0 == (H_TOTAL_PENT<<2) - 1'b1 :
|
||||
(timings == TIMINGS_S128)?
|
||||
(machine == MACHINE_S48)?
|
||||
hc0 == (H_TOTAL_S48<<2) - 1'b1 :
|
||||
(machine == MACHINE_S128 || machine == MACHINE_S3)?
|
||||
hc0 == (H_TOTAL_S128<<2) - 1'b1 :
|
||||
// 48K
|
||||
hc0 == (H_TOTAL_S48<<2) - 1'b1 ;
|
||||
// Pentagon
|
||||
hc0 == (H_TOTAL_PENT<<2) - 1'b1 ;
|
||||
wire vc_reset =
|
||||
(timings == TIMINGS_PENT)?
|
||||
vc == V_TOTAL_PENT - 1'b1 :
|
||||
(timings == TIMINGS_S128)?
|
||||
(machine == MACHINE_S48)?
|
||||
vc == V_TOTAL_S48 - 1'b1:
|
||||
(machine == MACHINE_S128 || machine == MACHINE_S3)?
|
||||
vc == V_TOTAL_S128 - 1'b1 :
|
||||
// 48K
|
||||
vc == V_TOTAL_S48 - 1'b1;
|
||||
// Pentagon
|
||||
vc == V_TOTAL_PENT - 1'b1 ;
|
||||
wire hsync0 =
|
||||
(timings == TIMINGS_PENT)?
|
||||
(hc >= (H_AREA + H_RBORDER_PENT + H_BLANK1_PENT)) &&
|
||||
(hc < (H_AREA + H_RBORDER_PENT + H_BLANK1_PENT + H_SYNC_PENT)) :
|
||||
(timings == TIMINGS_S128)?
|
||||
(machine == MACHINE_S48)?
|
||||
(hc >= (H_AREA + H_RBORDER_S48 + H_BLANK1_S48)) &&
|
||||
(hc < (H_AREA + H_RBORDER_S48 + H_BLANK1_S48 + H_SYNC_S48)) :
|
||||
(machine == MACHINE_S128 || machine == MACHINE_S3)?
|
||||
(hc >= (H_AREA + H_RBORDER_S128 + H_BLANK1_S128)) &&
|
||||
(hc < (H_AREA + H_RBORDER_S128 + H_BLANK1_S128 + H_SYNC_S128)) :
|
||||
// 48K
|
||||
(hc >= (H_AREA + H_RBORDER_S48 + H_BLANK1_S48)) &&
|
||||
(hc < (H_AREA + H_RBORDER_S48 + H_BLANK1_S48 + H_SYNC_S48)) ;
|
||||
// Pentagon
|
||||
(hc >= (H_AREA + H_RBORDER_PENT + H_BLANK1_PENT)) &&
|
||||
(hc < (H_AREA + H_RBORDER_PENT + H_BLANK1_PENT + H_SYNC_PENT)) ;
|
||||
wire vsync0 =
|
||||
(timings == TIMINGS_PENT)?
|
||||
(vc >= (V_AREA + V_BBORDER_PENT)) && (vc < (V_AREA + V_BBORDER_PENT + V_SYNC_PENT)) :
|
||||
(timings == TIMINGS_S128)?
|
||||
(machine == MACHINE_S48)?
|
||||
(vc >= (V_AREA + V_BBORDER_S48)) && (vc < (V_AREA + V_BBORDER_S48 + V_SYNC_S48)) :
|
||||
(machine == MACHINE_S128 || machine == MACHINE_S3)?
|
||||
(vc >= (V_AREA + V_BBORDER_S128)) && (vc < (V_AREA + V_BBORDER_S128 + V_SYNC_S128)) :
|
||||
// 48K
|
||||
(vc >= (V_AREA + V_BBORDER_S48)) && (vc < (V_AREA + V_BBORDER_S48 + V_SYNC_S48)) ;
|
||||
// Pentagon
|
||||
(vc >= (V_AREA + V_BBORDER_PENT)) && (vc < (V_AREA + V_BBORDER_PENT + V_SYNC_PENT)) ;
|
||||
wire blank =
|
||||
(timings == TIMINGS_PENT)?
|
||||
((vc >= (V_AREA + V_BBORDER_PENT)) && (vc < (V_AREA + V_BBORDER_PENT + V_SYNC_PENT))) ||
|
||||
((hc >= (H_AREA + H_RBORDER_PENT)) &&
|
||||
(hc < (H_AREA + H_RBORDER_PENT + H_BLANK1_PENT + H_SYNC_PENT + H_BLANK2_PENT))) :
|
||||
(timings == TIMINGS_S128)?
|
||||
(machine == MACHINE_S48)?
|
||||
((vc >= (V_AREA + V_BBORDER_S48)) && (vc < (V_AREA + V_BBORDER_S48 + V_SYNC_S48))) ||
|
||||
((hc >= (H_AREA + H_RBORDER_S48)) &&
|
||||
(hc < (H_AREA + H_RBORDER_S48 + H_BLANK1_S48 + H_SYNC_S48 + H_BLANK2_S48))) :
|
||||
(machine == MACHINE_S128 || machine == MACHINE_S3)?
|
||||
((vc >= (V_AREA + V_BBORDER_S128)) && (vc < (V_AREA + V_BBORDER_S128 + V_SYNC_S128))) ||
|
||||
((hc >= (H_AREA + H_RBORDER_S128)) &&
|
||||
(hc < (H_AREA + H_RBORDER_S128 + H_BLANK1_S128 + H_SYNC_S128 + H_BLANK2_S128))) :
|
||||
// 48K
|
||||
((vc >= (V_AREA + V_BBORDER_S48)) && (vc < (V_AREA + V_BBORDER_S48 + V_SYNC_S48))) ||
|
||||
((hc >= (H_AREA + H_RBORDER_S48)) &&
|
||||
(hc < (H_AREA + H_RBORDER_S48 + H_BLANK1_S48 + H_SYNC_S48 + H_BLANK2_S48))) ;
|
||||
// Pentagon
|
||||
((vc >= (V_AREA + V_BBORDER_PENT)) && (vc < (V_AREA + V_BBORDER_PENT + V_SYNC_PENT))) ||
|
||||
((hc >= (H_AREA + H_RBORDER_PENT)) &&
|
||||
(hc < (H_AREA + H_RBORDER_PENT + H_BLANK1_PENT + H_SYNC_PENT + H_BLANK2_PENT))) ;
|
||||
|
||||
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
@ -166,30 +169,61 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
blink_cnt <= blink_cnt + 1'b1;
|
||||
end
|
||||
|
||||
reg hsync0_delayed;
|
||||
always @(posedge clk28)
|
||||
hsync0_delayed <= hsync0;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n)
|
||||
even_line <= 0;
|
||||
else if (hsync0 && !hsync0_delayed)
|
||||
even_line <= ~even_line;
|
||||
end
|
||||
|
||||
wire [7:0] attr_border = {2'b00, border[2:0], 3'b000};
|
||||
|
||||
reg [7:0] bitmap, attr, bitmap_next;
|
||||
wire screen_show = (vc < V_AREA) && (hc0 >= (SCREEN_DELAY<<2) - 1) && (hc0 < ((H_AREA + SCREEN_DELAY)<<2) - 1);
|
||||
wire screen_update = hc0[4:0] == 5'b10011;
|
||||
wire border_update = (hc0[4:0] == 5'b10011) || (machine == MACHINE_PENT && ck7);
|
||||
wire bitmap_shift = hc0[1:0] == 2'b11;
|
||||
wire next_addr = hc0[4:0] == 5'b10001;
|
||||
|
||||
reg [7:0] vaddr;
|
||||
reg [7:3] haddr;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
vaddr <= 0;
|
||||
haddr <= 0;
|
||||
end
|
||||
else if (next_addr) begin
|
||||
vaddr <= vc[7:0];
|
||||
haddr <= hc[7:3];
|
||||
end
|
||||
end
|
||||
|
||||
reg loading;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n)
|
||||
loading <= 0;
|
||||
else
|
||||
loading <= (vc < V_AREA) && (hc0 > 15) && (hc0 < (H_AREA<<2) + 17);
|
||||
end
|
||||
|
||||
|
||||
wire [7:0] attr_border = {2'b00, border[2:0], border[2:0]};
|
||||
|
||||
reg [7:0] bitmap, attr, bitmap_next, attr_next;
|
||||
reg [7:0] up_ink0, up_paper0;
|
||||
|
||||
reg fetch_step;
|
||||
wire fetch_bitmap = fetch && fetch_step == 1'd1;
|
||||
wire fetch_attr = fetch && fetch_step == 1'd0;
|
||||
wire fetch_bitmap = fetch && fetch_step == 2'd0;
|
||||
wire fetch_attr = fetch && fetch_step == 2'd1;
|
||||
assign fetch_next = loading && fetch_allow;
|
||||
|
||||
assign addr = fetch_bitmap?
|
||||
{ 2'b10, vc[7:6], vc[2:0], vc[5:3], hc[7:3] } :
|
||||
{ 5'b10110, vc[7:3], hc[7:3] };
|
||||
|
||||
reg [7:0] up_ink0, up_paper0;
|
||||
{ 2'b10, vaddr[7:6], vaddr[2:0], vaddr[5:3], haddr[7:3] } :
|
||||
{ 5'b10110, vaddr[7:3], haddr[7:3] };
|
||||
assign up_ink_addr = { attr_next[7:6], 1'b0, attr_next[2:0] };
|
||||
assign up_paper_addr = { attr_next[7:6], 1'b1, attr_next[5:3] };
|
||||
|
||||
assign loading = (vc < V_AREA) && (hc < H_AREA || hc0_reset);
|
||||
wire screen_show = (vc < V_AREA) && (hc0 >= (SCREEN_DELAY<<2) - 2) && (hc0 < ((H_AREA + SCREEN_DELAY)<<2) - 2);
|
||||
wire screen_update = vc < V_AREA && hc <= H_AREA && hc != 0 && hc0[4:0] == 5'b11110;
|
||||
wire border_update = !screen_show && ((timings == TIMINGS_PENT && ck7) || hc0[4:0] == 5'b11110);
|
||||
wire bitmap_shift = hc0[1:0] == 2'b10;
|
||||
|
||||
assign fetch_next = loading && fetch_allow;
|
||||
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
fetch <= 0;
|
||||
@ -198,12 +232,14 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
bitmap <= 0;
|
||||
attr_next <= 0;
|
||||
bitmap_next <= 0;
|
||||
up_ink0 <= 0;
|
||||
up_paper0 <= 0;
|
||||
end
|
||||
else begin
|
||||
if (ck14) begin
|
||||
if (fetch)
|
||||
fetch_step <= fetch_step + 1'b1;
|
||||
fetch <= fetch_next;
|
||||
fetch <= fetch_allow;
|
||||
|
||||
if (fetch_attr)
|
||||
attr_next <= fetch_data;
|
||||
@ -211,12 +247,14 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
attr_next <= attr_border;
|
||||
if (fetch_bitmap)
|
||||
bitmap_next <= fetch_data;
|
||||
else if (!loading)
|
||||
bitmap_next <= 0;
|
||||
end
|
||||
|
||||
if (border_update)
|
||||
attr <= attr_border;
|
||||
else if (screen_update)
|
||||
if (screen_show && screen_update)
|
||||
attr <= attr_next;
|
||||
else if (!screen_show && border_update)
|
||||
attr <= attr_border;
|
||||
|
||||
if (screen_update)
|
||||
bitmap <= bitmap_next;
|
||||
@ -225,28 +263,42 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
|
||||
if (screen_update)
|
||||
up_ink0 <= up_ink;
|
||||
if (screen_update || (!screen_show && !loading))
|
||||
if (screen_update)
|
||||
up_paper0 <= up_paper;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
/* ATTRIBUTE PORT */
|
||||
wire port_ff_attr = (machine == MACHINE_PENT) || hc[3:1] == 3'h6 || hc[3:1] == 3'h0;
|
||||
wire port_ff_bitmap = (hc[3] && hc[1]);
|
||||
assign port_ff_active = loading && (port_ff_attr || port_ff_bitmap);
|
||||
assign port_ff_data =
|
||||
port_ff_attr? attr_next :
|
||||
port_ff_bitmap? bitmap_next :
|
||||
8'hFF;
|
||||
|
||||
assign contention = (vc < V_AREA) && (hc < H_AREA) && (hc[2] || hc[3]);
|
||||
|
||||
|
||||
/* RGBS generation */
|
||||
wire pixel = bitmap[7];
|
||||
always @(posedge clk28) begin
|
||||
if (blank)
|
||||
{g, r, b} = 0;
|
||||
else if (up_en) begin
|
||||
g = pixel? up_ink0[7:5] : up_paper0[7:5];
|
||||
r = pixel? up_ink0[4:2] : up_paper0[4:2];
|
||||
b[2:1] = pixel? up_ink0[1:0] : up_paper0[1:0];
|
||||
b[0] = |b[2:1];
|
||||
g = pixel? up_ink0[7:5] : up_paper0[7:5];
|
||||
r = pixel? up_ink0[4:2] : up_paper0[4:2];
|
||||
b = pixel? up_ink0[1:0] : up_paper0[1:0];
|
||||
end
|
||||
else begin
|
||||
{g[2], r[2], b[2]} = (pixel ^ (attr[7] & blink))? attr[2:0] : attr[5:3];
|
||||
{g[1], r[1], b[1]} = {g[2] & attr[6], r[2] & attr[6], b[2] & attr[6]};
|
||||
{g[0], r[0], b[0]} = {g[2], r[2], b[2]};
|
||||
{g[2], r[2], b[1]} = (pixel ^ (attr[7] & blink))? attr[2:0] : attr[5:3];
|
||||
{g[1], r[1], b[0]} = {g[2] & attr[6], r[2] & attr[6], b[1] & attr[6]};
|
||||
{g[0], r[0]} = {g[2], r[2]};
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk28) begin
|
||||
csync = ~(vsync0 ^ hsync0);
|
||||
vsync = ~vsync0;
|
||||
hsync = ~hsync0;
|
||||
|
227
fpga/rtl/top.sv
227
fpga/rtl/top.sv
@ -48,11 +48,9 @@ pll pll0(.inclk0(clk_in), .c0(clk40), .c1(clk20), .locked(rst_n));
|
||||
|
||||
|
||||
/* SHARED DEFINITIONS */
|
||||
timings_t timings;
|
||||
machine_t machine;
|
||||
turbo_t turbo;
|
||||
rammode_t ram_mode;
|
||||
reg pause = 0;
|
||||
wire ps2_key_pause, ps2_key_reset;
|
||||
wire ps2_key_reset, ps2_key_pause;
|
||||
wire [2:0] border;
|
||||
wire magic_reboot, magic_beeper;
|
||||
wire up_active;
|
||||
@ -102,30 +100,25 @@ always @(posedge clk28) begin
|
||||
usrrst_n <= (!rst_n || ps2_key_reset || magic_reboot)? 1'b0 : 1'b1;
|
||||
end
|
||||
|
||||
/* PAUSE */
|
||||
always @(posedge clk28) begin
|
||||
if (n_int == 1'b0 && bus.rfsh)
|
||||
pause <= ps2_key_pause;
|
||||
end
|
||||
|
||||
|
||||
/* SCREEN CONTROLLER */
|
||||
wire blink;
|
||||
wire [2:0] screen_border = {border[2] ^ ~sd_cs, border[1] ^ magic_beeper, border[0] ^ (pause & blink)};
|
||||
wire [2:0] r, g, b;
|
||||
wire [2:0] screen_border = {border[2] ^ ~sd_cs, border[1] ^ magic_beeper, border[0]};
|
||||
wire [2:0] r, g;
|
||||
wire [1:0] b;
|
||||
wire hsync;
|
||||
wire screen_contention, port_ff_active;
|
||||
wire [14:0] screen_addr;
|
||||
wire [5:0] up_ink_addr, up_paper_addr;
|
||||
wire [7:0] up_ink, up_paper;
|
||||
wire screen_loading;
|
||||
wire [14:0] screen_addr;
|
||||
wire [7:0] attr_next;
|
||||
wire [8:0] vc, hc;
|
||||
wire [7:0] port_ff_data;
|
||||
wire clk14, clk7, clk35, ck14, ck7, ck35;
|
||||
screen screen0(
|
||||
.rst_n(rst_n),
|
||||
.rst_n(usrrst_n),
|
||||
.clk28(clk28),
|
||||
|
||||
.timings(timings),
|
||||
.machine(machine),
|
||||
.border(screen_border),
|
||||
|
||||
.r(r),
|
||||
@ -141,16 +134,17 @@ screen screen0(
|
||||
.fetch_next(screen_fetch_next),
|
||||
.fetch_data(bus.d),
|
||||
|
||||
.loading(screen_loading),
|
||||
.blink(blink),
|
||||
.attr_next(attr_next),
|
||||
|
||||
.up_en(up_active),
|
||||
.up_ink_addr(up_ink_addr),
|
||||
.up_paper_addr(up_paper_addr),
|
||||
.up_ink(up_ink),
|
||||
.up_paper(up_paper),
|
||||
|
||||
.contention(screen_contention),
|
||||
.blink(blink),
|
||||
.port_ff_active(port_ff_active),
|
||||
.port_ff_data(port_ff_data),
|
||||
|
||||
.vc_out(vc),
|
||||
.hc_out(hc),
|
||||
.clk14(clk14),
|
||||
@ -210,16 +204,17 @@ cpucontrol cpucontrol0(
|
||||
.clk14(clk14),
|
||||
.clk7(clk7),
|
||||
.clk35(clk35),
|
||||
.ck14(ck14),
|
||||
.ck7(ck7),
|
||||
|
||||
.bus(bus),
|
||||
|
||||
.vc(vc),
|
||||
.hc(hc),
|
||||
.rampage128(rampage128),
|
||||
.screen_loading(screen_loading),
|
||||
.machine(machine),
|
||||
.screen_contention(screen_contention),
|
||||
.turbo(turbo),
|
||||
.timings(timings),
|
||||
.pause(pause),
|
||||
.ext_wait_cycle(div_wait || up_active),
|
||||
.init_done_in(init_done),
|
||||
|
||||
@ -234,32 +229,39 @@ cpucontrol cpucontrol0(
|
||||
|
||||
|
||||
/* MAGIC */
|
||||
wire div_automap;
|
||||
wire [7:0] magic_dout;
|
||||
wire magic_dout_active;
|
||||
wire magic_mode, magic_map;
|
||||
wire divmmc_en, joy_sinclair, rom_plus3, rom_alt48, mix_acb, mix_mono, up_en, covox_en, sd_en;
|
||||
wire joy_sinclair, up_en, covox_en, sd_en;
|
||||
panning_t panning;
|
||||
divmmc_t divmmc_en;
|
||||
magic magic0(
|
||||
.rst_n(usrrst_n),
|
||||
.rst_n(n_rstcpu),
|
||||
.clk28(clk28),
|
||||
|
||||
.bus(bus),
|
||||
.d_out(magic_dout),
|
||||
.d_out_active(magic_dout_active),
|
||||
|
||||
.n_int(n_int),
|
||||
.n_int_next(n_int_next),
|
||||
.n_nmi(n_nmi),
|
||||
|
||||
.magic_button(ps2_key_magic),
|
||||
.pause_button(ps2_key_pause),
|
||||
.sd_cd(sd_cd),
|
||||
.div_automap(div_automap),
|
||||
|
||||
.magic_mode(magic_mode),
|
||||
.magic_map(magic_map),
|
||||
|
||||
.magic_reboot(magic_reboot),
|
||||
.magic_beeper(magic_beeper),
|
||||
.timings(timings),
|
||||
.machine(machine),
|
||||
.turbo(turbo),
|
||||
.ram_mode(ram_mode),
|
||||
.joy_sinclair(joy_sinclair),
|
||||
.rom_plus3(rom_plus3),
|
||||
.rom_alt48(rom_alt48),
|
||||
.mix_acb(mix_acb),
|
||||
.mix_mono(mix_mono),
|
||||
.panning(panning),
|
||||
.divmmc_en(divmmc_en),
|
||||
.ulaplus_en(up_en),
|
||||
.covox_en(covox_en),
|
||||
@ -273,31 +275,26 @@ wire ports_dout_active;
|
||||
wire beeper, tape_out;
|
||||
wire screenpage;
|
||||
wire rompage128;
|
||||
wire [3:0] rampage_ext;
|
||||
wire [2:0] rampage_ext;
|
||||
wire [2:0] port_1ffd;
|
||||
wire port_dffd_d3;
|
||||
wire port_dffd_d4;
|
||||
wire [4:0] port_dffd;
|
||||
ports ports0 (
|
||||
.rst_n(usrrst_n),
|
||||
.rst_n(n_rstcpu),
|
||||
.clk28(clk28),
|
||||
|
||||
.bus(bus),
|
||||
.d_out(ports_dout),
|
||||
.d_out_active(ports_dout_active),
|
||||
|
||||
.en_128k(ram_mode == RAM_512 || ram_mode == RAM_128),
|
||||
.en_plus3(rom_plus3),
|
||||
.en_profi(ram_mode == RAM_512),
|
||||
.en_kempston(!joy_sinclair),
|
||||
.en_sinclair(joy_sinclair),
|
||||
|
||||
.timings(timings),
|
||||
.clkcpu_ck(clkcpu_ck),
|
||||
.screen_loading(screen_loading),
|
||||
.attr_next(attr_next),
|
||||
.machine(machine),
|
||||
.port_ff_active(port_ff_active),
|
||||
.port_ff_data(port_ff_data),
|
||||
.kd(ps2_kd),
|
||||
.kempston_data({3'b000, ps2_joy_fire, ps2_joy_up, ps2_joy_down, ps2_joy_left, ps2_joy_right}),
|
||||
.magic_button(ps2_key_magic),
|
||||
.magic_map(magic_map),
|
||||
.tape_in(sd_miso_tape_in),
|
||||
|
||||
.tape_out(tape_out),
|
||||
@ -308,8 +305,7 @@ ports ports0 (
|
||||
.rampage128(rampage128),
|
||||
.rampage_ext(rampage_ext),
|
||||
.port_1ffd(port_1ffd),
|
||||
.port_dffd_d3(port_dffd_d3),
|
||||
.port_dffd_d4(port_dffd_d4)
|
||||
.port_dffd(port_dffd)
|
||||
);
|
||||
|
||||
|
||||
@ -318,7 +314,7 @@ wire turbosound_dout_active;
|
||||
wire [7:0] turbosound_dout;
|
||||
wire [7:0] ay_a0, ay_b0, ay_c0, ay_a1, ay_b1, ay_c1;
|
||||
turbosound turbosound0(
|
||||
.rst_n(usrrst_n),
|
||||
.rst_n(n_rstcpu),
|
||||
.clk28(clk28),
|
||||
.ck35(ck35),
|
||||
.en(1'b1),
|
||||
@ -328,8 +324,6 @@ turbosound turbosound0(
|
||||
.d_out(turbosound_dout),
|
||||
.d_out_active(turbosound_dout_active),
|
||||
|
||||
.pause(pause),
|
||||
|
||||
.ay_a0(ay_a0),
|
||||
.ay_b0(ay_b0),
|
||||
.ay_c0(ay_c0),
|
||||
@ -355,10 +349,9 @@ soundrive soundrive0(
|
||||
.ch_r1(soundrive_r1)
|
||||
);
|
||||
|
||||
|
||||
/* SOUND MIXER */
|
||||
mixer mixer0(
|
||||
.rst_n(rst_n),
|
||||
.rst_n(usrrst_n),
|
||||
.clk28(clk28),
|
||||
|
||||
.beeper(beeper ^ magic_beeper),
|
||||
@ -375,8 +368,8 @@ mixer mixer0(
|
||||
.sd_r0(soundrive_r0),
|
||||
.sd_r1(soundrive_r1),
|
||||
|
||||
.ay_acb(mix_acb),
|
||||
.mono(mix_mono),
|
||||
.ay_acb(panning == PANNING_ABC),
|
||||
.mono(panning == PANNING_MONO),
|
||||
|
||||
.dac_l(snd_l),
|
||||
.dac_r(snd_r)
|
||||
@ -389,12 +382,12 @@ wire [7:0] div_dout;
|
||||
wire [3:0] div_page;
|
||||
wire sd_mosi0;
|
||||
divmmc divmmc0(
|
||||
.rst_n(usrrst_n),
|
||||
.rst_n(n_rstcpu),
|
||||
.clk28(clk28),
|
||||
.ck14(ck14),
|
||||
.ck7(ck7),
|
||||
.en(divmmc_en),
|
||||
.en_hooks(~sd_cd),
|
||||
.en(divmmc_en == DIVMMC_ON || divmmc_en == DIVMMC_NOOS),
|
||||
.en_hooks(divmmc_en == DIVMMC_ON),
|
||||
|
||||
.bus(bus),
|
||||
.d_out(div_dout),
|
||||
@ -405,15 +398,16 @@ divmmc divmmc0(
|
||||
.sd_sck(sd_sck),
|
||||
.sd_cs(sd_cs),
|
||||
|
||||
.rammap(port_dffd_d4 | port_1ffd[0]),
|
||||
.rammap(port_dffd[4] | port_1ffd[0]),
|
||||
.magic_mode(magic_mode),
|
||||
.magic_map(magic_map),
|
||||
|
||||
.div_page(div_page),
|
||||
.div_map(div_map),
|
||||
.div_ram(div_ram),
|
||||
.div_ramwr_mask(div_ramwr_mask),
|
||||
.div_wait(div_wait)
|
||||
.page(div_page),
|
||||
.map(div_map),
|
||||
.automap(div_automap),
|
||||
.ram(div_ram),
|
||||
.ramwr_mask(div_ramwr_mask),
|
||||
.cpuwait(div_wait)
|
||||
);
|
||||
assign sd_mosi = (~sd_cd)? sd_mosi0 : tape_out;
|
||||
|
||||
@ -422,7 +416,7 @@ assign sd_mosi = (~sd_cd)? sd_mosi0 : tape_out;
|
||||
wire up_dout_active;
|
||||
wire [7:0] up_dout;
|
||||
ulaplus ulaplus0(
|
||||
.rst_n(usrrst_n),
|
||||
.rst_n(n_rstcpu),
|
||||
.clk28(clk28),
|
||||
.en(up_en),
|
||||
|
||||
@ -484,77 +478,46 @@ asmi asmi0(
|
||||
|
||||
|
||||
/* MEMORY CONTROLLER */
|
||||
reg romreq, ramreq, ramreq_wr;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
romreq = 1'b0;
|
||||
ramreq = 1'b0;
|
||||
ramreq_wr = 1'b0;
|
||||
end
|
||||
else begin
|
||||
romreq = bus.mreq && !bus.rfsh && bus.a[14] == 0 && bus.a[15] == 0 &&
|
||||
(magic_map || (!div_ram && div_map) || (!div_ram && !port_dffd_d4 && !port_1ffd[0]));
|
||||
ramreq = bus.mreq && !bus.rfsh && !romreq;
|
||||
ramreq_wr = ramreq && bus.wr && div_ramwr_mask == 0;
|
||||
end
|
||||
end
|
||||
memcontrol memcontrol0(
|
||||
.rst_n(rst_n),
|
||||
.clk28(clk28),
|
||||
.bus(bus),
|
||||
.va(va),
|
||||
.vd(vd),
|
||||
.n_vrd(n_vrd),
|
||||
.n_vwr(n_vwr),
|
||||
|
||||
assign n_vrd = ((((ramreq || romreq) && bus.rd) || screen_fetch) && !rom2ram_ram_wren)? 1'b0 : 1'b1;
|
||||
assign n_vwr = ((ramreq_wr && bus.wr && !screen_fetch) || rom2ram_ram_wren)? 1'b0 : 1'b1;
|
||||
.machine(machine),
|
||||
.screenpage(screenpage),
|
||||
.screen_fetch(screen_fetch),
|
||||
.snow(snow),
|
||||
.screen_addr(screen_addr),
|
||||
.magic_map(magic_map),
|
||||
.rampage128(rampage128),
|
||||
.rompage128(rompage128),
|
||||
.port_1ffd(port_1ffd),
|
||||
.port_dffd(port_dffd),
|
||||
.rampage_ext(rampage_ext),
|
||||
.divmmc_en(divmmc_en != DIVMMC_OFF),
|
||||
.div_ram(div_ram),
|
||||
.div_map(div_map),
|
||||
.div_ramwr_mask(div_ramwr_mask),
|
||||
.div_page(div_page),
|
||||
|
||||
/* VA[18:13] map
|
||||
* 00xxxx 128Kb of roms
|
||||
* 00111x 16Kb of magic ram
|
||||
* 01xxxx 128Kb of divmmc memory
|
||||
* 10xxxx 128Kb of extended ram (via port dffd)
|
||||
* 11xxxx 128Kb of main ram
|
||||
*/
|
||||
|
||||
reg [18:13] ram_a;
|
||||
always @(posedge clk28) begin
|
||||
ram_a <=
|
||||
magic_map & bus.a[15] & bus.a[14]? {2'b00, 3'b111, bus.a[13]} :
|
||||
magic_map? {3'b111, screenpage, bus.a[14:13]} :
|
||||
div_map & ~bus.a[14] & ~bus.a[15] & bus.a[13]? {2'b01, div_page} :
|
||||
div_map & ~bus.a[14] & ~bus.a[15]? {2'b01, 4'b0011} :
|
||||
port_dffd_d3 & bus.a[15]? {2'b11, bus.a[14], bus.a[15], bus.a[14], bus.a[13]} :
|
||||
port_dffd_d3 & bus.a[14]? {1'b1, ~rampage_ext[0], rampage128, bus.a[13]} :
|
||||
(port_1ffd[2] == 1'b0 && port_1ffd[0] == 1'b1)? {2'b11, port_1ffd[1], bus.a[15], bus.a[14], bus.a[13]} :
|
||||
(port_1ffd == 3'b101)? {2'b11, ~(bus.a[15] & bus.a[14]), bus.a[15], bus.a[14]} :
|
||||
(port_1ffd == 3'b111)? {2'b11, ~(bus.a[15] & bus.a[14]), (bus.a[15] | bus.a[14]), bus.a[14]} :
|
||||
bus.a[15] & bus.a[14]? {1'b1, ~rampage_ext[0], rampage128, bus.a[13]} :
|
||||
{2'b11, bus.a[14], bus.a[15], bus.a[14], bus.a[13]} ;
|
||||
end
|
||||
|
||||
reg [16:14] rom_a;
|
||||
always @(posedge clk28) begin
|
||||
rom_a <=
|
||||
magic_map? 3'd2 :
|
||||
div_map? 3'd3 :
|
||||
(rom_plus3 && port_1ffd[2] == 1'b0 && rompage128 == 1'b0)? 3'd4 :
|
||||
(rom_plus3 && port_1ffd[2] == 1'b0 && rompage128 == 1'b1)? 3'd5 :
|
||||
(rom_plus3 && port_1ffd[2] == 1'b1 && rompage128 == 1'b0)? 3'd6 :
|
||||
(rompage128 == 1'b1 && rom_alt48 == 1'b1)? 3'd7 :
|
||||
(rompage128 == 1'b1)? 3'd1 :
|
||||
3'd0;
|
||||
end
|
||||
|
||||
assign va[18:0] =
|
||||
rom2ram_ram_wren? {2'b00, rom2ram_ram_address} :
|
||||
screen_fetch && snow? {3'b111, screenpage, screen_addr[14:8], {8{1'bz}}} :
|
||||
screen_fetch? {3'b111, screenpage, screen_addr} :
|
||||
romreq? {2'b00, rom_a[16:14], bus.a[13], {13{1'bz}}} :
|
||||
{ram_a[18:13], {13{1'bz}}};
|
||||
|
||||
assign vd[7:0] =
|
||||
~n_vrd? {8{1'bz}} :
|
||||
rom2ram_ram_wren? rom2ram_dataout :
|
||||
up_dout_active? up_dout :
|
||||
div_dout_active? div_dout :
|
||||
turbosound_dout_active? turbosound_dout :
|
||||
ports_dout_active? ports_dout :
|
||||
~n_wr? {8{1'bz}} :
|
||||
8'hFF;
|
||||
.rom2ram_ram_address(rom2ram_ram_address),
|
||||
.rom2ram_ram_wren(rom2ram_ram_wren),
|
||||
.rom2ram_dataout(rom2ram_dataout),
|
||||
.magic_dout_active(magic_dout_active),
|
||||
.magic_dout(magic_dout),
|
||||
.up_dout_active(up_dout_active),
|
||||
.up_dout(up_dout),
|
||||
.div_dout_active(div_dout_active),
|
||||
.div_dout(div_dout),
|
||||
.turbosound_dout_active(turbosound_dout_active),
|
||||
.turbosound_dout(turbosound_dout),
|
||||
.ports_dout_active(ports_dout_active),
|
||||
.ports_dout(ports_dout)
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
||||
|
Reference in New Issue
Block a user