mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-04-27 12:49:15 +00:00
add Commen Units
This commit is contained in:
1460
common/CPU/FZ80/fz80.v
Normal file
1460
common/CPU/FZ80/fz80.v
Normal file
File diff suppressed because it is too large
Load Diff
459
common/CPU/FZ80/fz80c.v
Normal file
459
common/CPU/FZ80/fz80c.v
Normal file
@@ -0,0 +1,459 @@
|
||||
//
|
||||
// Z80 Compatible Bus wrapper for fz80 ver.0.52
|
||||
//
|
||||
// Version 0.52a
|
||||
//
|
||||
// Copyright (c) 2004 Tatsuyuki Sato
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
/*
|
||||
note:
|
||||
|
||||
It should be necessary to set "`define M1" inf fz80.
|
||||
---------------------------------------------------
|
||||
|
||||
-----------------------------
|
||||
non-compatible spesification.
|
||||
-----------------------------
|
||||
|
||||
1.no internal cycle
|
||||
A internal cycle without bus cycle doesn't exist.
|
||||
So some instruction is faster than Z80.
|
||||
|
||||
2.ealy tristate after reset
|
||||
The "at" and "dt" assert after 1cycle from reset.
|
||||
The Z80 is after 2cycles from reset.
|
||||
|
||||
3.busreq/busack timming are not checked yet.
|
||||
|
||||
4.halt always output 1(no supported).
|
||||
|
||||
-------------
|
||||
state changes
|
||||
-------------
|
||||
+------+---+---+---+---+---+---+
|
||||
|state |t1w|t1 |t2w|t2 |t3 |t4 |
|
||||
+------+---+---+---+---+---+---+
|
||||
| M1 | - | O | - | O*| O | O |
|
||||
| MEM | - | O | - | O*| x | O |
|
||||
| IO | - | O | - | O*| x | O |
|
||||
| SpM1 | O | O | O | O | O | O |
|
||||
+------+---+---+---+---+---+---+
|
||||
*:sense wait (wait cycle)
|
||||
|
||||
histry:
|
||||
2004. 9.16 ver.0.52a
|
||||
bugfix power on reset error.
|
||||
halt_n output always 1 (do not supported yet)
|
||||
change `MREQ_INSIDE_RD logic.
|
||||
|
||||
2004. 9.10 ver.0.52
|
||||
added power on reset
|
||||
bugfix mreq inside rd mode
|
||||
2004. 9. 9 ver.0.51
|
||||
1st test version
|
||||
*/
|
||||
|
||||
//`define FZ80C_NGC_LINK // xilinx XST link synthesized fz80c.v
|
||||
//`define DEBUG_OUTPUT
|
||||
|
||||
// ----- design option -----
|
||||
`define MREQ_INSIDE_RD // for wr = (rfsh & ~mreq_n & rd_n);
|
||||
//`define FZ80C_POWER_ON_RESET // power on self reset
|
||||
//`define DISABLE_BUSREQ_SYNC // bypass busreq/busack syncronize.
|
||||
//`define DISABLE_REFRESH_CYCLE // no rfsh cycle & inst code fetch t4 raise
|
||||
//`define NMI_SYNC_SENSE // nmi fall sense with clk
|
||||
//`define DO_VAL_IF_DT 8'h00 // "do" set fixed value when output disable
|
||||
|
||||
module fz80c (/*AUTOARG*/
|
||||
// Inputs
|
||||
reset_n, clk, wait_n, int_n, nmi_n, busrq_n, di,
|
||||
// Outputs
|
||||
m1_n, mreq_n, iorq_n, rd_n, wr_n, rfsh_n, halt_n, busak_n,
|
||||
`ifdef DEBUG_OUTPUT
|
||||
ts,
|
||||
wait_window,
|
||||
`endif
|
||||
A, At,
|
||||
do,dt
|
||||
);
|
||||
|
||||
input reset_n,clk;
|
||||
input wait_n , busrq_n;
|
||||
input int_n,nmi_n;
|
||||
input [7:0] di;
|
||||
|
||||
output m1_n;
|
||||
output mreq_n;
|
||||
output iorq_n;
|
||||
output rd_n;
|
||||
output wr_n;
|
||||
output rfsh_n;
|
||||
output halt_n;
|
||||
output busak_n; // (enable controll : mreq_n,iorq_n,rd_n,wr_n,rfsh_n)
|
||||
output [15:0] A; // Address Bus
|
||||
output [7:0] do; // Data Bus
|
||||
output dt; // tristate controll : do
|
||||
output At; // tristate controll : A
|
||||
|
||||
`ifdef DEBUG_OUTPUT
|
||||
output [3:0] ts;
|
||||
output wait_window;
|
||||
`endif
|
||||
|
||||
`ifndef FZ80C_NGC_LINK
|
||||
|
||||
// internal register
|
||||
reg [15:0] A;
|
||||
reg [7:0] dinst_r;
|
||||
reg [7:0] do_r;
|
||||
reg [3:0] ts;
|
||||
reg reset_s;
|
||||
reg m1_r;
|
||||
`ifndef DISABLE_REFRESH_CYCLE
|
||||
reg rfsh_r;
|
||||
`endif
|
||||
reg mreq_r;
|
||||
reg iorq_r;
|
||||
reg wr_r;
|
||||
reg rd_r;
|
||||
reg wait_r;
|
||||
reg dt_r,dt_t4;
|
||||
`ifndef DISABLE_BUSREQ_SYNC
|
||||
reg at_r;
|
||||
reg busack_r;
|
||||
reg busreq_r;
|
||||
`endif
|
||||
|
||||
//reg halt_r;
|
||||
|
||||
`ifdef NMI_SYNC_SENSE
|
||||
reg nmi_r1,nmi_r2;
|
||||
`endif
|
||||
|
||||
// auto wait
|
||||
reg tw1,tw2;
|
||||
|
||||
// gate signal base
|
||||
reg t3l;
|
||||
reg t04l;
|
||||
|
||||
`ifdef FZ80C_POWER_ON_RESET
|
||||
reg por_n = 0;
|
||||
reg por2_n = 0;
|
||||
`endif
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// FZ80
|
||||
//////////////////////////////////////////////////////////////
|
||||
wire start;
|
||||
wire mreq;
|
||||
wire iorq;
|
||||
wire rd;
|
||||
wire wr;
|
||||
wire busack;
|
||||
wire waitreq;
|
||||
reg intreq;
|
||||
reg nmireq;
|
||||
wire busreq;
|
||||
wire m1;
|
||||
//wire [7:0] data_in = m1 ? dinst_r : di;
|
||||
wire [7:0] data_in = ~rfsh_n ? dinst_r : di;
|
||||
wire [7:0] data_out;
|
||||
wire [15:0] adr ,radr;
|
||||
wire nmiack;
|
||||
//wire halt;
|
||||
|
||||
// mreq,iorq inside in rd_wr
|
||||
//wire req_mask =
|
||||
|
||||
fz80 fz80(
|
||||
.data_in(data_in),
|
||||
.reset_in(reset_s),
|
||||
.clk(~clk),
|
||||
.adr(adr),
|
||||
.intreq(intreq),
|
||||
.nmireq(nmireq),
|
||||
.busreq(busreq),
|
||||
.start(start),
|
||||
.mreq(mreq),
|
||||
.iorq(iorq),
|
||||
.rd(rd),
|
||||
.wr(wr),
|
||||
.data_out(data_out),
|
||||
.busack_out(busack),
|
||||
.intack_out(),
|
||||
.mr(),
|
||||
|
||||
.m1(m1),
|
||||
// .halt(halt),
|
||||
.radr(radr),
|
||||
.nmiack_out(nmiack),
|
||||
.waitreq(waitreq)
|
||||
);
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// wires
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
// state value
|
||||
wire t0 = ts[3:0]==0; // t0 : reset cycle
|
||||
wire t1 = ts[0]; // t1 : spM1 = t1&t2
|
||||
wire t2 = ts[1]; // t2 : spM1 = tw(1,2)
|
||||
wire t3 = ts[2]; // M1.t3
|
||||
wire t4 = ts[3]; // M1.t4 or MEM/IO.t3
|
||||
|
||||
wire t04 = ~t1 & ~t2 & ~t3; // T0 or T4
|
||||
|
||||
`ifdef DEBUG_OUTPUT
|
||||
// wait input window
|
||||
assign wait_window = t2 & ~wait_r;
|
||||
`endif
|
||||
|
||||
// RFSH assert timming
|
||||
`ifdef DISABLE_REFRESH_CYCLE
|
||||
wire nxt_rfsh = 1'b0;
|
||||
`else
|
||||
wire nxt_rfsh = (m1&t2&wait_r)|t3; // T3 and T4
|
||||
`endif
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// NMI eddge sense
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
`ifndef NMI_SYNC_SENSE
|
||||
wire nmi_clr = nmiack | reset_s;
|
||||
always @(negedge nmi_n or posedge nmi_clr)
|
||||
begin
|
||||
if(nmi_clr) nmireq <= #1 1'b0;
|
||||
else nmireq <= #1 1'b1;
|
||||
end
|
||||
`endif
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// Timming state controll
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
`ifdef FZ80C_POWER_ON_RESET
|
||||
always @(negedge clk)
|
||||
begin
|
||||
por_n <= #1 por2_n;
|
||||
por2_n <= #1 1'b1;
|
||||
end
|
||||
// with por
|
||||
always @(negedge clk or negedge por_n)
|
||||
if(~por_n) reset_s <= #1 1'b1;
|
||||
else reset_s <= #1 ~reset_n;
|
||||
`else
|
||||
// without por
|
||||
always @(negedge clk) reset_s <= #1 ~reset_n;
|
||||
`endif
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset_s)
|
||||
begin
|
||||
dinst_r <= #1 8'h00;
|
||||
ts <= #1 4'b0000; // reset cycle;
|
||||
A <= #1 16'h0000;
|
||||
m1_r <= #1 1'b1;
|
||||
`ifndef DISABLE_REFRESH_CYCLE
|
||||
rfsh_r <= #1 1'b1;
|
||||
`endif
|
||||
intreq <= #1 1'b0;
|
||||
`ifdef NMI_SYNC_SENSE
|
||||
nmireq <= #1 1'b0;
|
||||
nmi_r2 <= #1 1'b0;
|
||||
nmi_r1 <= #1 1'b0;
|
||||
`endif
|
||||
tw1 <= #1 1'b0;
|
||||
tw2 <= #1 1'b0;
|
||||
dt_t4 <= #1 1'b1;
|
||||
`ifndef DISABLE_BUSREQ_SYNC
|
||||
busreq_r <= #1 1'b1;
|
||||
busack_r <= #1 1'b1;
|
||||
at_r <= #1 1'b1;
|
||||
`endif
|
||||
|
||||
iorq_r <= #1 1'b1;
|
||||
rd_r <= #1 1'b1;
|
||||
mreq_r <= #1 1'b1;
|
||||
|
||||
// halt_r <= #1 1'b1;
|
||||
end else begin
|
||||
// T1 T2 on , T3 T4 off
|
||||
m1_r <= #1 ~m1 | nxt_rfsh;
|
||||
|
||||
`ifndef DISABLE_REFRESH_CYCLE
|
||||
// T3 T4 on , T1 T2 off
|
||||
rfsh_r <= #1 ~nxt_rfsh;
|
||||
`endif
|
||||
|
||||
// T1(M1),T2,T4(IO) on , T1(IO),T3,T4(M1) off
|
||||
iorq_r <= #1 ~iorq | t04 | tw1 | nxt_rfsh;
|
||||
|
||||
// T1(MEM),T2,T4(MEM) on,T1(IO),T3,T4(M1) off
|
||||
rd_r <= #1 ~rd | (iorq&t04) | nxt_rfsh;
|
||||
|
||||
// T1,T2,T4(MEM) on T3,T4(M1) off
|
||||
mreq_r <= #1 ~mreq | nxt_rfsh;
|
||||
|
||||
// timming state controll
|
||||
ts[0] <= #1 (t1&tw1) | t04; // t1
|
||||
ts[1] <= #1 (t2& ~wait_r) | (t1&~tw1); // t2
|
||||
ts[2] <= #1 (t2& wait_r& m1); // t3
|
||||
ts[3] <= #1 (t2& wait_r&~m1) | t3; // t4
|
||||
|
||||
// auto wait state
|
||||
tw1 <= #1 ~t1 & (m1&iorq); // TW for SpecialM1
|
||||
tw2 <= #1 t1 & iorq; // TW for IO and SpecialM1
|
||||
|
||||
// address / refresh address
|
||||
A <= #1 nxt_rfsh ? radr : adr;
|
||||
|
||||
// IRQ (T4 raise)
|
||||
intreq <= #1 ~int_n;
|
||||
|
||||
// NMI eddge sense
|
||||
`ifdef NMI_SYNC_SENSE
|
||||
nmi_r2 <= #1 nmi_r1;
|
||||
nmi_r1 <= #1 ~nmi_n;
|
||||
if(nmiack) nmireq <= #1 1'b0;
|
||||
else if(~nmi_r2 & nmi_r1) nmireq <= #1 1'b1;
|
||||
`endif
|
||||
|
||||
// Opcode Latch = T3 raise
|
||||
if(t2) dinst_r <= #1 di;
|
||||
|
||||
// data outpot tristate , HOLD half clock in T4
|
||||
dt_t4 <= #1 dt_r;
|
||||
|
||||
// busreq / busack & Address tristate
|
||||
`ifndef DISABLE_BUSREQ_SYNC
|
||||
busreq_r <= #1 ~busrq_n;
|
||||
busack_r <= #1 ~busack;
|
||||
at_r <= #1 ~busack;
|
||||
`endif
|
||||
|
||||
// halt fetch
|
||||
// if(m1&t4) halt_r <= #1 ~halt;
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
// clk fall event
|
||||
always @(negedge clk)
|
||||
begin
|
||||
if (reset_s)
|
||||
begin
|
||||
t3l <= #1 1'b0;
|
||||
t04l <= #1 1'b1;
|
||||
wait_r <= #1 1'b1;
|
||||
wr_r <= #1 1'b1;
|
||||
dt_r <= #1 1'b1;
|
||||
do_r <= #1 8'h00;
|
||||
end else begin
|
||||
// gate controll
|
||||
t3l <= #1 t3;
|
||||
|
||||
// t4l-t0l | specialM1.t1l
|
||||
t04l <= #1 t04 | (t1&m1&iorq);
|
||||
|
||||
// DataOutput
|
||||
do_r <= #1 data_out;
|
||||
|
||||
// wait sense (T2 raise)
|
||||
wait_r <= #1 (wait_n | (m1&iorq)) & ~tw2;
|
||||
|
||||
// data bus enable , T1,T2 on , T4 off
|
||||
dt_r <= #1 ~wr | t04;
|
||||
|
||||
// T1(IO),T2 on , T1(MEM),T4 off
|
||||
wr_r <= #1 ~wr | t4 | (mreq&t1);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// fz80 input
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
assign waitreq = ~t4;
|
||||
`ifdef DISABLE_BUSREQ_SYNC
|
||||
assign busreq = ~busrq_n;
|
||||
`else
|
||||
assign busreq = busreq_r;
|
||||
`endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// output signal
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// MREQ glidge mask
|
||||
`ifdef MREQ_INSIDE_RD
|
||||
reg mreq_dly;
|
||||
always @(posedge clk or negedge rd_n)
|
||||
begin
|
||||
if(~rd_n) mreq_dly <= #1 1'b0;
|
||||
else if(t04) mreq_dly <= #1 rd;
|
||||
end
|
||||
|
||||
reg rd_hold_n;
|
||||
always @(posedge clk or posedge mreq_n)
|
||||
begin
|
||||
if(mreq_n) rd_hold_n <= #1 1'b1;
|
||||
else rd_hold_n <= #1 mreq_n | rd_n;
|
||||
end
|
||||
|
||||
`else
|
||||
wire mreq_dly = 0;
|
||||
wire rd_hold_n = 1;
|
||||
`endif
|
||||
|
||||
assign m1_n = m1_r;
|
||||
`ifndef DISABLE_REFRESH_CYCLE
|
||||
assign rfsh_n = rfsh_r;
|
||||
`else
|
||||
assign rfsh_n = 1'b1;
|
||||
`endif
|
||||
assign mreq_n = (mreq_r| t04l | mreq_dly) & (~t3l | rfsh_n);
|
||||
assign iorq_n = iorq_r | t04l;
|
||||
assign rd_n = (rd_r | t04l) & rd_hold_n;
|
||||
assign wr_n = wr_r | t1;
|
||||
assign dt = dt_r & dt_t4;
|
||||
`ifndef DISABLE_BUSREQ_SYNC
|
||||
assign At = at_r;
|
||||
assign busak_n = busack_r;
|
||||
`else
|
||||
assign At = busack | reset_s;
|
||||
assign busak_n = busack;
|
||||
`endif
|
||||
|
||||
`ifdef DO_VAL_IF_DT
|
||||
assign do = dt ? `DO_VAL_IF_DT : do_r;
|
||||
`else
|
||||
assign do = do_r;
|
||||
`endif
|
||||
|
||||
//assign halt_n = halt_r;
|
||||
assign halt_n = 1'b1;
|
||||
|
||||
`endif // FZ80C_USER_NGC_LINK
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user