1
0
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:
UzixLS
2021-09-21 19:57:59 +03:00
parent 83081238ed
commit 0e572d9d69
28 changed files with 1183 additions and 645 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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