mirror of
https://github.com/UzixLS/zx-sizif-xxs.git
synced 2025-07-18 23:01:40 +03:00
refactor memory controller
Also this commit fixes ula+ io contention for classic timings. This affects ham256.tap.
This commit is contained in:
@ -16,6 +16,7 @@ interface cpu_bus();
|
||||
reg rd;
|
||||
reg wr;
|
||||
|
||||
wire ioreq;
|
||||
wire memreq;
|
||||
reg ioreq;
|
||||
reg memreq;
|
||||
reg memreq_rise;
|
||||
endinterface
|
||||
|
@ -17,53 +17,53 @@ module cpu(
|
||||
input machine_t machine,
|
||||
input turbo_t turbo,
|
||||
input init_done_in,
|
||||
input hold,
|
||||
|
||||
output reg n_rstcpu_out,
|
||||
output reg clkcpu,
|
||||
output clkcpu_ck,
|
||||
output clkcpu_stall,
|
||||
output reg n_int,
|
||||
output n_int_next,
|
||||
output snow
|
||||
output reg n_int_next,
|
||||
output snow,
|
||||
output contention
|
||||
);
|
||||
|
||||
|
||||
/* CONTENTION */
|
||||
wire iorq_contended = bus.iorq && (~bus.a[0] || (~bus.a[1] && ~bus.a_raw[15] && bus.wr)) && (machine != MACHINE_S3);
|
||||
wire iorq_contended = bus.ioreq && (~bus.a[0] || (bus.a == 16'hBF3B) || (bus.a == 16'hFF3B)) && (machine != MACHINE_S3);
|
||||
reg mreq_delayed, iorq_delayed;
|
||||
always @(negedge clk28) if (clkcpu_ck)
|
||||
always @(posedge clkcpu)
|
||||
mreq_delayed <= bus.mreq;
|
||||
always @(negedge clk28) if (clkcpu_ck)
|
||||
iorq_delayed <= bus.iorq && ~bus.a[0];
|
||||
wire contention_mem_page = (machine == MACHINE_S3)? ram_page128[2] : ram_page128[0];
|
||||
wire contention_mem_addr = bus.a_raw[14] & (~bus.a_raw[15] | (bus.a_raw[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 && iorq_contended;
|
||||
wire contention0 = video_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_raw[14] && ~bus.a_raw[15] && bus.rfsh && (machine == MACHINE_S48 || machine == MACHINE_S128);
|
||||
always @(posedge clkcpu)
|
||||
iorq_delayed <= iorq_contended;
|
||||
wire contention_page = (machine == MACHINE_S3)? ram_page128[2] : ram_page128[0];
|
||||
wire contention_addr = bus.a_raw[14] & (~bus.a_raw[15] | (bus.a_raw[15] & contention_page));
|
||||
wire contention_mem = !iorq_contended && !mreq_delayed && contention_addr;
|
||||
wire contention0 = video_contention && !iorq_delayed && (contention_mem || iorq_contended);
|
||||
assign contention = clkcpu && contention0 && turbo == TURBO_NONE && (machine == MACHINE_S48 || machine == MACHINE_S128 || machine == MACHINE_S3);
|
||||
assign snow = video_contention && contention_addr && bus.rfsh && bus.mreq && (machine == MACHINE_S48 || machine == MACHINE_S128);
|
||||
|
||||
|
||||
/* CLOCK */
|
||||
reg [3:0] turbo_wait;
|
||||
wire turbo_wait_trig0 = turbo == TURBO_14 && bus.mreq && !bus.rfsh;
|
||||
wire turbo_wait_trig1 = turbo == TURBO_14 && (bus.rd || bus.wr);
|
||||
reg turbo_wait_trig0_prev, turbo_wait_trig1_prev;
|
||||
wire turbo_wait_cond = turbo == TURBO_14 && (bus.rd || bus.wr || (bus.iorq && bus.m1));
|
||||
reg [2:0] turbo_wait_reg;
|
||||
reg turbo_wait;
|
||||
always @* begin
|
||||
if (bus.iorq)
|
||||
turbo_wait <= turbo_wait_cond && !turbo_wait_reg[2];
|
||||
else
|
||||
turbo_wait <= turbo_wait_cond && !turbo_wait_reg[1];
|
||||
end
|
||||
always @(posedge clk28) begin
|
||||
turbo_wait[0] <= turbo_wait_trig0 && !turbo_wait_trig0_prev;
|
||||
turbo_wait[1] <= turbo_wait[0] || (turbo_wait_trig1 && !turbo_wait_trig1_prev);
|
||||
turbo_wait[2] <= turbo_wait[1];
|
||||
turbo_wait[3] <= turbo_wait[2];
|
||||
turbo_wait_trig0_prev <= turbo_wait_trig0;
|
||||
turbo_wait_trig1_prev <= turbo_wait_trig1;
|
||||
if (clkcpu != clk14)
|
||||
turbo_wait_reg <= {turbo_wait_reg[1:0], turbo_wait_cond};
|
||||
end
|
||||
|
||||
reg clkcpu_prev;
|
||||
assign clkcpu_ck = clkcpu && !clkcpu_prev;
|
||||
assign clkcpu_stall = contention || (|turbo_wait[3:1]);
|
||||
always @(posedge clk28) begin
|
||||
clkcpu_prev <= clkcpu;
|
||||
if (clkcpu_stall)
|
||||
if (contention || hold || turbo_wait)
|
||||
clkcpu <= clkcpu;
|
||||
else if (turbo == TURBO_14)
|
||||
clkcpu <= clk14;
|
||||
|
@ -27,17 +27,17 @@ module divmmc(
|
||||
output reg mapram,
|
||||
output ram,
|
||||
output ramwr_mask,
|
||||
output cpuwait
|
||||
output ext_wait_cycle2
|
||||
);
|
||||
|
||||
|
||||
reg automap0, automap_next;
|
||||
reg automap, automap_next;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
automap_next <= 0;
|
||||
automap0 <= 0;
|
||||
automap <= 0;
|
||||
end
|
||||
else if (bus.m1 && bus.memreq && !mask_hooks) begin
|
||||
else if (bus.m1 && bus.memreq_rise && !mask_hooks) begin
|
||||
if (!en_hooks || !en || rammap) begin
|
||||
automap_next <= 0;
|
||||
end
|
||||
@ -56,18 +56,14 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
end
|
||||
else if (bus.a[15:8] == 8'h3D) begin // tr-dos mapping area
|
||||
automap_next <= 1'b1;
|
||||
automap0 <= 1'b1;
|
||||
automap <= 1'b1;
|
||||
end
|
||||
end
|
||||
else if (!bus.m1) begin
|
||||
automap0 <= automap_next;
|
||||
automap <= automap_next;
|
||||
end
|
||||
end
|
||||
|
||||
// #3Dxx entrypoint is critical for timings, so we're arming 'map' signal as soon as possible
|
||||
wire automap = automap0 || (bus.m1 && bus.memreq && !mask_hooks && en_hooks && en && !rammap && bus.a[15:8] == 8'h3D);
|
||||
|
||||
|
||||
reg conmem;
|
||||
wire port_e3_cs = en && bus.ioreq && bus.a[7:0] == 8'hE3;
|
||||
wire port_e7_cs = en && bus.ioreq && bus.a[7:0] == 8'hE7;
|
||||
@ -111,7 +107,7 @@ end
|
||||
|
||||
reg [3:0] spi_cnt;
|
||||
wire spi_cnt_en = ~spi_cnt[3] | spi_cnt[2] | spi_cnt[1] | spi_cnt[0];
|
||||
assign cpuwait = ~spi_cnt[3];
|
||||
assign ext_wait_cycle2 = ~spi_cnt[3];
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n)
|
||||
spi_cnt <= 0;
|
||||
|
@ -16,7 +16,7 @@ module magic(
|
||||
input div_paged,
|
||||
|
||||
output reg magic_mode,
|
||||
output magic_map,
|
||||
output reg magic_map,
|
||||
|
||||
output reg magic_reboot,
|
||||
output reg magic_beeper,
|
||||
@ -37,12 +37,11 @@ localparam magic_on_start = 1'b1;
|
||||
|
||||
reg magic_unmap_next;
|
||||
reg magic_map_next;
|
||||
reg magic_map0;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
n_nmi <= 1'b1;
|
||||
magic_mode <= magic_on_start;
|
||||
magic_map0 <= magic_on_start;
|
||||
magic_map <= magic_on_start;
|
||||
magic_map_next <= 0;
|
||||
magic_unmap_next <= 0;
|
||||
end
|
||||
@ -53,29 +52,26 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
magic_mode <= 1'b1;
|
||||
end
|
||||
|
||||
if (magic_map0 && bus.memreq && bus.rd && bus.a == 16'hf000 && !magic_map_next) begin
|
||||
if (magic_map && bus.memreq && bus.rd && bus.a == 16'hf000 && !magic_map_next) begin
|
||||
magic_unmap_next <= 1'b1;
|
||||
magic_mode <= 1'b0;
|
||||
end
|
||||
else if (magic_map0 && bus.memreq && bus.rd && bus.a == 16'hf008) begin
|
||||
else if (magic_map && bus.memreq && bus.rd && bus.a == 16'hf008) begin
|
||||
magic_unmap_next <= 1'b1;
|
||||
magic_map_next <= 1'b1;
|
||||
end
|
||||
else if (magic_unmap_next && !bus.memreq) begin
|
||||
magic_map0 <= 1'b0;
|
||||
magic_map <= 1'b0;
|
||||
magic_unmap_next <= 1'b0;
|
||||
end
|
||||
else if (magic_mode && bus.m1 && bus.memreq && (bus.a == 16'h0066 || magic_map_next)) begin
|
||||
else if (magic_mode && bus.m1 && bus.memreq_rise && (bus.a == 16'h0066 || magic_map_next)) begin
|
||||
n_nmi <= 1'b1;
|
||||
magic_map0 <= 1'b1;
|
||||
magic_map <= 1'b1;
|
||||
magic_map_next <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// this signal is critical for timings, so we're arming it as soon as possible
|
||||
assign magic_map = magic_map0 || (magic_mode && bus.m1 && bus.memreq && (bus.a == 16'h0066 || magic_map_next) && !magic_unmap_next);
|
||||
|
||||
|
||||
/* MAGIC CONFIG */
|
||||
wire config_cs = magic_map && bus.ioreq && bus.a[7:0] == 8'hFF;
|
||||
|
129
fpga/rtl/mem.sv
129
fpga/rtl/mem.sv
@ -1,13 +1,19 @@
|
||||
import common::*;
|
||||
module mem(
|
||||
input rst_n,
|
||||
input clk28,
|
||||
cpu_bus bus,
|
||||
output [18:0] va,
|
||||
output reg [18:0] va,
|
||||
inout [7:0] vd,
|
||||
output n_vrd,
|
||||
output n_vwr,
|
||||
output reg n_vrd,
|
||||
output reg n_vwr,
|
||||
|
||||
output bus_valid,
|
||||
output cpuwait,
|
||||
|
||||
input machine_t machine,
|
||||
input turbo_t turbo,
|
||||
input cpu_contention,
|
||||
input magic_map,
|
||||
input [2:0] ram_page128,
|
||||
input rom_page128,
|
||||
@ -23,10 +29,13 @@ module mem(
|
||||
input video_page,
|
||||
input video_read_req,
|
||||
input [14:0] video_read_addr,
|
||||
output video_read_req_ack,
|
||||
output video_data_valid,
|
||||
|
||||
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,
|
||||
@ -51,11 +60,11 @@ module mem(
|
||||
reg romreq, ramreq, ramreq_wr;
|
||||
reg [18:13] va_18_13;
|
||||
wire [15:0] a = bus.a_raw[15:0];
|
||||
always @(negedge clk28) begin
|
||||
romreq = bus.mreq && a[15:14] == 2'b00 &&
|
||||
always @* begin
|
||||
romreq = a[15:14] == 2'b00 &&
|
||||
(magic_map || (!div_ram && div_map) || (!div_ram && !port_dffd[4] && !port_1ffd[0]));
|
||||
ramreq = bus.mreq && !romreq;
|
||||
ramreq_wr = ramreq && bus.wr && div_ramwr_mask == 0;
|
||||
ramreq = !romreq;
|
||||
ramreq_wr = ramreq && div_ramwr_mask == 0;
|
||||
|
||||
if (romreq) va_18_13 =
|
||||
(magic_map) ? {5'd2, 1'b0} :
|
||||
@ -80,15 +89,6 @@ always @(negedge clk28) begin
|
||||
{2'b11, a[14], a[15], a[14], a[13]} ;
|
||||
end
|
||||
|
||||
assign n_vrd = (((bus.mreq && bus.rd) || video_read_req) && !rom2ram_ram_wren)? 1'b0 : 1'b1;
|
||||
assign n_vwr = ((ramreq_wr && bus.wr && !video_read_req) || rom2ram_ram_wren)? 1'b0 : 1'b1;
|
||||
|
||||
assign va[18:0] =
|
||||
(rom2ram_ram_wren) ? {2'b00, rom2ram_ram_address} :
|
||||
(video_read_req && snow) ? {3'b111, video_page, video_read_addr[14:8], {8{1'bz}}} :
|
||||
(video_read_req) ? {3'b111, video_page, video_read_addr} :
|
||||
{va_18_13, {13{1'bz}}};
|
||||
|
||||
assign vd[7:0] =
|
||||
~n_vrd ? {8{1'bz}} :
|
||||
bus.wr ? {8{1'bz}} :
|
||||
@ -102,5 +102,102 @@ assign vd[7:0] =
|
||||
bus.rd ? 8'hFF :
|
||||
{8{1'bz}} ;
|
||||
|
||||
localparam BUS_VALID_LATENCY = 2'd1;
|
||||
reg [1:0] bus_valid_step;
|
||||
localparam LATENCY = 2'd2;
|
||||
reg [1:0] step;
|
||||
localparam REQ_NONE = 3'd0;
|
||||
localparam REQ_CPU_RD = 3'd1;
|
||||
localparam REQ_CPU_WR = 3'd2;
|
||||
localparam REQ_VIDEO_RD = 3'd3;
|
||||
localparam REQ_ROM2RAM_WR = 3'd4;
|
||||
reg [2:0] current_req;
|
||||
reg cpuwait_reg;
|
||||
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
va <= {va_18_13, {13{1'bz}}};
|
||||
n_vrd <= 1'b1;
|
||||
n_vwr <= 1'b1;
|
||||
cpuwait_reg <= 0;
|
||||
bus_valid_step <= 0;
|
||||
step <= 0;
|
||||
current_req <= REQ_NONE;
|
||||
end
|
||||
else begin
|
||||
if (step)
|
||||
step <= step - 1'd1;
|
||||
if (bus_valid_step)
|
||||
bus_valid_step <= bus_valid_step - 1'd1;
|
||||
if (!(bus.mreq && bus.rd))
|
||||
cpuwait_reg <= 0;
|
||||
|
||||
if (rom2ram_ram_wren) begin
|
||||
if (current_req != REQ_ROM2RAM_WR)
|
||||
step <= LATENCY;
|
||||
va <= {2'b00, rom2ram_ram_address};
|
||||
n_vrd <= 1'b1;
|
||||
n_vwr <= (current_req == REQ_ROM2RAM_WR && step == 0)? 1'b1 : 1'b0;
|
||||
bus_valid_step <= BUS_VALID_LATENCY;
|
||||
current_req <= REQ_ROM2RAM_WR;
|
||||
end
|
||||
else if (turbo == TURBO_14 && current_req == REQ_VIDEO_RD && step) begin
|
||||
// complete current request
|
||||
bus_valid_step <= BUS_VALID_LATENCY;
|
||||
end
|
||||
else if (bus.mreq && bus.wr && ramreq_wr) begin
|
||||
if (current_req != REQ_CPU_WR)
|
||||
step <= LATENCY;
|
||||
va <= {va_18_13, {13{1'bz}}};
|
||||
n_vrd <= 1'b1;
|
||||
n_vwr <= (current_req == REQ_CPU_WR && step == 0)? 1'b1 : 1'b0;
|
||||
current_req <= REQ_CPU_WR;
|
||||
end
|
||||
else if (bus.mreq && bus.rd) begin
|
||||
if (current_req != REQ_CPU_RD) begin
|
||||
step <= LATENCY;
|
||||
end
|
||||
else if (va[18:13] != va_18_13) begin
|
||||
cpuwait_reg <= 1'b1;
|
||||
step <= LATENCY;
|
||||
end
|
||||
else if (!step) begin
|
||||
cpuwait_reg <= 1'b0;
|
||||
end
|
||||
va <= {va_18_13, {13{1'bz}}};
|
||||
n_vrd <= 1'b0;
|
||||
n_vwr <= 1'b1;
|
||||
current_req <= REQ_CPU_RD;
|
||||
end
|
||||
else if ((bus.mreq || bus.iorq) && !bus.rfsh && !cpu_contention) begin
|
||||
va <= {va_18_13, {13{1'bz}}};
|
||||
n_vrd <= 1'b1;
|
||||
n_vwr <= 1'b1;
|
||||
current_req <= REQ_NONE;
|
||||
end
|
||||
else if (video_read_req) begin
|
||||
if (current_req != REQ_VIDEO_RD || !step)
|
||||
step <= LATENCY;
|
||||
va <= snow? {3'b111, video_page, video_read_addr[14:7], {7{1'bz}}} :
|
||||
{3'b111, video_page, video_read_addr} ;
|
||||
n_vrd <= 1'b0;
|
||||
n_vwr <= 1'b1;
|
||||
bus_valid_step <= BUS_VALID_LATENCY;
|
||||
current_req <= REQ_VIDEO_RD;
|
||||
end
|
||||
else begin
|
||||
va <= {va_18_13, {13{1'bz}}};
|
||||
n_vrd <= 1'b1;
|
||||
n_vwr <= 1'b1;
|
||||
current_req <= REQ_NONE;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign cpuwait = cpuwait_reg || (bus.mreq && bus.rd && current_req == REQ_CPU_RD && va[18:13] != va_18_13);
|
||||
assign bus_valid = bus_valid_step == 0;
|
||||
assign video_data_valid = current_req == REQ_VIDEO_RD && step == 0;
|
||||
assign video_read_req_ack = current_req == REQ_VIDEO_RD && step == 1'd1 && (!((bus.mreq || bus.iorq) && !bus.rfsh && !cpu_contention) || turbo == TURBO_14);
|
||||
|
||||
|
||||
endmodule
|
||||
|
@ -58,30 +58,16 @@ wire ps2_key_reset, ps2_key_pause;
|
||||
wire [2:0] border;
|
||||
wire magic_reboot, magic_beeper;
|
||||
wire up_active;
|
||||
wire clkcpu_stall;
|
||||
wire [2:0] ram_page128;
|
||||
wire init_done;
|
||||
wire video_read_req, video_read_req_next;
|
||||
wire mem_bus_valid;
|
||||
wire mem_wait;
|
||||
wire sd_indication;
|
||||
|
||||
|
||||
/* CPU BUS */
|
||||
cpu_bus bus();
|
||||
reg bus_memreq, bus_ioreq;
|
||||
wire mem_bus_valid = !video_read_req && !video_read_req_next;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
bus_ioreq <= 0;
|
||||
bus_memreq <= 0;
|
||||
end
|
||||
else begin
|
||||
bus.a <= mem_bus_valid? {a[15:13], va[12:0]} : bus.a;
|
||||
bus.d <= mem_bus_valid? vd : bus.d;
|
||||
bus_ioreq <= (mem_bus_valid | bus_ioreq) & ~n_iorq & n_m1;
|
||||
bus_memreq <= (mem_bus_valid | bus_memreq) & ~n_mreq & n_rfsh;
|
||||
end
|
||||
end
|
||||
always @(posedge clk168) begin
|
||||
always @(negedge clk28) begin
|
||||
bus.a_raw <= {a[15:13], va[12:0]};
|
||||
bus.iorq <= ~n_iorq;
|
||||
bus.mreq <= ~n_mreq;
|
||||
@ -90,8 +76,13 @@ always @(posedge clk168) begin
|
||||
bus.rd <= ~n_rd;
|
||||
bus.wr <= ~n_wr;
|
||||
end
|
||||
assign bus.ioreq = bus_ioreq & bus.iorq;
|
||||
assign bus.memreq = bus_memreq & bus.mreq;
|
||||
always @(posedge clk28) begin
|
||||
bus.a <= mem_bus_valid? {a[15:13], va[12:0]} : bus.a;
|
||||
bus.d <= mem_bus_valid? vd : bus.d;
|
||||
bus.ioreq <= (mem_bus_valid | bus.ioreq) & ~n_iorq & n_m1;
|
||||
bus.memreq <= (mem_bus_valid | bus.memreq) & ~n_mreq & n_rfsh;
|
||||
bus.memreq_rise <= mem_bus_valid & ~bus.memreq & ~n_mreq & n_rfsh;
|
||||
end
|
||||
|
||||
|
||||
/* RESET */
|
||||
@ -105,6 +96,7 @@ end
|
||||
wire [5:0] r, g, b;
|
||||
wire hsync, vsync, csync0;
|
||||
wire video_contention, port_ff_active;
|
||||
wire video_read_req, video_read_req_ack, video_read_data_valid;
|
||||
wire [14:0] video_read_addr;
|
||||
wire [5:0] up_ink_addr, up_paper_addr;
|
||||
wire [7:0] up_ink_data, up_paper_data;
|
||||
@ -116,7 +108,6 @@ video video0(
|
||||
.clk28(clk28),
|
||||
|
||||
.machine(machine),
|
||||
.turbo(turbo),
|
||||
.border({border[2] ^ sd_indication, border[1] ^ magic_beeper, border[0]}),
|
||||
|
||||
.r(r),
|
||||
@ -126,10 +117,10 @@ video video0(
|
||||
.vsync(vsync),
|
||||
.hsync(hsync),
|
||||
|
||||
.read_allow((!bus.iorq && !bus.mreq) || bus.rfsh || (clkcpu_stall && turbo == TURBO_NONE)),
|
||||
.read_req(video_read_req),
|
||||
.read_req_next(video_read_req_next),
|
||||
.read_req_addr(video_read_addr),
|
||||
.read_req_ack(video_read_req_ack),
|
||||
.read_data_valid(video_read_data_valid),
|
||||
.read_data(vd),
|
||||
|
||||
.up_en(up_active),
|
||||
@ -190,7 +181,7 @@ ps2 #(.CLK_FREQ(28_000_000)) ps2_0(
|
||||
|
||||
|
||||
/* CPU CONTROLLER */
|
||||
wire n_int_next, clkcpu_ck, snow;
|
||||
wire n_int_next, clkcpu_ck, snow, cpu_contention;
|
||||
cpu cpu0(
|
||||
.rst_n(usrrst_n),
|
||||
.clk28(clk28),
|
||||
@ -207,16 +198,17 @@ cpu cpu0(
|
||||
.ram_page128(ram_page128),
|
||||
.machine(machine),
|
||||
.turbo(turbo),
|
||||
.hold(mem_wait),
|
||||
.video_contention(video_contention),
|
||||
.init_done_in(init_done),
|
||||
|
||||
.n_rstcpu_out(n_rstcpu),
|
||||
.clkcpu(clkcpu),
|
||||
.clkcpu_ck(clkcpu_ck),
|
||||
.clkcpu_stall(clkcpu_stall),
|
||||
.n_int(n_int),
|
||||
.n_int_next(n_int_next),
|
||||
.snow(snow)
|
||||
.snow(snow),
|
||||
.contention(cpu_contention)
|
||||
);
|
||||
|
||||
|
||||
@ -479,6 +471,7 @@ asmi asmi0(
|
||||
|
||||
/* MEMORY CONTROLLER */
|
||||
mem mem0(
|
||||
.rst_n(rst_n),
|
||||
.clk28(clk28),
|
||||
.bus(bus),
|
||||
.va(va),
|
||||
@ -486,7 +479,12 @@ mem mem0(
|
||||
.n_vrd(n_vrd),
|
||||
.n_vwr(n_vwr),
|
||||
|
||||
.bus_valid(mem_bus_valid),
|
||||
.cpuwait(mem_wait),
|
||||
|
||||
.machine(machine),
|
||||
.turbo(turbo),
|
||||
.cpu_contention(cpu_contention),
|
||||
.magic_map(magic_map),
|
||||
.ram_page128(ram_page128),
|
||||
.rom_page128(rom_page128),
|
||||
@ -502,6 +500,8 @@ mem mem0(
|
||||
.video_page(video_page),
|
||||
.video_read_req(video_read_req),
|
||||
.video_read_addr(video_read_addr),
|
||||
.video_read_req_ack(video_read_req_ack),
|
||||
.video_data_valid(video_read_data_valid),
|
||||
|
||||
.rom2ram_ram_address(rom2ram_ram_address),
|
||||
.rom2ram_ram_wren(rom2ram_ram_wren),
|
||||
|
@ -4,7 +4,6 @@ module video(
|
||||
input clk28,
|
||||
|
||||
input machine_t machine,
|
||||
input turbo_t turbo,
|
||||
input [2:0] border,
|
||||
|
||||
output reg [5:0] r,
|
||||
@ -14,10 +13,10 @@ module video(
|
||||
output reg hsync,
|
||||
output reg csync,
|
||||
|
||||
input read_allow,
|
||||
output reg read_req,
|
||||
output read_req_next,
|
||||
output read_req,
|
||||
output [14:0] read_req_addr,
|
||||
input read_req_ack,
|
||||
input read_data_valid,
|
||||
input [7:0] read_data,
|
||||
|
||||
output contention,
|
||||
@ -179,7 +178,7 @@ wire screen_show = (vc < V_AREA) && (hc0 >= (SCREEN_DELAY<<2) - 1) && (hc0 < ((H
|
||||
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'b10000;
|
||||
wire next_addr = hc0[4:0] == 5'b10001;
|
||||
|
||||
reg screen_read, up_read;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
@ -188,7 +187,7 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
up_read <= 0;
|
||||
end
|
||||
else begin
|
||||
screen_read <= (vc < V_AREA) && (hc0 > 15) && (hc0 < (H_AREA<<2) + 17);
|
||||
screen_read <= (vc < V_AREA) && (hc0 > 17) && (hc0 < (H_AREA<<2) + 17);
|
||||
up_read <= screen_read && (screen_update || up_read);
|
||||
end
|
||||
end
|
||||
@ -209,41 +208,39 @@ end
|
||||
reg [7:0] bitmap, attr, bitmap_next, attr_next;
|
||||
reg [7:0] up_ink, up_paper;
|
||||
|
||||
reg [1:0] read_cnt;
|
||||
localparam READ_CYCLES = 2'd2;
|
||||
assign read_req_next = screen_read && (read_allow || (|read_cnt && read_cnt != READ_CYCLES && turbo == TURBO_14));
|
||||
|
||||
reg read_step;
|
||||
assign read_req_addr = (read_step == 1'd0)?
|
||||
reg read_step, read_step_cur;
|
||||
assign read_req = 1'b1; // just to simplify logic
|
||||
assign read_req_addr = (read_step == 1'd1)?
|
||||
{ 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 = up_read? { attr_next[7:6], 1'b0, attr_next[2:0] } : { 3'b0, border[2:0] };
|
||||
assign up_ink_addr = up_read? { attr_next[7:6], 1'b0, attr_next[2:0] } : { 3'b0, border[2:0] };
|
||||
assign up_paper_addr = up_read? { attr_next[7:6], 1'b1, attr_next[5:3] } : { 3'b0, border[2:0] };
|
||||
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
read_req <= 0;
|
||||
read_step <= 0;
|
||||
read_cnt <= 0;
|
||||
read_step_cur <= 0;
|
||||
attr_next <= 0;
|
||||
bitmap_next <= 0;
|
||||
end
|
||||
else begin
|
||||
read_req <= read_req_next;
|
||||
if (read_cnt == READ_CYCLES) begin
|
||||
if (read_step == 1'd1)
|
||||
attr_next <= read_data;
|
||||
if (read_step == 1'd0)
|
||||
bitmap_next <= read_data;
|
||||
read_step <= read_step + 1'b1;
|
||||
read_cnt <= 0;
|
||||
end
|
||||
else if (read_req && read_req_next && !next_addr) begin
|
||||
read_cnt <= read_cnt + 1'b1;
|
||||
end
|
||||
else begin
|
||||
read_cnt <= 0;
|
||||
end
|
||||
if (next_addr)
|
||||
read_step <= 0;
|
||||
else if (read_req_ack)
|
||||
read_step <= read_step + 1'd1;
|
||||
|
||||
if (read_req_ack)
|
||||
read_step_cur <= read_step;
|
||||
|
||||
if (read_data_valid && read_step_cur == 2'd0 && screen_read)
|
||||
attr_next <= read_data;
|
||||
else if (!screen_read && hc0[0])
|
||||
attr_next <= {2'b00, border[2:0], border[2:0]};
|
||||
|
||||
if (read_data_valid && read_step_cur == 2'd1 && screen_read)
|
||||
bitmap_next <= read_data;
|
||||
else if (!screen_read && hc0[0])
|
||||
bitmap_next <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -44,13 +44,21 @@ Loop:
|
||||
|
||||
ORG #8000 // mapped #0000
|
||||
MagicROM_Start:
|
||||
ld sp, #8000
|
||||
ld bc, #09ff ; divmmc = 1
|
||||
ld a, 1 ; ...
|
||||
out (c), a ; ...
|
||||
ld bc, #03ff ; cpu freq = 7mhz
|
||||
ld a, 3 ; ...
|
||||
ld bc, #02ff ; machine = 128
|
||||
ld a, 1 ; ...
|
||||
out (c), a ; ...
|
||||
ld bc, #03ff ; cpu freq = 14mhz
|
||||
ld a, 4 ; ...
|
||||
out (c), a ; ...
|
||||
.100 in a, (#fe)
|
||||
ld bc, #0000
|
||||
ld de, #5000
|
||||
ld hl, #6000
|
||||
ldir
|
||||
push bc
|
||||
jp #f008
|
||||
ORG #F000
|
||||
|
Reference in New Issue
Block a user