1
0
mirror of https://github.com/UzixLS/zx-sizif-xxs.git synced 2025-07-18 23:01:40 +03:00
Files
zx-sizif-xxs/fpga/rtl/cpu.sv
Eugene Lozovoy c8d83ac5c1 refactor memory controller
Also this commit fixes ula+ io contention for classic timings. This
affects ham256.tap.
2024-01-08 20:15:34 +03:00

154 lines
4.0 KiB
Systemverilog

import common::*;
module cpu(
input rst_n,
input clk28,
input clk14,
input clk7,
input clk35,
input ck14,
input ck7,
cpu_bus bus,
input [8:0] vc,
input [8:0] hc,
input video_contention,
input [2:0] ram_page128,
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 reg n_int,
output reg n_int_next,
output snow,
output contention
);
/* CONTENTION */
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 @(posedge clkcpu)
mreq_delayed <= bus.mreq;
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 */
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
if (clkcpu != clk14)
turbo_wait_reg <= {turbo_wait_reg[1:0], turbo_wait_cond};
end
reg clkcpu_prev;
assign clkcpu_ck = clkcpu && !clkcpu_prev;
always @(posedge clk28) begin
clkcpu_prev <= clkcpu;
if (contention || hold || turbo_wait)
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 = 248;
localparam INT_H_S48 = 0;
localparam INT_L_S48 = 6'd32;
localparam INT_V_S128 = 248;
localparam INT_H_S128 = 4;
localparam INT_L_S128 = 6'd36;
localparam INT_V_PENT = 239;
localparam INT_H_PENT = 322;
localparam INT_L_PENT = 6'd32;
wire int_begin =
(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 :
// Pentagon
vc == INT_V_PENT && hc == INT_H_PENT ;
wire [5:0] int_len =
(machine == MACHINE_S48)?
INT_L_S48 :
(machine == MACHINE_S128 || machine == MACHINE_S3)?
INT_L_S128 :
// Pentagon
INT_L_PENT ;
reg [5:0] int_cnt;
always @(posedge clk28 or negedge rst_n) begin
if (!rst_n) begin
int_cnt <= 0;
n_int_next <= 1'b1;
end
else if ((int_cnt != 0 && clkcpu_ck) || (int_cnt == 0 && int_begin)) begin
int_cnt <= int_cnt + 1'b1;
n_int_next <= (int_cnt < int_len)? 1'b0 : 1'b1;
end
end
always @(posedge clk28 or negedge rst_n) begin
if (!rst_n)
n_int <= 1'b1;
else if (clkcpu_ck)
n_int <= n_int_next;
end
/* RESET */
always @(posedge clk28 or negedge rst_n) begin
if (!rst_n)
n_rstcpu_out <= 0;
else if (!init_done_in)
n_rstcpu_out <= 0;
`ifdef TESTBENCH
else if (hc[4])
n_rstcpu_out <= 1'b1;
`endif
else if (vc[8])
n_rstcpu_out <= 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