mirror of
https://github.com/UzixLS/zx-sizif-xxs.git
synced 2025-07-18 23:01:40 +03:00
154 lines
4.0 KiB
Systemverilog
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
|