OpenCores
URL https://opencores.org/ocsvn/wb_z80/wb_z80/trunk

Subversion Repositories wb_z80

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 16 to Rev 17
    Reverse comparison

Rev 16 → Rev 17

/trunk/rtl/z80_core_top.v
0,0 → 1,178
///////////////////////////////////////////////////////////////////////////////////////////////
////
//// file name: z80_core_top.v
//// description: interconnect module for z80 core.
//// project: wb_z80 ////
////
//// Author: B.J. Porcella
//// bporcella@sbcglobal.net
////
////
////
///////////////////////////////////////////////////////////////////////////////////////////////
////
//// Copyright (C) 2000-2002 B.J. Porcella
//// Real Time Solutions
////
////
//// This source file may be used and distributed without
//// restriction provided that this copyright statement is not
//// removed from the file and that any derivative work contains
//// the original copyright notice and the associated disclaimer.
////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//// POSSIBILITY OF SUCH DAMAGE.
////
///////////////////////////////////////////////////////////////////////////////////////////////
// CVS Log
//
// $Id: z80_core_top.v,v 1.1 2004-04-27 21:27:13 bporcella Exp $
//
// $Date: 2004-04-27 21:27:13 $
// $Revision: 1.1 $
// $Author: bporcella $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.1.1.1 2004/04/13 23:47:42 bporcella
// import first files
//
//
//
// connects modules:
// memstate2.v // main state machine for z8
// inst_exec.v // main execution engine for z80
// generic_spram.v // main memory (on board)
// z80_sdram_config.v // fundamentally wishbone glue logic - not on top per design guidelines
//-------1---------2---------3--------Module Name and Port List------7---------8---------9--------0
module z80_core_top( wb_dat_o,
wb_stb_o,
wb_cyc_o,
wb_we_o,
wb_adr_o,
wb_tga_o,
bist_ack_o,
bist_err_o,
wb_ack_i,
wb_clk_i,
wb_dat_i,
bist_req_i,
int_req_i
 
 
);
 
//-------1---------2---------3--------Output Ports---------6---------7---------8---------9--------0
 
output [7:0] wb_dat_o;
output wb_stb_o;
output wb_cyc_o;
output wb_we_o;
output [15:0] wb_adr_o;
output [1:0] wb_tga_o;
output bist_ack_o;
output bist_err_o;
 
 
//-------1---------2---------3--------Input Ports----------6---------7---------8---------9--------0
 
input wb_ack_i;
input wb_clk_i;
input [7:0] wb_dat_i;
input bist_req_i;
input int_req_i;
 
 
//-------1---------2---------3--------Parameters-----------6---------7---------8---------9--------0
//-------1---------2---------3--------Wires------5---------6---------7---------8---------9--------0
wire [15:0] wb_adr_o;
wire [15:0] add_out; // output of adder (may not wb_adr_o)
wire [9:0] ir1, ir2;
wire [15:0] nn;
wire [15:0] sp;
wire [7:0] ar, fr, br, cr, dr, er, hr, lr;
wire [15:0] ixr, iyr;
wire [7:0] wb_dat_i, wb_dat_o, sdram_do, cfg_do;
wire [15:0] add16; // ir2 execution engine output for sp updates
 
 
 
 
 
 
 
//-------1---------2---------3--------Registers--5---------6---------7---------8---------9--------0
//-------1---------2---------3--------Assignments----------6---------7---------8---------9--------0
//-------1---------2---------3--------State Machines-------6---------7---------8---------9--------0
 
z80_memstate2 i_z80_memstate2(
.wb_adr_o(wb_adr_o), .wb_we_o(wb_we_o), .wb_cyc_o(wb_cyc_o), .wb_stb_o(wb_stb_o), .wb_tga_o(wb_tga_o), .wb_dat_o(wb_dat_o),
.exec_ir2(exec_ir2), .ir1(ir1), .ir2(ir2), .ir1dd(ir1dd), .ir1fd(ir1fd), .ir2dd(ir2dd), .ir2fd(ir2fd), .nn(nn), .sp(sp),
.upd_ar(upd_ar), .upd_br(upd_br), .upd_cr(upd_cr), .upd_dr(upd_dr), .upd_er(upd_er), .upd_hr(upd_hr), .upd_lr(upd_lr),.upd_fr(upd_fr),
.beq0(beq0), .ceq0(ceq0),
.ar(ar), .fr(fr), .br(br), .cr(cr), .dr(dr), .er(er), .hr(hr), .lr(lr),
.ixr(ixr), .iyr(iyr),
.wb_dat_i(cfg_do), .wb_ack_i(wb_ack_i),
.int_req_i(int_req_i),
.add16(add16),
.wb_clk_i(wb_clk_i),
.rst_i(rst_i) // keep this generic - may turn out to be different from wb_rst
);
 
 
z80_inst_exec i_z80_inst_exec(
.br_eq0(br_eq0),
.cr_eq0(cr_eq0),
.upd_ar(upd_ar), .upd_br(upd_br), .upd_cr(upd_cr), .upd_dr(upd_dr), .upd_er(upd_er), .upd_hr(upd_hr), .upd_lr(upd_lr),.upd_fr(upd_fr),
.ar(ar), .fr(fr), .br(br), .cr(cr), .dr(dr), .er(er), .hr(hr), .lr(lr),
.ixr(ixr), .iyr(iyr), .add16(add16),
.exec_ir2(exec_ir2),
.exec_decbc(exec_decbc), .exec_decb(exec_decb),
.ir2(ir2),
.clk(wb_clk_i),
.rst(rst_i),
.nn(nn), .sp(sp),
.dd_grp(dd_grp),
.fd_grp(fd_grp)
);
 
// The parameter passed to i_generic_sprem specifies the number of address bits used by the
// memory -- and thus the memory size. We expect to use 15 here in the released documentation -
// giving an onboard 32k SRAM and allowing 32k space for off-chip memory. Note that any change to
// this parameter requires modifications to the decode logic in z80_sdram_cfg.
//
// The generic_spram is being used here per Open Cores coding guidelines. I'm not sure I'm totally
// happy with this...... Depending on which target technology is specified, read behavior changes.
// It is easy to insure all possible behavior will in fact operate properly -- see the data reduction
// logic in sdram_cfg.v -- but still... I guess the important thing to be aware of is that
// big memories like this typically require special back-end handleing. This is likely to prove
// no exception - despite the work that has been done to make this file as generally useful as
// possible.
 
generic_spram #(12) i_generic_spram(
// Generic synchronous single-port RAM interface
.clk(wb_clk_i), .rst(rst_i), .ce(cfg_ce_spram_o), .we(wb_we_o), .oe(1'b1), .addr(wb_adr_o[11:0]), .di(wb_dat_o), .do(sdram_do)
);
 
 
 
z80_sdram_cfg i_z80_sdram_cfg(
.cfg_ce_spram_o(cfg_ce_spram_o), .cfg_do(cfg_do), .cfg_ack_o(cfg_ack_o), .sdram_di(sdram_do),
.wb_adr_i(wb_adr_o), .wb_dat_i(wb_dat_i), .wb_ack_i(wb_ack_i), .wb_stb_i(wd_stb_o),
.wb_cyc_i(wb_cyc_o), .wb_tga_i(wb_tga_o) );
 
 
endmodule
/trunk/rtl/files.txt
0,0 → 1,8
+incdir+.
z80_core_top.v
z80_inst_exec.v
z80_memstate2.v
z80_sdram_cfg.v
generic_spram.v
 
 
/trunk/rtl/generic_spram.v
0,0 → 1,429
//////////////////////////////////////////////////////////////////////
//// ////
//// Generic Single-Port Synchronous RAM ////
//// ////
//// This file is part of memory library available from ////
//// http://www.opencores.org/cvsweb.shtml/generic_memories/ ////
//// ////
//// Description ////
//// This block is a wrapper with common single-port ////
//// synchronous memory interface for different ////
//// types of ASIC and FPGA RAMs. Beside universal memory ////
//// interface it also provides a behavioral model of generic ////
//// single-port synchronous RAM. ////
//// It also contains a synthesizeable model for FPGAs. ////
//// It should be used in all OPENCORES designs that want to be ////
//// portable accross different target technologies and ////
//// independent of target memory. ////
//// ////
//// Supported ASIC RAMs are: ////
//// - Artisan Single-Port Sync RAM ////
//// - Avant! Two-Port Sync RAM (*) ////
//// - Virage Single-Port Sync RAM ////
//// - Virtual Silicon Single-Port Sync RAM ////
//// ////
//// Supported FPGA RAMs are: ////
//// - Generic FPGA (VENDOR_FPGA) ////
//// Tested RAMs: Altera, Xilinx ////
//// Synthesis tools: LeonardoSpectrum, Synplicity ////
//// - Xilinx (VENDOR_XILINX) ////
//// - Altera (VENDOR_ALTERA) ////
//// ////
//// To Do: ////
//// - fix avant! two-port ram ////
//// - add additional RAMs ////
//// ////
//// Author(s): ////
//// - Richard Herveille, richard@asics.ws ////
//// - Damjan Lampret, lampret@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.3 2001/11/09 00:34:19 samg
// minor changes: unified with all common rams
//
// Revision 1.2 2001/11/08 19:32:59 samg
// corrected output: output not valid if ce low
//
// Revision 1.1.1.1 2001/09/14 09:57:09 rherveille
// Major cleanup.
// Files are now compliant to Altera & Xilinx memories.
// Memories are now compatible, i.e. drop-in replacements.
// Added synthesizeable generic FPGA description.
// Created "generic_memories" cvs entry.
//
// Revision 1.2 2001/07/30 05:38:02 lampret
// Adding empty directories required by HDL coding guidelines
//
//
 
//`include "timescale.v"
 
//`define VENDOR_XILINX
//`define VENDOR_ALTERA
//`define VENDOR_FPGA
 
module generic_spram(
// Generic synchronous single-port RAM interface
clk, rst, ce, we, oe, addr, di, do
);
 
//
// Default address and data buses width
//
parameter aw = 6; //number of address-bits
parameter dw = 8; //number of data-bits
 
//
// Generic synchronous single-port RAM interface
//
input clk; // Clock, rising edge
input rst; // Reset, active high
input ce; // Chip enable input, active high
input we; // Write enable input, active high
input oe; // Output enable input, active high
input [aw-1:0] addr; // address bus inputs
input [dw-1:0] di; // input data bus
output [dw-1:0] do; // output data bus
 
//
// Module body
//
 
`ifdef VENDOR_FPGA
//
// Instantiation synthesizeable FPGA memory
//
// This code has been tested using LeonardoSpectrum and Synplicity.
// The code correctly instantiates Altera EABs and Xilinx BlockRAMs.
//
reg [dw-1 :0] mem [(1<<aw) -1:0];
reg [aw-1:0] raddr;
 
always@(posedge clk)
begin
// read operation
raddr <= #1 addr; // read address needs to be registered to read clock
 
// write operation
if (we && ce)
mem[addr] <= #1 di;
end
 
assign #1 do = mem[raddr];
 
`else
 
`ifdef VENDOR_XILINX
 
wire [dw-1:0] q; // output from xilinx ram
//
// Instantiation of FPGA memory:
//
// Virtex/Spartan2 BlockRAMs
//
xilinx_ram_sp xilinx_ram(
.clk(clk),
.rst(rst),
.addr(addr),
.di(di),
.en(ce),
.we(we),
.do(do)
);
 
defparam
xilinx_ram.dwidth = dw,
xilinx_ram.awidth = aw;
 
`else
 
`ifdef VENDOR_ALTERA
 
//
// Instantiation of FPGA memory:
//
// Altera FLEX EABs
//
 
altera_ram_sp altera_ram(
.inclock(clk),
.address(addr),
.data(di),
.we(we && ce),
.q(do)
);
 
defparam
altera_ram.dwidth = dw,
altera_ram.awidth = aw;
 
`else
 
`ifdef VENDOR_ARTISAN
 
//
// Instantiation of ASIC memory:
//
// Artisan Synchronous Single-Port RAM (ra1sh)
//
artisan_ssp #(dw, 1<<aw, aw) artisan_ssp(
.CLK(clk),
.CEN(~ce),
.WEN(~we),
.A(addr),
.D(di),
.OEN(~oe),
.Q(do)
);
 
`else
 
`ifdef VENDOR_AVANT
 
//
// Instantiation of ASIC memory:
//
// Avant! Asynchronous Two-Port RAM
//
avant_atp avant_atp(
.web(~we),
.reb(),
.oeb(~oe),
.rcsb(),
.wcsb(),
.ra(addr),
.wa(addr),
.di(di),
.do(do)
);
 
`else
 
`ifdef VENDOR_VIRAGE
 
//
// Instantiation of ASIC memory:
//
// Virage Synchronous 1-port R/W RAM
//
virage_ssp virage_ssp(
.clk(clk),
.adr(addr),
.d(di),
.we(we),
.oe(oe),
.me(ce),
.q(do)
);
 
`else
 
`ifdef VENDOR_VIRTUALSILICON
 
//
// Instantiation of ASIC memory:
//
// Virtual Silicon Single-Port Synchronous SRAM
//
virtualsilicon_spram #(1<<aw, aw-1, dw-1) virtualsilicon_ssp(
.CK(clk),
.ADR(addr),
.DI(di),
.WEN(~we),
.CEN(~ce),
.OEN(~oe),
.DOUT(do)
);
 
`else
 
//
// Generic single-port synchronous RAM model
//
 
//
// Generic RAM's registers and wires
//
reg [dw-1:0] mem [(1<<aw)-1:0]; // RAM content
wire [dw-1:0] q; // RAM output
reg [aw-1:0] raddr; // RAM read address
//
// Data output drivers
//
assign do = (oe & ce) ? q : {dw{1'bz}};
 
//
// RAM read and write
//
 
// read operation
always@(posedge clk)
if (ce) // && !we)
raddr <= #1 addr; // read address needs to be registered to read clock
 
assign #1 q = rst ? {dw{1'b0}} : mem[raddr];
 
// write operation
always@(posedge clk)
if (ce && we)
mem[addr] <= #1 di;
 
// Task prints range of memory
// *** Remember that tasks are non reentrant, don't call this task in parallel for multiple instantiations.
task print_ram;
input [aw-1:0] start;
input [aw-1:0] finish;
integer rnum;
begin
for (rnum=start;rnum<=finish;rnum=rnum+1)
$display("Addr %h = %h",rnum,mem[rnum]);
end
endtask
 
`endif // !VIRTUALSILICON_SSP
`endif // !VIRAGE_SSP
`endif // !AVANT_ATP
`endif // !ARTISAN_SSP
`endif // !VENDOR_ALTERA
`endif // !VENDOR_XILINX
`endif // !VENDOR_FPGA
 
endmodule
 
 
//
// Black-box modules
//
 
`ifdef VENDOR_ALTERA
module altera_ram_sp (
address,
inclock,
we,
data,
q) /* synthesis black_box */;
 
parameter awidth = 7;
parameter dwidth = 8;
 
input [awidth -1:0] address;
input inclock;
input we;
input [dwidth -1:0] data;
output [dwidth -1:0] q;
 
// synopsis translate_off
// exemplar translate_off
 
syn_ram_irou #(
"UNUSED",
dwidth,
awidth,
1 << awidth
)
altera_spram_model (
.Inclock(inclock),
.Address(address),
.Data(data),
.WE(we),
.Q(q)
);
 
// exemplar translate_on
// synopsis translate_on
 
endmodule
`endif // VENDOR_ALTERA
 
`ifdef VENDOR_XILINX
module xilinx_ram_sp (
clk,
rst,
addr,
di,
en,
we,
do) /* synthesis black_box */ ;
 
parameter awidth = 7;
parameter dwidth = 8;
 
input clk;
input rst;
input [awidth -1:0] addr;
input [dwidth -1:0] di;
input en;
input we;
output [dwidth -1:0] do;
 
// insert simulation model
 
 
// synopsys translate_off
// exemplar translate_off
 
C_MEM_SP_BLOCK_V1_0 #(
awidth,
1,
"0",
1 << awidth,
1,
1,
1,
1,
1,
1,
1,
"",
16,
0,
0,
1,
1,
dwidth
)
xilinx_spram_model (
.CLK(clk),
.RST(rst),
.ADDR(addr),
.DI(di),
.EN(en),
.WE(we),
.DO(do)
);
 
// exemplar translate_on
// synopsys translate_on
 
endmodule
`endif // VENDOR_XILINX
 
/trunk/rtl/z80_inst_exec.v
0,0 → 1,1235
///////////////////////////////////////////////////////////////////////////////////////////////////
// //
// file name: inst_exec.v //
// description: main execution engine for wishbone z80 //
// project: wb_z80 //
// //
// Author: B.J. Porcella //
// e-mail: bporcella@sbcglobal.net //
// //
// //
// //
///////////////////////////////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2000-2002 B.J. Porcella //
// Real Time Solutions //
// //
// //
// This source file may be used and distributed without //
// restriction provided that this copyright statement is not //
// removed from the file and that any derivative work contains //
// the original copyright notice and the associated disclaimer. //
// //
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //
// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //
// POSSIBILITY OF SUCH DAMAGE. //
// //
//-------1---------2---------3--------Comments on file -------------7---------8---------9--------0
//
// This file contains the data related registers of the z80 and the
// logic required to update them. Included registers are:
// ar fr
// br cr
// dr er
// hr lr
// ixr
// iyr
// intr
//
// and the "prime" registers
// ap fp
// bp cp
// dp ep
// hp lp
//
// This logic can be considered a "slave" to the memstate sequencer (in memstate2.v).
// as memstate sequencer executes any instruction from ir1 (the of - os pipe) the instruction
// gets transferred to ir2 - which now becomes active.
//
// In the case of any memory type instruction (HL) , the pipeline must stall 1 tick to get the
// operand into the nn register. This file logic needs not understand any of that -- just
// execute when told to (ir2_val).
//
// From a block diagram standpoint this file is somewhat messy. There are multiple ALU's and
// multiple source multiplexors. Part of the reason for this is hardware speed - the
// various additions start pretty early in the cycle ( as not much decode logic is needed to
// get them started. In parallel with that - the destination selectors ( which require more
// complex decoding logic ) are "doing thier thing" No claim that this is absolute optimum - any
// good synthesizer should be able to make the basic structure faster when flattened. However,
// the intention is that even if the synthesizer is pretty primitive -- reasonably fast hardware
// will be produced.
//
//-------1---------2---------3--------CVS Log -----------------------7---------8---------9--------0
//
// $Id: z80_inst_exec.v,v 1.1 2004-04-27 21:27:13 bporcella Exp $
//
// $Date: 2004-04-27 21:27:13 $
// $Revision: 1.1 $
// $Author: bporcella $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.4 2004/04/19 19:13:27 bporcella
// real lint problems pretty much fixed -- need another look - but need to get on to other things first
//
// Revision 1.3 2004/04/19 05:09:11 bporcella
// fixed some lint problems --
//
// Revision 1.2 2004/04/18 18:50:08 bporcella
// fixed some lint problems --
//
// Revision 1.1.1.1 2004/04/13 23:49:54 bporcella
// import first files
//
//
//
//-------1---------2---------3--------Module Name and Port List------7---------8---------9--------0
module z80_inst_exec( br_eq0,
cr_eq0,
upd_ar, upd_br, upd_cr, upd_dr, upd_er, upd_hr, upd_lr,upd_fr,
ar, fr, br, cr, dr, er, hr, lr,
ixr, iyr, add16,
exec_ir2,
exec_decbc, exec_decb,
ir2,
clk,
rst,
nn, sp,
dd_grp,
fd_grp
);
 
//-------1---------2---------3--------Output Ports---------6---------7---------8---------9--------0
output br_eq0;
output cr_eq0;
output upd_ar, upd_br, upd_cr, upd_dr, upd_er, upd_hr, upd_lr,upd_fr;
output [7:0] ar, fr, br, cr, dr, er, hr, lr;
output [15:0] ixr, iyr;
output [15:0] add16;
//-------1---------2---------3--------Input Ports----------6---------7---------8---------9--------0
input exec_ir2;
input exec_decbc; // in general this needs to happen at different time from exec
input exec_decb; // in general - we don't have the EB instruction (yet) when this hits
input [9:0] ir2;
input clk;
input rst;
input [15:0] nn, sp;
input dd_grp; // this must be ir2
input fd_grp;
 
//-------1---------2---------3--------Parameters-----------6---------7---------8---------9--------0
`include "opcodes.v"
 
//-------1---------2---------3--------Wires----------------6---------7---------8---------9--------0
 
//wire [7:0] src_pqr; // arithmetic sources gven by ir2[2:0]
wire [7:0] src_hr ;
wire [7:0] src_lr ;
//wire [7:0] alu_out; // {CF. 8bit_result}
//wire alu_cry;
 
//wire c_in0, c_out7, c_in8, c_out11, cout15;
wire [15:0] src_a, src_b;
wire [15:0] add16;
wire sf, zf, f5f, hf, f3f, pvf, nf, cf;
wire [7:0] daa_alu; // {cry, number} hf goes to 0 always.
wire daa_cry;
wire upd_ar, upd_br, upd_cr, upd_dr, upd_er, upd_fr, upd_hr, upd_lr;
wire c_8out3;
wire [7:0] add_8bit;
 
wire [15:0] src_dblhr ;
//wire src_cb_r20 ;
wire [7:0] src_pqr20 ;
wire [7:0] src_pqr53 ;
wire [15:0] src_dbl ;
wire [7:0] alu8_fr ;
wire alu8_nf ;
wire c_8out7 ;
wire alu8_cry ;
wire alu8_hcry ;
wire [7:0] alu8_out ;
wire add16_ofl ;
wire c_16out7 ;
wire c_16out11 ;
wire c_16out15 ;
wire c_16in0 ;
wire sh_cry ;
wire [7:0] sh_alu ;
wire sh_alu_act ;
wire bit_alu_act ;
wire [7:0] bit_alu ;
wire [7:0] decc_alu ;
wire [7:0] decb_alu ;
wire upd_a_alu8 ;
wire up_a_sh_alu ;
wire up_a_src_pqr ;
wire up_a_n ;
wire upd_b_alu8 ;
wire up_b_src_pqr ;
wire up_b_add16 ;
wire [7:0] sh_src ;
 
wire up_c_add16 ;
wire upd_c_alu8 ;
wire up_c_src_pqr ;
wire up_d_add16 ;
wire upd_d_alu8 ;
wire up_d_src_pqr ;
wire up_e_add16 ;
wire upd_e_alu8 ;
wire up_e_src_pqr ;
wire up_h_add16 ;
wire upd_h_alu8 ;
wire upd_h_src_pqr ;
wire up_l_add16 ;
wire upd_l_alu8 ;
wire upd_l_src_pqr ;
wire upd_fr_alu8 ;
wire upd_fr_add16 ;
wire upd_fr_edadd16 ;
wire upd_fr_sh ;
wire upd_fr_cbsh ;
wire eb_blk_mv ;
wire ed_blk_cp ;
wire c_8in0 ;
 
//-------1---------2---------3--------Registers------------6---------7---------8---------9--------0
 
reg [7:0] ar, fr, br, cr, dr, er, hr, lr, intr;
reg [7:0] ap, fp, bp, cp, dp, ep, hp, lp;
reg [15:0] ixr, iyr;
//-------1---------2---------3--------Assignments----------6---------7---------8---------9--------0
 
// it appears that dd and fd as a prefix to cb has a significantly modfied fuction......
// specifically, it is assumed that a memory operation is to be implemented (ix + d)
// , In fact the
// pipeline is such that we can make a fetch for free - so we will do that..... the
// prefix flags should not be set here -- all we will know on execution is that it is a
// cb instruction. ---- src is always nn
assign src_hr = dd_grp ? ixr[15:8] :
fd_grp ? iyr[15:8] :
hr ;
assign src_lr = dd_grp ? ixr[7:0] :
fd_grp ? iyr[7:0] :
lr ;
 
assign src_dblhr = dd_grp ? ixr : // ed grp instructions (ADC HL ; SBC HL are not affected -
fd_grp ? iyr : // instruction assembler assures this - ed_grp has no prefix
{hr, lr} ;
// ddcb_grp not defined - src_cb_r20 not used. Why these lines? 4/17/2004
//assign src_cb_r20 = (ddcb_grp | fdcb_grp) ? nn[7:0] :
// cb_grp ? src_pqr20 :
// ar ;
assign br_eq0 = ~|br; // for first cut do this quick and dirty.
assign cr_eq0 = ~|cr; // if this becomes a critical path - make these registers.
assign src_pqr20 = {8{ir2[2:0]==REG8_B }} & br |
{8{ir2[2:0]==REG8_C }} & cr |
{8{ir2[2:0]==REG8_D }} & dr |
{8{ir2[2:0]==REG8_E }} & er |
{8{ir2[2:0]==REG8_H }} & src_hr |
{8{ir2[2:0]==REG8_L }} & src_lr |
{8{ir2[2:0]==REG8_MEM}} & nn[15:8] |
{8{ir2[2:0]==REG8_A }} & ar ;
assign src_pqr53 = {8{ir2[5:3]==REG8_B }} & br |
{8{ir2[5:3]==REG8_C }} & cr |
{8{ir2[5:3]==REG8_D }} & dr |
{8{ir2[5:3]==REG8_E }} & er |
{8{ir2[5:3]==REG8_H }} & src_hr |
{8{ir2[5:3]==REG8_L }} & src_lr |
{8{ir2[5:3]==REG8_MEM}} & nn[15:8] |
{8{ir2[5:3]==REG8_A }} & ar ;
 
 
assign src_dbl = {16{ir2[5:4]==2'b00}} & {br, cr} |
{16{ir2[5:4]==2'b01}} & {dr, er} |
{16{ir2[5:4]==2'b10}} & src_dblhr | // HL, ixr, iyr
{16{ir2[5:4]==2'b11}} & sp ;
 
assign sh_src = ir2[8] & dd_grp ? nn[15:8] :
ir2[8] & fd_grp ? nn[15:8] :
ir2 ? src_pqr20 :
ar ;
// I wonder how well the synthesizer can reduce this??? - It is probably worth spending
// some time during physical design to see if a more low level description would help --
// there is somebody out there who knows - and there is probably a good low level description.
//
// guess its kind of important to understand precisely what the synthesizer does
// with some of the status things we need also.
//
//
// The nastiest status to get is HF. Really need 4 bit adders to do that ( or reproduce a lot
// of logic.) I don't have a lot of confdence in the synthesier's ability to minimize arithmetic
// operations -- Its a moving target of course, but I've seen some really silly stuff come out
// of synthesis when you use a "+" operator. guess I will be pretty explicit here.
// Documentation of the HF is srange. IN and OUT operators are defined as X -- but 16 bit operations
// get set by CRY from bit 11. (Do I care??? ) well probably not but it is documented - so should
// be tested i guess.
//
//
// may want to re-define as a module with carry look-ahead ?
//
// Had a notion to define a single adder - subtractor for both 8 and 16 bit operations, but
// getting into source mux issues that solution scared me..... Worry the cry flag might
// become a worst case path. As defined, a good chunk of the decode process can go on in
// parallel with the cry computation --- with final decisions made using a small mux at
// the flag register.
// ------------ 8 bit adder for accumulator ops plus the INC DEC ops ---------------------
// It is documented that the hf is modified by the INC and DEC ops even if ar is not the
// destination of result --- clearly hf and nf are pretty usless on a INC B but ours is
// not to reason why :-) ---- well its fun to bitch about silly stuff like this.
// ( not as much fun to deal with instruction tests testing "features" -- or worse programmers
// who figure out ways to use theses "features". )
//
// 8 bit adder with cry out of bit 3 used for most operations on A as well as the
// inc/dec instructions. also need to get ED44 (ar <= -ar) working here
wire [7:0] src_pqri; // use just here and below
wire [7:0] src_aor_cnst = ed_blk_cp ? ar : // CPI CPIR CPD CPDR
ir2[9] ? 8'h0 : // for ed44 -a //ed_grp == ir2[9]
ir2[7] ? ar :
ir2[0] ? 8'hff :
8'h00 ;
//--------------- the "standard" flag logic -----------------------------
// sf zf f5f hf
assign alu8_fr ={alu8_out[7], ~|alu8_out, alu8_out[5], alu8_hcry,
// f3f fpv fn fc
alu8_out[3], alu8_out[7], alu8_nf, c_8out7 };
 
//assign alu8_pvf = (ir2[7:3]==5'b10100 | ir2[7:3]==5'b10101 | ir2[7:3]==5'b10110) ?
// ~^alu8_out : // even parity
// (src_aor_cnst[7]==src_pqri[7]) & (src_aor_cnst[7]!=alu8_out[7]) ; // ofl
 
assign alu8_nf = (ir2[7:3]==5'b10010) |
(ir2[7:3]==5'b10011) |
(ir2[7:6]==2'b00) & ir2[0] |
ir2[9] ;
 
assign {c_8out3, add_8bit[3:0]} = {1'b0, src_aor_cnst[3:0]} + {1'b0, src_pqri[3:0]} + {4'b0, c_8in0};
//wire [4:0] ha_temp = {1'b0, src_aor_cnst[3:0]} + {1'b0, src_pqri[3:0]} + {4'b0, c_8in0};
//assign c_8out3
 
assign {c_8out7, add_8bit[7:4]} = {1'b0, src_aor_cnst[7:4]} + {1'b0, src_pqri[7:4]} + {4'b0, c_8out3};
 
// notice that both inputs and outputs of the adder are being selected below.
// making ed_blk_cp high priority kind of negates the origional idea of making the
// decodes fast here --- course when all is included this can't be too fast.
// Just note for syntheses that this is a slow path that could be improved with some thought.
// 1 1 8 8 1
assign {alu8_cry, alu8_hcry, alu8_out, src_pqri, c_8in0 }=
ed_blk_cp ? {c_8out7,c_8out3, add_8bit, ~src_pqr20, 1'h1} : //CPI CPIR CPD CPDR
 
{19{ir2[7:3]==5'b10000}} & ({c_8out7,c_8out3, add_8bit, src_pqr20, 1'b0} ) |// a+src
{19{ir2[7:3]==5'b10001}} & ({c_8out7,c_8out3, add_8bit, src_pqr20, cf} ) |// a+src+cf
{19{ir2[7:3]==5'b10010}} & ({c_8out7,c_8out3, add_8bit, ~src_pqr20, 1'h1} ) |// a-src
{19{ir2[7:3]==5'b10011}} & ({c_8out7,c_8out3, add_8bit, ~src_pqr20, ~cf } ) |// a-src-cf
{19{ir2[7:3]==5'b10100}} & ({1'b0 ,1'b1 , ar & src_pqr20, src_pqr20, 1'b0} ) |// a&src
{19{ir2[7:3]==5'b10101}} & ({1'b0 ,1'b0 , ar ^ src_pqr20, src_pqr20, 1'b0} ) |// a^src
{19{ir2[7:3]==5'b10110}} & ({1'b0 ,1'b0 , ar | src_pqr20, src_pqr20, 1'b0} ) |// a|src
{19{ir2[7:3]==5'b10111}} & ({c_8out7,c_8out3, add_8bit, src_pqr20, 1'h1}) |// a-src
{19{(ir2[7:6]==2'b00)& ~ir2[0] }}& ({ cf,c_8out3, add_8bit, src_pqr53, 1'h1}) |// inc_r main
{19{(ir2[7:6]==2'b00)& ir2[0] }}& ({ cf,c_8out3, add_8bit, src_pqr53, 1'h0}) |// dec_r
{19{(ir2[7:6]==2'b01) }}& ({c_8out7,c_8out3, add_8bit, ~ar, 1'h1}) ;// ed44 -a
 
 
// do some hand decoding here
// ADDsHL_BC = 'h09, DECsBC = 'h0B, INCsBC = 'h03 compair with {ir2[7:6],ir2[3:0]}
// ADDsHL_DE = 'h19, DECsDE = 'h1B INCsDE = 'h13 ED_SBCsHL_REG = 6'b01__0010
// ADDsHL_HL = 'h29, DECsHL = 'h2B INCsHL = 'h23 ED_ADCsHL_REG = 6'b01__1010
// ADDsHL_SP = 'h39, DECsSP = 'h3B INCsSP = 'h33
// by inspection just use ir2[3:0] - i guess in a pinch we do't need ir2[2] = but let the
// synthesizer figure that out. - it should be able to.
//
 
 
// ---------------- 16 bit adder with bit 11 carrry out and bit 8 carry in ------------------
//
assign add16_ofl = (src_a[15] == src_b[15]) & (src_a[15] != add16[15]);
///tmp/lint/wb_z80/rtl/inst_exec.v(363): Warning 22014: synchronous loop without set/reset detected on signal "src_b[11:8]" (OC)
assign {c_16out7, add16[7:0]} = {1'b0, src_a[7:0]} + {1'b0, src_b[7:0] } + {8'b0, c_16in0};
assign {c_16out11, add16[11:8]} = {1'b0, src_a[11:8]} + {1'b0, src_b[11:8] } + {4'b0, c_16out7};
assign {c_16out15, add16[15:12]} = {1'b0, src_a[15:12]} + {1'b0, src_b[15:12]} + {4'b0, c_16out11};
 
assign { src_a, src_b, c_16in0} = // assigning 33 bits
{33{ir2[3:0] == 4'h9}} & {src_dblhr, src_dbl ,1'b0 } | //ADD
{33{ir2[3:0] == 4'hb}} & {16'hffff , src_dbl ,1'b0 } | //DEC
{33{ir2[3:0] == 4'h3}} & {16'h0001 , src_dbl ,1'b0 } | //INC
{33{ir2[3:0] == 4'h2}} & {src_dblhr, ~src_dbl , ~cf } | //SBC
{33{ir2[3:0] == 4'ha}} & {src_dblhr, src_dbl , cf } ; //ADC
//-------------------------- sh alu --------------------------------------------------
// shift insructions. Think of these as 8 shift types:
// RLC RL RRC RR SLA SLL SRA SRL The SLL types appear to be undocumented -- but possibly used
// in assembly code as they appear to have some utility - and by all accounts operate reliably.
// The first four are implemented in a single byte inaruction . (A <= sh_op A )
// All 8 are implemented in the CB group with all registers as potential sources (and dests).
// if dd_grp or fd_grp is prefix..... source is always the memory. This is undocumented - but
// may be a useful hint for simplyfing the total machine. Destination registers
// (if any) get a copy of the updated memory location (This is also true of the bit set and
// clear instructions in the cb_grp.
 
assign {sh_cry, sh_alu} = {9{ir2[5:3]==3'b000}} & {sh_src, sh_src[7] } | //RLC
{9{ir2[5:3]==3'b001}} & {sh_src[0], sh_src[0], sh_src[7:1]} | // RRC
{9{ir2[5:3]==3'b010}} & {sh_src, cf } | //RL
{9{ir2[5:3]==3'b011}} & {sh_src[0], cf, sh_src[7:1] } | // RR
{9{ir2[5:3]==3'b100}} & {sh_src, 1'b0} | //SLA
{9{ir2[5:3]==3'b101}} & {sh_src[0], sh_src[7], sh_src[7:1]} | //SRA
{9{ir2[5:3]==3'b110}} & {sh_src, 1'b1} | //SLL
{9{ir2[5:3]==3'b111}} & {sh_src[0], 1'b0, sh_src[7:1]} ; //SRL
 
 
// shift insts
assign sh_alu_act = ir2[9:6] == 4'b0100;
//CB_RLC = 7'b01_00_000, // these must be compaired with ir2[9:3]
//CB_RRC = 7'b01_00_001, // these must be compaired with ir2[9:3]
//CB_RL = 7'b01_00_010, // these must be compaired with ir2[9:3]
//CB_RR = 7'b01_00_011, // these must be compaired with ir2[9:3]
//CB_SLA = 7'b01_00_100, // these must be compaired with ir2[9:3]
//CB_SRA = 7'b01_00_101, // these must be compaired with ir2[9:3]
//CB_SLL = 7'b01_00_110, // these must be compaired with ir2[9:3]
//CB_SRL = 7'b01_00_111, // these must be compaired with ir2[9:3]
 
//---------------------------- bit test alu ---------------------------------------
// bit test insts
//CB_BIT = 4'b01_01, // these must be compaired with ir2[9:6]
//CB_RES = 4'b01_10, // these must be compaired with ir2[9:6]assign
//CB_SET = 4'b01_11, // these must be compaired with ir2[9:6]
assign bit_alu_act = ir2[9:6] == CB_BIT |
ir2[9:6] == CB_RES |
ir2[9:6] == CB_RES ;
 
wire [7:0] bit_decode = {8{ir2[5:3] == 3'h0}} & 8'h01 |
{8{ir2[5:3] == 3'h1}} & 8'h02 |
{8{ir2[5:3] == 3'h2}} & 8'h04 |
{8{ir2[5:3] == 3'h3}} & 8'h08 |
{8{ir2[5:3] == 3'h4}} & 8'h10 |
{8{ir2[5:3] == 3'h5}} & 8'h20 |
{8{ir2[5:3] == 3'h6}} & 8'h40 |
{8{ir2[5:3] == 3'h7}} & 8'h80 ;
 
assign bit_alu = {8{ir2[9:6] == CB_BIT}} & ( sh_src & bit_decode) |
{8{ir2[9:6] == CB_RES}} & ( sh_src & ~bit_decode) |
{8{ir2[9:6] == CB_RES}} & ( sh_src | bit_decode) ;
 
//------------ dec bc alu ---------------------------------------------
//exec_decbc; these are all we know (in general)
//exec_decb;
assign decc_alu = cr + 8'hff ;
assign decb_alu = br + ( exec_decb ? 8'hff : // just dec b if io blk move
cr_eq0 ? 8'hff : // cry out if c in this case
8'h00 ); // only dec c reg this tick
// ------------------ daa alu -------------------------------------------------------
// the documentation does not cover all cases here -- only those that matter (i suppose).
// ( documentation assumes you are operating with 2 daa'd numbers -- but of course the
// ar can contain many values that don't fit that assumption when this instruction is executed.
// Any arbitrary instruction test may test un-documented cases.
//
// this leaves me to guess what the actual logic is - and how to match it.
// So I am doing that -- see what happens. If an instruction test breaks this... I should be
// able to fix it easily.
//
wire [3:0] ls_nbl = (!nf & hf) ? 4'h6:
(!nf & (ar[3:0] > 4'h9)) ? 4'h6:
(nf & hf ) ? 4'ha:
4'h0;
 
wire [4:0] ms_nbl = (!nf & cf) ? 5'h16: // includes new cry
(!nf & (ar[3:0] > 4'h9)) ? 5'h16:
(!nf & (ar[3:0] == 4'h9) &
(ar[3:0] > 4'h9)) ? 5'h16:
(nf & !cf & hf ) ? 5'h0f:
(nf & cf & !hf ) ? 5'h1a:
(nf & cf & hf ) ? 5'h19:
5'h00;
 
 
assign {daa_cry, daa_alu} = { ms_nbl[4], {ar + { ms_nbl[3:0], ls_nbl}} } ;
 
 
//-------1---------2---------3--------State Machines-------6---------7---------8---------9--------0
 
// update ar
 
assign upd_a_alu8 =
ADDsA_B == ir2 | SUBsB == ir2 | ANDsB == ir2 | ORsB == ir2 |
ADDsA_C == ir2 | SUBsC == ir2 | ANDsC == ir2 | ORsC == ir2 |
ADDsA_D == ir2 | SUBsD == ir2 | ANDsD == ir2 | ORsD == ir2 |
ADDsA_E == ir2 | SUBsE == ir2 | ANDsE == ir2 | ORsE == ir2 |
ADDsA_H == ir2 | SUBsH == ir2 | ANDsH == ir2 | ORsH == ir2 |
ADDsA_L == ir2 | SUBsL == ir2 | ANDsL == ir2 | ORsL == ir2 |
ADDsA_6HL7 == ir2 | SUBs6HL7 == ir2 | ANDs6HL7 == ir2 | ORs6HL7 == ir2 |
ADDsA_A == ir2 | SUBsA == ir2 | ANDsA == ir2 | ORsA == ir2 |
ADCsA_B == ir2 | SBCsB == ir2 | XORsB == ir2 |
ADCsA_C == ir2 | SBCsC == ir2 | XORsC == ir2 | INCsA == ir2 |
ADCsA_D == ir2 | SBCsD == ir2 | XORsD == ir2 | DECsA == ir2 |
ADCsA_E == ir2 | SBCsE == ir2 | XORsE == ir2 |
ADCsA_H == ir2 | SBCsH == ir2 | XORsH == ir2 |
ADCsA_L == ir2 | SBCsL == ir2 | XORsL == ir2 |
ADCsA_6HL7 == ir2 | SBCs6HL7 == ir2 | XORs6HL7 == ir2 |
ADCsA_A == ir2 | SBCsA == ir2 | XORsA == ir2 |
ADDsA_N == ir2 | // ADD A,N ; C6 XX ADDsA_6HL7 = 'h86
ADCsA_N == ir2 | // ADC A,N ; CE XX ADCsA_6HL7 = 'h8E
SUBsN == ir2 | // SUB N ; D6 XX SUBs6HL7 = 'h96
SBCsA_N == ir2 | // SBC A,N ; DE XX
ANDsN == ir2 | // AND N ; E6 XX
XORsN == ir2 | // XOR N ; EE XX
ORsN == ir2 ; // OR N ; F6 XX
assign up_a_sh_alu =
RLCA == ir2 | // RLCA ; 07
RRCA == ir2 | // RRCA ; 0F
RRA == ir2 | // RRA ; 1F
RLA == ir2 ; // RLA ; 17
assign up_a_src_pqr =
LDsA_B == ir2 | // LD A,B ; 78
LDsA_C == ir2 | // LD A,C ; 79
LDsA_D == ir2 | // LD A,D ; 7A
LDsA_E == ir2 | // LD A,E ; 7B
LDsA_H == ir2 | // LD A,H ; 7C
LDsA_L == ir2 | // LD A,L ; 7D
LDsA_6HL7 == ir2 | // LD A,(HL) ; 7E
LDsA_A == ir2 ; // LD A,A ; 7F
assign up_a_n =
LDsA_N == ir2 | // LD A,N ; 3E XX
LDsA_6BC7 == ir2 | // LD A,(BC) ; 0A
LDsA_6DE7 == ir2 | // LD A,(DE) ; 1A
LDsA_6NN7 == ir2 | // LD A,(NN) ; 3A XX XX
INsA_6N7 == ir2 | // IN A,(N) ; DB XX
(ED_INsREG_6C7 == {ir2[9:6],ir2[2:0]}) & (ir2[5:3] == REG8_A) ;
 
 
//EXsAF_AFp = 10'h08,// EX AF,AF' ; 08
//EXX = 10'hD9,// EXX ; D9
//DAA = 10'h27,// DAA ; 27
//CPL = 10'h2F,// CPL ; 2F a <= ~a
//POPsAF = 10'hF1,// POP AF ; F1
// don't forget these beauties not affected by prefixes
//ED_RRD = 'h67// RRD ;
//ED_RLD = 'h6F// RLD ; ED 6F nibble roates A (HL)
//ED_NEG = 5'b01___100, // A<= -A compair with {ir2[9:6],ir2[2:0]}
 
//------------------------------- ar ------------------------------------------
 
assign upd_ar = upd_a_alu8 | up_a_sh_alu | up_a_src_pqr | up_a_n | ir2 == EXsAF_AFp |
ir2 == EXX | ir2 == DAA | ir2 == CPL | ir2 == POPsAF |
ir2[2:0] == REG8_A & bit_alu_act | ir2[2:0] == REG8_A & sh_alu_act |
ir2== ED_RRD | {ir2[9:6], ir2[2:0]} == ED_NEG |
ir2 == ED_LDsA_I ;
always @(posedge clk)
begin
if (upd_a_alu8 & exec_ir2) ar <= alu8_out;
if (up_a_sh_alu & exec_ir2) ar <= sh_alu;
if (up_a_src_pqr & exec_ir2) ar <= src_pqr20;
if (up_a_n & exec_ir2) ar <= nn[7:0];
if (ir2 == EXsAF_AFp & exec_ir2) ar <= ap;
if (ir2 == EXX & exec_ir2) ar <= ap;
if (ir2 == DAA & exec_ir2) ar <= daa_alu;
if (ir2 == CPL & exec_ir2) ar <= ~ar;
if (ir2 == POPsAF & exec_ir2) ar <= nn[15:8];
if (ir2[2:0] == REG8_A &
bit_alu_act & exec_ir2) ar <= bit_alu;
if (ir2[2:0] == REG8_A &
sh_alu_act & exec_ir2) ar <= sh_alu;
if (ir2 == ED_RRD & exec_ir2) ar[3:0] <= nn[3:0];
if (ir2 == ED_RLD & exec_ir2) ar[3:0] <= nn[7:4];
if ({ir2[9:6], ir2[2:0]} == ED_NEG & exec_ir2) ar <= alu8_out; // ED44 this done by alu8 for flags
if (ir2 == ED_LDsA_I & exec_ir2) ar <= ir2[7:0] ;
end
 
 
 
 
// update br
//assign upd_b_decbc =
// ED_LDI == ir2 | // LDI ; ED A0
// ED_CPI == ir2 | // CPI ; ED A1
// ED_LDD == ir2 | // LDD ; ED A8
// ED_CPD == ir2 | // CPD ; ED A9
// ED_LDIR == ir2 | // LDIR ; ED B0
// ED_CPIR == ir2 | // CPIR ; ED B1
// ED_LDDR == ir2 | // LDDR ; ED B8
// ED_CPDR == ir2 ;// CPDR ; ED B9
 
//assign eb_io =
 
// ED_INI == ir2 | // INI ; ED A2
// ED_IND == ir2 | // IND ; ED AA
// ED_OUTD == ir2 | // OUTD ; ED AB
// ED_OUTI == ir2 | // OUTI ; ED A3
// ED_INIR == ir2 | // INIR ; ED B2
// ED_OTIR == ir2 | // OTIR ; ED B3
// ED_INDR == ir2 | // INDR ; ED BA
// ED_OTDR == ir2 ; // OTDR ; ED BB
 
assign upd_b_alu8 =
INCsB == ir2 |// INC B ; 04
DECsB == ir2 ;// DEC B ; 05
 
 
assign up_b_src_pqr =
LDsB_B == ir2 |// LD B,B ; 40
LDsB_C == ir2 |// LD B,C ; 41
LDsB_D == ir2 |// LD B,D ; 42
LDsB_E == ir2 |// LD B,E ; 43
LDsB_H == ir2 |// LD B,H ; 44
LDsB_L == ir2 |// LD B,L ; 45
LDsB_6HL7 == ir2 |// LD B,(HL) ; 46
LDsB_A == ir2 ;// LD B,A ; 47
assign up_b_add16 =
INCsBC == ir2 |// INC BC ; 03
DECsBC == ir2 ;// DEC BC ; 0B
//LDsBC_nn = 10'h01,// LD BC,NN ; 01 XX XX
//POPsBC = 10'hC1,// POP BC ; C1
//EXX = 10'hD9,// EXX ; D9
//LDsB_N = 10'h06,// LD B,N ; 06 XX
//DJNZs$t2 = 10'h10,// DJNZ $+2 ; 10 XX //pre dec br
//ED_RRD = 'h67// RRD ; ED 67 nibble roates A HL
//ED_RLD = 'h6F// RLD ; ED 6F nibble roates A HL
//ED_INsREG_6C7 = 5'b01___000,// compair with {ir2[7:6],ir2[2:0]} really (BCio)
 
//------------------------------- br -----------------------------------------
 
assign upd_br = upd_b_alu8 | up_b_src_pqr | up_b_add16 | LDsBC_NN == ir2 |
POPsBC == ir2 | EXX == ir2 | LDsB_N == ir2 |
ir2[2:0] == REG8_B & bit_alu_act | ir2[2:0] == REG8_B & sh_alu_act |
DJNZs$t2 == ir2 | (ED_INsREG_6C7 == {ir2[9:6],ir2[2:0]}) & (ir2[5:3] == REG8_B);
 
 
always @(posedge clk)
begin
if ( upd_b_alu8 & exec_ir2) br <= alu8_out;
if ( up_b_src_pqr & exec_ir2) br <= src_pqr20;
if ( up_b_add16 & exec_ir2) br <= add16[15:8];
if ( LDsBC_NN == ir2 & exec_ir2) br <= nn[15:8];
if ( POPsBC == ir2 & exec_ir2) br <= nn[15:8];
if ( EXX == ir2 & exec_ir2) br <= bp;
if ( LDsB_N == ir2 & exec_ir2) br <= nn[7:0];
if (ir2[2:0] == REG8_B &
bit_alu_act & exec_ir2) br <= bit_alu;
if (ir2[2:0] == REG8_B &
sh_alu_act & exec_ir2) br <= sh_alu;
if ( DJNZs$t2 == ir2 & exec_ir2) br <= br + 8'hff; // use seperate adder here as no flags
// change -- we need br==0. for now
// use |br. If we need more speed add
// a ff.
if (exec_decb | exec_decbc) br <= decb_alu;
if ( (ED_INsREG_6C7 == {ir2[7:6],ir2[2:0]}) & (ir2[5:3] == REG8_B) & exec_ir2 )
br <= nn[7:0];
end
 
 
// update cr
assign up_c_add16 =
INCsBC == ir2 |// INC BC ; 03
DECsBC == ir2 ;// DEC BC ; 0B,
assign upd_c_alu8 =
INCsC == ir2 |// INC C ; 0C
DECsC == ir2 ;// DEC C ; 0D
assign up_c_src_pqr =
LDsC_B == ir2 |// LD C,B ; 48
LDsC_C == ir2 |// LD C,C ; 49
LDsC_D == ir2 |// LD C,D ; 4A
LDsC_E == ir2 |// LD C,E ; 4B
LDsC_H == ir2 |// LD C,H ; 4C
LDsC_L == ir2 |// LD C,L ; 4D
LDsC_6HL7 == ir2 |// LD C,(HL) ; 4E
LDsC_A == ir2 ;// LD C,A ; 4F
 
 
//LDsC_N == ir2 |// LD C,N ; 0E XX
//LDsBC_NN = 10'h01,// LD BC,NN ; 01 XX XX
//POPsBC = 10'hC1,// POP BC ; C1
//EXX = 10'hD9,// EXX ; D9
//ED_INsREG_6C7 = 5'b01___000,// compair with {ir2[9:6],ir2[2:0]} really (BCio)
 
//------------------------------- cr -----------------------------------------
assign upd_cr = upd_c_alu8 | up_c_src_pqr | up_c_add16 | LDsBC_NN == ir2 |
POPsBC == ir2 | EXX == ir2 | LDsC_N == ir2 |
ir2[2:0] == REG8_C & bit_alu_act | ir2[2:0] == REG8_C & sh_alu_act |
(ED_INsREG_6C7 == {ir2[9:6],ir2[2:0]}) & (ir2[5:3] == REG8_C);
 
 
 
always @(posedge clk)
begin
if ( upd_c_alu8 & exec_ir2) cr <= alu8_out;
if ( up_c_src_pqr & exec_ir2) cr <= src_pqr20;
if ( up_c_add16 & exec_ir2) cr <= add16[7:0];
if ( LDsBC_NN == ir2 & exec_ir2) cr <= nn[7:0];
if ( POPsBC == ir2 & exec_ir2) cr <= nn[7:0];
if ( EXX == ir2 & exec_ir2) cr <= cp;
if ( LDsC_N == ir2 & exec_ir2) cr <= nn[7:0];
if (ir2[2:0] == REG8_C &
bit_alu_act & exec_ir2) cr <= bit_alu;
if (ir2[2:0] == REG8_C &
sh_alu_act & exec_ir2) cr <= sh_alu;
if ( exec_decbc) cr <= decc_alu;
if ((ED_INsREG_6C7 == {ir2[9:6],ir2[2:0]}) & (ir2[5:3] == REG8_C) & exec_ir2)
cr <= nn[7:0];
end
 
 
// update dr
assign up_d_add16 =
INCsDE == ir2 | // INC DE ; 13
DECsDE == ir2 ; // DEC DE ; 1B
 
assign upd_d_alu8 =
INCsD == ir2 | // INC D ; 14
DECsD == ir2 ; // DEC D ; 15
assign up_d_src_pqr =
LDsD_B == ir2 | //LD D,B ; 50
LDsD_C == ir2 | //LD D,C ; 51
LDsD_D == ir2 | //LD D,D ; 52
LDsD_E == ir2 | //LD D,E ; 53
LDsD_H == ir2 | //LD D,H ; 54
LDsD_L == ir2 | //LD D,L ; 55
LDsD_6HL7 == ir2 | //LD D,(HL) ; 56endmodule
LDsD_A == ir2 ; //LD D,A ; 57
 
//LDsD_N = 10'h16,// LD D,N ; 16 XX
//LDsDE_NN = 10'h11,// LD DE,NN ; 11 XX XX
//POPsDE = 10'hD1,// POP DE ; D1
//EXX = 10'hD9,// EXX ; D9
//EXsDE_HL = 10'hEB,// EX DE,HL ; EB
//ED_INsREG_6C7 = 5'b01___000,// compair with {ir2[9:6],ir2[2:0]} really (BCio)
 
//---------------------------------- dr ------------------------------------
 
assign upd_dr = upd_d_alu8 | up_d_src_pqr | up_d_add16 | LDsDE_NN == ir2 |
POPsDE == ir2 | EXX == ir2 | EXsDE_HL == ir2 | LDsD_N == ir2 |
ir2[2:0] == REG8_D & bit_alu_act | ir2[2:0] == REG8_D & sh_alu_act |
(ED_INsREG_6C7 == {ir2[9:6],ir2[2:0]}) & (ir2[5:3] == REG8_D);
 
 
 
 
 
 
always @(posedge clk)
begin
if ( upd_d_alu8 & exec_ir2) dr <= alu8_out;
if ( up_d_src_pqr & exec_ir2) dr <= src_pqr20;
if ( up_d_add16 & exec_ir2) dr <= add16[15:8];
if ( LDsDE_NN == ir2 & exec_ir2) dr <= nn[15:8];
if ( POPsDE == ir2 & exec_ir2) dr <= nn[15:8];
if ( EXX == ir2 & exec_ir2) dr <= dp;
if ( EXsDE_HL == ir2 & exec_ir2) dr <= hr;
if ( LDsD_N == ir2 & exec_ir2) dr <= nn[7:0];
if (ir2[2:0] == REG8_D &
bit_alu_act & exec_ir2) dr <= bit_alu;
if (ir2[2:0] == REG8_D &
sh_alu_act & exec_ir2) dr <= sh_alu;
if ((ED_INsREG_6C7 == {ir2[9:6],ir2[2:0]})
& (ir2[5:3] == REG8_D) & exec_ir2)
dr <= nn[7:0];
 
end
 
// update er
assign up_e_add16 =
INCsDE == ir2 |// INC DE ; 13
DECsDE == ir2 ;// DEC DE ; 1B
assign upd_e_alu8 =
INCsE == ir2 |// INC E ; 1C
DECsE == ir2 ;// DEC E ; 1D
assign up_e_src_pqr =
LDsE_B == ir2 |// LD E,B ; 58
LDsE_C == ir2 |// LD E,C ; 59
LDsE_D == ir2 |// LD E,D ; 5A
LDsE_E == ir2 |// LD E,E ; 5B
LDsE_H == ir2 |// LD E,H ; 5C
LDsE_L == ir2 |// LD E,L ; 5D
LDsE_6HL7 == ir2 |// LD E,(HL) ; 5E
LDsE_A == ir2 ;// LD E,A ; 5F
 
//LDsE_N = 10'h1E,// LD E,N ; 1E XX
//LDsDE_NN = 10'h11,// LD DE,NN ; 11 XX XX
//POPsDE = 10'hD1,// POP DE ; D1
//EXX = 10'hD9,// EXX ; D9
//EXsDE_HL = 10'hEB,// EX DE,HL ; EB
//ED_INsREG_6C7 = 5'b01___000,// compair with {ir2[9:6],ir2[2:0]} really (BCio)
 
//---------------------------------- er ------------------------------------
 
 
assign upd_er = upd_e_alu8 | up_e_src_pqr | up_e_add16 | LDsDE_NN == ir2 |
POPsDE == ir2 | EXX == ir2 | EXsDE_HL == ir2 | LDsD_N == ir2 |
ir2[2:0] == REG8_E & bit_alu_act | ir2[2:0] == REG8_E & sh_alu_act |
(ED_INsREG_6C7 == {ir2[9:6],ir2[2:0]}) & (ir2[5:3] == REG8_E);
 
 
 
 
 
 
 
 
 
always @(posedge clk)
begin
if ( upd_e_alu8 & exec_ir2) er <= alu8_out;
if ( up_e_src_pqr & exec_ir2) er <= src_pqr20;
if ( up_e_add16 & exec_ir2) er <= add16[7:0];
if ( LDsDE_NN == ir2 & exec_ir2) er <= nn[7:0];
if ( POPsDE == ir2 & exec_ir2) er <= nn[7:0];
if ( EXX == ir2 & exec_ir2) er <= ep;
if ( EXsDE_HL == ir2 & exec_ir2) er <= hr;
if ( LDsE_N == ir2 & exec_ir2) er <= nn[7:0];
if (ir2[2:0] == REG8_E &
bit_alu_act & exec_ir2) er <= bit_alu;
if (ir2[2:0] == REG8_E &
sh_alu_act & exec_ir2) er <= sh_alu;
if ((ED_INsREG_6C7 == {ir2[9:6],ir2[2:0]}) & (ir2[5:3] == REG8_E) & exec_ir2)
er <= nn[7:0];
end
 
 
// update hr
assign up_h_add16 =
ADDsHL_BC == ir2 | // ADD HL,BC ; 09
ADDsHL_DE == ir2 | // ADD HL,DE ; 19
ADDsHL_HL == ir2 | // ADD HL,HL ; 29
ADDsHL_SP == ir2 | // ADD HL,SP ; 39
INCsHL == ir2 | // INC HL ; 23
DECsHL == ir2 ; // DEC HL ; 2B
assign upd_h_alu8 =
INCsH == ir2 | // INC H ; 24
DECsH == ir2 ; // DEC H ; 25
assign upd_h_src_pqr =
LDsH_B == ir2 | // LD H,B ; 60
LDsH_C == ir2 | // LD H,C ; 61
LDsH_D == ir2 | // LD H,D ; 62
LDsH_E == ir2 | // LD H,E ; 63
LDsH_H == ir2 | // LD H,H ; 64
LDsH_L == ir2 | // LD H,L ; 65
LDsH_6HL7 == ir2 | // LD H,(HL) ; 66
LDsH_A == ir2 ; // LD H,A ; 67
//ED_INsREG_6C7 = 5'b01___000,// compair with {ir2[9:6],ir2[2:0]} really (BCio)
 
//POPsHL = 10'hE1,// POP HL ; E1
//EXs6SP7_HL = 10'hE3,// EX (SP),HL ; E3
//LDsHL_NN = 10'h21,// LD HL,NN ; 21 XX XX
//LDsHL_6NN7 = 10'h2A,// LD HL,(NN) ; 2A XX XX
//LDsH_N = 10'h26,// LD H,N ; 26 XX
 
// only these are not affected by dd and fd prefixes
//EXsDE_HL = 10'hEB,// EX DE,HL ; EB
//EXX = 10'hD9,// EXX ; D9
 
//---------------------------------- hr ------------------------------------
// we just check hr and lr - the prefixes for use of ix and iy imply that something
// pretty strange has to happen for a hazard related to use of those registers. We can
// assume upd hr impies upd ix and iy without adverse timing consequences.
//
assign upd_hr = upd_h_alu8 | upd_h_src_pqr | up_h_add16 | LDsHL_NN == ir2 | LDsHL_6NN7== ir2 |
POPsHL == ir2 | EXX == ir2 | EXsDE_HL == ir2 | LDsH_N == ir2 |
ir2[2:0] == REG8_H & bit_alu_act | ir2[2:0] == REG8_H & sh_alu_act |
(ED_INsREG_6C7 == {ir2[9:6],ir2[2:0]}) & (ir2[5:3] == REG8_H);
 
 
 
 
wire exec_hlir2 = exec_ir2 & !(dd_grp | fd_grp);
 
always @(posedge clk)
begin
if ( upd_h_alu8 & exec_hlir2) hr <= alu8_out;
if ( upd_h_src_pqr & exec_hlir2) hr <= src_pqr20;
if ( up_h_add16 & exec_hlir2) hr <= add16[15:8];
if ( LDsHL_NN == ir2 & exec_hlir2) hr <= nn[15:8];
if ( LDsHL_6NN7== ir2 & exec_hlir2) hr <= nn[15:8];
if ( POPsHL == ir2 & exec_hlir2) hr <= nn[15:8];
if ( EXs6SP7_HL== ir2 & exec_hlir2) hr <= nn[15:8];
if ( EXX == ir2 & exec_ir2) hr <= hp;
if ( EXsDE_HL == ir2 & exec_ir2) hr <= dr;
if ( LDsH_N == ir2 & exec_hlir2) hr <= nn[7:0];
if (ir2[2:0] == REG8_H &
bit_alu_act & exec_hlir2) hr <= bit_alu;
if (ir2[2:0] == REG8_H &
sh_alu_act & exec_hlir2) hr <= sh_alu;
if ((ED_INsREG_6C7 == {ir2[9:6],ir2[2:0]}) & (ir2[5:3] == REG8_H) & exec_ir2)
hr <= nn[7:0];
 
end
 
// update lr
assign up_l_add16 =
ADDsHL_BC == ir2 |// ADD HL,BC ; 09
ADDsHL_DE == ir2 |// ADD HL,DE ; 19
ADDsHL_HL == ir2 |// ADD HL,HL ; 29
ADDsHL_SP == ir2 |// ADD HL,SP ; 39
INCsHL == ir2 |// INC HL ; 23
DECsHL == ir2 ;// DEC HL ; 2B
assign upd_l_alu8 =
INCsL == ir2 |// INC L ; 2C
DECsL == ir2 ;// DEC L ; 2D
assign upd_l_src_pqr =
LDsL_B == ir2 |// LD L,B ; 68
LDsL_C == ir2 |// LD L,C ; 69
LDsL_D == ir2 |// LD L,D ; 6A
LDsL_E == ir2 |// LD L,E ; 6B
LDsL_H == ir2 |// LD L,H ; 6C
LDsL_L == ir2 |// LD L,L ; 6D
LDsL_6HL7 == ir2 |// LD L,(HL) ; 6E
LDsL_A == ir2 ;// LD L,A ; 6F
//EXX = 10'hD9,// EXX ; D9
//POPsHL = 10'hE1,// POP HL ; E1
//EXs6SP7_HL = 10'hE3,// EX (SP),HL ; E3
//EXsDE_HL = 10'hEB,// EX DE,HL ; EB
//LDsHL_NN = 10'h21,// LD HL,NN ; 21 XX XX
//LDsHL_6NN7 = 10'h2A,// LD HL,(NN) ; 2A XX XX
//LDsL_N = 10'h2E,// LD L,N ; 2E XX
//ED_INsREG_6C7
 
 
 
//---------------------------------- lr ------------------------------------
assign upd_lr = upd_l_alu8 | upd_l_src_pqr | up_l_add16 | LDsHL_NN == ir2 | LDsHL_6NN7== ir2 |
POPsHL == ir2 | EXX == ir2 | EXsDE_HL == ir2 | LDsL_N == ir2 |
ir2[2:0] == REG8_L & bit_alu_act | ir2[2:0] == REG8_L & sh_alu_act |
(ED_INsREG_6C7 == {ir2[9:6],ir2[2:0]}) & (ir2[5:3] == REG8_L);
 
 
 
always @(posedge clk)
begin
if ( upd_l_alu8 & exec_hlir2) lr <= alu8_out;
if ( upd_l_src_pqr & exec_hlir2) lr <= src_pqr20;
if ( up_l_add16 & exec_hlir2) lr <= add16[7:0];
if ( LDsHL_NN == ir2 & exec_hlir2) lr <= nn[7:0];
if ( LDsHL_6NN7== ir2 & exec_hlir2) lr <= nn[7:0];
if ( POPsHL == ir2 & exec_hlir2) lr <= nn[7:0];
if ( EXs6SP7_HL== ir2 & exec_hlir2) lr <= nn[7:0];
if ( EXX == ir2 & exec_ir2) lr <= lp;
if ( EXsDE_HL == ir2 & exec_ir2) lr <= er;
if ( LDsL_N == ir2 & exec_hlir2) lr <= nn[7:0];
if (ir2[2:0] == REG8_L &
bit_alu_act & exec_hlir2) lr <= bit_alu;
if (ir2[2:0] == REG8_L &
sh_alu_act & exec_hlir2) lr <= sh_alu;
if ((ED_INsREG_6C7 == {ir2[9:6],ir2[2:0]}) & (ir2[5:3] == REG8_L) & exec_ir2)
lr <= nn[7:0];
end
//------------------------ ixr ---------------------------------------------
wire exec_ixir2 = exec_ir2 & dd_grp;
always @(posedge clk)
begin
if ( upd_l_alu8 & exec_ixir2) ixr[7:0] <= alu8_out;
if ( upd_l_src_pqr & exec_ixir2) ixr[7:0] <= src_pqr20;
if ( up_l_add16 & exec_ixir2) ixr[7:0] <= add16[7:0];
if ( LDsHL_NN == ir2 & exec_ixir2) ixr[7:0] <= nn[7:0];
if ( LDsHL_6NN7== ir2 & exec_ixir2) ixr[7:0] <= nn[7:0];
if ( POPsHL == ir2 & exec_ixir2) ixr[7:0] <= nn[7:0];
if ( EXs6SP7_HL== ir2 & exec_ixir2) ixr[7:0] <= nn[7:0];
 
if ( LDsL_N == ir2 & exec_ixir2) ixr[7:0] <= nn[7:0];
if (ir2[2:0] == REG8_L &
bit_alu_act & exec_ixir2) ixr[7:0] <= bit_alu;
if (ir2[2:0] == REG8_L &
sh_alu_act & exec_ixir2) ixr[7:0] <= sh_alu;
end
 
always @(posedge clk)
begin
if ( upd_h_alu8 & exec_ixir2) ixr[15:8] <= alu8_out;
if ( upd_h_src_pqr & exec_ixir2) ixr[15:8] <= src_pqr20;
if ( up_h_add16 & exec_ixir2) ixr[15:8] <= add16[15:8];
if ( LDsHL_NN == ir2 & exec_ixir2) ixr[15:8] <= nn[15:8];
if ( LDsHL_6NN7== ir2 & exec_ixir2) ixr[15:8] <= nn[15:8];
if ( POPsHL == ir2 & exec_ixir2) ixr[15:8] <= nn[15:8];
if ( EXs6SP7_HL== ir2 & exec_ixir2) ixr[15:8] <= nn[15:8];
 
if ( LDsH_N == ir2 & exec_ixir2) ixr[15:8] <= nn[7:0];
if (ir2[2:0] == REG8_H &
bit_alu_act & exec_ixir2) ixr[15:8] <= bit_alu;
if (ir2[2:0] == REG8_H &
sh_alu_act & exec_ixir2) ixr[15:8] <= sh_alu;
end
 
//------------------------ iyr ---------------------------------------------
wire exec_iyir2 = exec_ir2 & fd_grp;
always @(posedge clk)
begin
if ( upd_l_alu8 & exec_iyir2) iyr[7:0] <= alu8_out;
if ( upd_l_src_pqr & exec_iyir2) iyr[7:0] <= src_pqr20;
if ( up_l_add16 & exec_iyir2) iyr[7:0] <= add16[7:0];
if ( LDsHL_NN == ir2 & exec_iyir2) iyr[7:0] <= nn[7:0];
if ( LDsHL_6NN7== ir2 & exec_iyir2) iyr[7:0] <= nn[7:0];
if ( POPsHL == ir2 & exec_iyir2) iyr[7:0] <= nn[7:0];
if ( EXs6SP7_HL== ir2 & exec_iyir2) iyr[7:0] <= nn[7:0];
 
if ( LDsL_N == ir2 & exec_iyir2) iyr[7:0] <= nn[7:0];
if (ir2[2:0] == REG8_L &
bit_alu_act & exec_iyir2) iyr[7:0] <= bit_alu;
if (ir2[2:0] == REG8_L &
sh_alu_act & exec_iyir2) iyr[7:0] <= sh_alu;
end
 
always @(posedge clk)
begin
if ( upd_h_alu8 & exec_iyir2) iyr[15:8] <= alu8_out;
if ( upd_h_src_pqr & exec_iyir2) iyr[15:8] <= src_pqr20;
if ( up_h_add16 & exec_iyir2) iyr[15:8] <= add16[15:8];
if ( LDsHL_NN == ir2 & exec_iyir2) iyr[15:8] <= nn[15:8];
if ( LDsHL_6NN7== ir2 & exec_iyir2) iyr[15:8] <= nn[15:8];
if ( POPsHL == ir2 & exec_iyir2) iyr[15:8] <= nn[15:8];
if ( EXs6SP7_HL== ir2 & exec_iyir2) iyr[15:8] <= nn[15:8];
 
if ( LDsH_N == ir2 & exec_iyir2) iyr[15:8] <= nn[7:0];
if (ir2[2:0] == REG8_H &
bit_alu_act & exec_iyir2) iyr[15:8] <= bit_alu;
if (ir2[2:0] == REG8_H &
sh_alu_act & exec_iyir2) iyr[15:8] <= sh_alu;
end
 
 
//---------------------------- prime regiters (shadows?) ----------------
 
always @(posedge clk)
begin
if (ir2 == EXsAF_AFp & exec_ir2)
begin
ap <= ar;
fp <= fr;
end
if (ir2 == EXX & exec_ir2)
begin
ap <= ar;
fp <= fr;
bp <= br;
cp <= cr;
dp <= dr;
ep <= er;
hp <= hr;
lp <= lr;
end
end
//-------------------------- flag registers -------------------------------
// This is a mess - There is in general no reasonable way to get this stuff to follow
// z80 exactly. --- in some of the undocumented cases, there is not even a
// guess expressed about what is actually done. In some of the other undocumented
// cases, what is claimed happens is soo silly that It is hard for me to believe
// it matters ( unfortunately i am far too aware that one man's garbage can be
// anothers treasure --- or....., its amazing how silly
// behavior (bug?) can become a feature. In any case, The attempt (at first blush) is
// only to get the documented stuff right -- although if undocumented behavior
// falls out, great. For exmple, I will typically update f3f and f5f with alu output -
// these flags are documented as "undefined".
//
// some of the wierd stuff to worry about:
// 16 bit ops:
// the ed insts SBC ADC muck with all flags but
// the ADD inst doesn't change sf zf or pvf.
// and the 16 bit INC and DEC insts touch nothing
//
// the ED_RLD and RRD instructions muck with flags based on ar -- these operations
// should be correct rleative to subsequent DAA's i suppose.
 
// update all flags from alu8 for logic operations pv <= parity else ofl
// INC and DEC same as but no cf change oh my god why? done in logic above
 
assign upd_fr_alu8 =
ADCsA_A == ir2 | ANDsA == ir2 | ORsA == ir2 | SUBsA == ir2 | DECsA == ir2 |
ADCsA_B == ir2 | ANDsB == ir2 | ORsB == ir2 | SUBsB == ir2 | DECsB == ir2 |
ADCsA_C == ir2 | ANDsC == ir2 | ORsC == ir2 | SUBsC == ir2 | DECsC == ir2 |
ADCsA_D == ir2 | ANDsD == ir2 | ORsD == ir2 | SUBsD == ir2 | DECsD == ir2 |
ADCsA_E == ir2 | ANDsE == ir2 | ORsE == ir2 | SUBsE == ir2 | DECsE == ir2 |
ADCsA_H == ir2 | ANDsH == ir2 | ORsH == ir2 | SUBsH == ir2 | DECsH == ir2 |
ADCsA_L == ir2 | ANDsL == ir2 | ORsL == ir2 | SUBsL == ir2 | DECsL == ir2 |
ADCsA_6HL7==ir2 | ANDs6HL7 ==ir2 | ORs6HL7 ==ir2 | SUBs6HL7 ==ir2 | INCsA == ir2 |
ADDsA_A == ir2 | CPsA == ir2 | SBCsA == ir2 | XORsA == ir2 | INCsB == ir2 |
ADDsA_B == ir2 | CPsB == ir2 | SBCs6HL7 ==ir2 | XORsB == ir2 | INCsC == ir2 |
ADDsA_C == ir2 | CPsC == ir2 | SBCsB == ir2 | XORsC == ir2 | INCsD == ir2 |
ADDsA_D == ir2 | CPsD == ir2 | SBCsC == ir2 | XORsD == ir2 | INCsE == ir2 |
ADDsA_E == ir2 | CPsE == ir2 | SBCsD == ir2 | XORsE == ir2 | INCsH == ir2 |
ADDsA_H == ir2 | CPsH == ir2 | SBCsE == ir2 | XORsH == ir2 | INCsL == ir2 |
ADDsA_L == ir2 | CPsL == ir2 | SBCsH == ir2 | XORsL == ir2 | INCs6HL7 == ir2 |
ADDsA_6HL7== ir2| CPs6HL7 ==ir2 | SBCsL == ir2 | XORs6HL7 == ir2 | DECs6HL7 == ir2 |
ED_NEG == {ir2[9:6],ir2[2:0]} ; //7'b1001___100, A<= -A
 
 
// update h n c (f5, f3) from alu16
assign upd_fr_add16 =
ADDsHL_BC == ir2 | // ADD HL,BC ; 09
ADDsHL_DE == ir2 | // ADD HL,DE ; 19
ADDsHL_HL == ir2 | // ADD HL,HL ; 29
ADDsHL_SP == ir2 ; // ADD HL,SP ; 39
// INCsBC == ir2 | // INC BC ; 03 no flag changes for these
// INCsDE == ir2 | // INC DE ; 13
// INCsHL == ir2 | // INC HL ; 23
// INCsSP == ir2 ; // INC SP ; 33
 
// update all flags from alu16
assign upd_fr_edadd16 =
ED_SBCsHL_REG == {ir2[9:6],ir2[3:0]} | // compair with {ir2[9:6],ir2[3:0]}
ED_ADCsHL_REG == {ir2[9:6],ir2[3:0]} ; // compair with {ir2[9:6],ir2[3:0]}
 
 
// the shifts probably muck with all flags (some operations are
// guarenteed not to change certain flags )
// docs say sf and zf never change for these ops.
assign upd_fr_sh =
RLA == ir2 |// RLA ; 17
RLCA == ir2 |// RLCA ; 07
RRA == ir2 |// RRA ; 1F
RRCA == ir2 ;// RRCA ; 0F
// sf and zf do change for theses
assign upd_fr_cbsh =
CB_RLC == ir2[9:3] | // these must be compaired with ir2[9:3]
CB_RRC == ir2[9:3] | // these must be compaired with ir2[9:3]
CB_RL == ir2[9:3] | // these must be compaired with ir2[9:3]
CB_RR == ir2[9:3] | // these must be compaired with ir2[9:3]
CB_SLA == ir2[9:3] | // these must be compaired with ir2[9:3]
CB_SRA == ir2[9:3] | // these must be compaired with ir2[9:3]
CB_SLL == ir2[9:3] | // these must be compaired with ir2[9:3]
CB_SRL == ir2[9:3] ; // these must be compaired with ir2[9:3]
 
// pretty nomal stuff here
//CB_BIT = 4'b01_01, // these must be compaired with ir2[9:6]
// which alu? -- done from alu8
//ED_NEG = 5'b01___100, // compair with {ir2[7:6],ir2[2:0]} all A<= -A
 
// rmw 8 types these handled by standard INC and DEC logic done.
//INCs6HL7 = 'h34,// INC (HL) ; 34
//DECs6HL7 = 'h35,// DEC (HL) ; 35
 
// ED Block Move messyness upd_b_decbc 4/19/2004 not used - probably not needed
// hf and nf <= 0 pnf<= BC==0
//assign eb_blk_mv =
// ED_LDI == ir2 | // LDI ; ED A0 (DE++) <= (HL++) , BC--
// ED_LDD == ir2 | // LDD ; ED A8 (DE--) <= (HL--) , BC--
// ED_LDIR == ir2 | // LDIR ; ED B0 (DE++) <= (HL++) , BC-- Repeat til BC==0
// ED_LDDR == ir2 ;// LDDR ; ED B8 (DE--) <= (HL--) , BC-- Repeat til BC==0
// only c not affected - nf<=1 ?
assign ed_blk_cp =
ED_CPI == ir2 | // CPI ; ED A1 A - (HL++) , BC--
ED_CPD == ir2 | // CPD ; ED A9 A - (HL--) , BC--
ED_CPIR == ir2 | // CPIR ; ED B1 A - (HL++) , BC-- repeat if(|B
ED_CPDR == ir2 ;// CPDR ; ED B9 A - (HL--) , BC-- repeat if(|B
 
// all the ed i/o muck with all flags -- wonderful cf?
// use the aluoutput for the b-1 computation.
// --------- eb_io
//ED_INI = 'hA2// INI ; ED A2 (HL++) <- (Cio) , B--
//ED_IND = 'hAA// IND ; ED AA (HL--) <- (Cio) , B--
//ED_INIR = 'hB2// INIR ; ED B2 (HL++) <- (Cio) , B-- repeat if(|B)
//ED_INDR = 'hBA// INDR ; ED BA (HL--) <- (Cio) , B-- repeat if(|B)
//ED_OUTI = 'hA3// OUTI ; ED A3 (Cio) <-(HL++) , B--
//ED_OUTD = 'hAB// OUTD ; ED AB (Cio) <-(HL--) , B--
//ED_OTIR = 'hB3// OTIR ; ED B3 (Cio) <-(HL++) , B-- rpt if(|B)
//ED_OTDR = 'hBB// OTDR ; ED BB (Cio) <-(HL--) , B-- rpt if(|B)
 
//ED_INsREG_6C7 = 5'b01___000,// compair with {ir2[7:6],ir2[2:0]} really (BCio)
 
 
 
// special problems -- lol more special problems ????
//CCF = 'h3F,// CCF ; 3F // h<=c c<=~C N<=0 F3,F5?
//CPL = 'h2F,// CPL ; 2F // H<=1 N<=1 F3,F5?
//DAA = 'h27,// DAA ; 27 // H<=0???
//SCF = 'h37,// SCF ; 37
//ED_RRD = 'h67// RRD ; ED 67 nibble roates A HL
//ED_RLD = 'h6F// RLD ; ED 6F nibble roates A HL
//ED_LDsA_I = 'h57// LD A,I ; ED 57 move I to A
 
assign { sf, zf, f5f, hf, f3f, pvf, nf, cf} = fr;
// gotta say those little ~^ operators down there worry me. Only 4 levels of xor - but jeeze
// there are a lot of them. I guess in most FPGA's it doesn't matter what the op is - just
// how many terms.
 
 
// do we need the exe_ir2 term here? isn't it added in the hazard term anyway?
assign upd_fr = exec_ir2 & ( ( upd_fr_alu8 ) |
( upd_fr_add16) |
( upd_fr_edadd16) |
( upd_fr_sh ) |
( upd_fr_cbsh ) |
(CB_BIT == ir2[9:6]) |
( ed_blk_cp ) |
(ED_INsREG_6C7 == {ir2[7:6],ir2[2:0]}) |
(CCF == ir2 ) |
(CPL == ir2 ) |
(DAA == ir2 ) |
(SCF == ir2 ) |
(ED_RRD == ir2) |
(ED_RLD == ir2) |
(ED_LDsA_I == ir2) |
(ir2 == EXsAF_AFp ) |
(ir2 == EXX ) );
 
 
 
wire iff2 = 1'b0; // this is supposed to be int ff #2 which is not (yet) implmented
always @(posedge clk)
begin
if (exec_ir2)
begin
if ( upd_fr_alu8 ) fr <= alu8_fr; // assembled above with 8 bit ALU
if ( upd_fr_add16) fr <= {sf, zf, add16[13], c_16out11, add16[11], pvf, 1'b0, c_16out15};
if ( upd_fr_edadd16) fr <= {add16[15], ~|add16, add16[13], c_16out11,
add16[11], add16_ofl, ~ir2[3], c_16out15};
if ( upd_fr_sh ) fr <= {sf, zf, sh_alu[5], 1'b0, sh_alu[3], pvf, 1'b0, sh_cry};
if ( upd_fr_cbsh ) fr <= {sh_alu[7], ~|sh_alu, sh_alu[5], 1'b0,
sh_alu[3], ~^sh_alu, 1'b0, sh_cry};
if (CB_BIT == ir2[9:6]) fr <={bit_alu[7], ~|bit_alu, bit_alu[5], 1'b1, //no idea why hf<=1
bit_alu[3], ~|bit_alu, 1'b0 , cf };// pvf == zf ???
if ( ed_blk_cp ) fr <= {alu8_out[7], ~|alu8_out, alu8_out[5], alu8_hcry,//std a-n stuff
alu8_out[3], alu8_out[7], 1'b1, cf }; //cept nf and cf
if (ED_INsREG_6C7 == {ir2[7:6],ir2[2:0]})
fr <= {nn[7], ~|nn[7:0], nn[5], 1'b0, nn[3], ~^nn[7:0], 1'b0, cf};
if (CCF == ir2 ) fr <= {sf, zf, f5f, cf, f3f, pvf, nf, ~cf};
if (CPL == ir2 ) fr <= {sf, zf, ar[5], 1'b1, ar[3], pvf, 1'b1, cf};
if (DAA == ir2 ) fr <= {daa_alu[7], ~|daa_alu, daa_alu[5], 1'b0, // hf sb (logically) 0
daa_alu[3], ~^daa_alu, nf, daa_cry };
if (SCF == ir2 ) fr <= { sf, zf, ar[5], 1'b0, ar[3], pvf, 1'b0, 1'b1 }; // very strange
if (ED_RRD == ir2) fr <= { sf, ~|{ar[7:4],nn[3:0]}, ar[5], 1'b0,
ar[3], ~^{ar[7:4],nn[3:0]}, 1'b0 , cf };
if (ED_RLD == ir2) fr <= { sf, ~|{ar[7:4],nn[7:4]}, ar[5], 1'b0,
ar[3], ~^{ar[7:4],nn[7:4]}, 1'b0 , cf };
if (ED_LDsA_I == ir2) fr <= { ir2[7], ~|ir2, ir2[5], 1'b0, ir2[3], iff2, 1'b0, cf }; // iff2 ?
if (ir2 == EXsAF_AFp) fr <= fp;
if (ir2 == EXX ) fr <= fp;
end
// in the case of blk_cp the update above is executed 2nd - and so these are don't cares.
if (exec_decb ) fr <= {decb_alu[7], ~|decb_alu, decb_alu[5], hf,
decb_alu[3], pvf, 1'b0, cf };
if (exec_decbc ) fr[5:1] <= { decb_alu[5], 1'b0, decb_alu[3], ~|decb_alu, 1'b0 };
end
//----------------------- intr -----------------------------------------------------------
always @(posedge clk or posedge rst)
if (rst) intr <= 8'h0;
else if (( ED_LDsI_A == ir2) & exec_ir2) intr <= ar;
 
endmodule
/trunk/rtl/z80_memstate2.v
0,0 → 1,1616
///////////////////////////////////////////////////////////////////////////////////////////////////
// //
// file name: memstate2.v //
// description: memory opertions for z80 //
// project: wb_z80 //
// //
// Author: B.J. Porcella //
// e-mail: bporcella@sbcglobal.net //
// //
// //
// //
///////////////////////////////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2000-2002 B.J. Porcella //
// Real Time Solutions //
// //
// //
// This source file may be used and distributed without //
// restriction provided that this copyright statement is not //
// removed from the file and that any derivative work contains //
// the original copyright notice and the associated disclaimer. //
// //
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //
// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //
// POSSIBILITY OF SUCH DAMAGE. //
// //
//-------1---------2---------3--------Comments on file -------------7---------8---------9--------0
// The memory state controller controls the wb bus, and provides address sequencing.
// Insructions are fetched in order (using PC) until the istate machine indicates that
// a complete instruction is in the first pipline stage (ir1). In general, operands are being
// fetched (stored) to satisfy ir1 while concurrently instructions are being executed from ir2.
// this situation can result in a number of potential hazards. As an example, if the ir2
// instruction changes the flag register and the ir1 instruction is a conditional jump,
// a hazard is generated by the hazard logic, and execution of the ir1 operation is delayed
// until the completion of the flag update.
//
// Reset starts execution at 0.
// The PC and SP are described in this file. modifications to other index registers -
// HL IX and IY are computed here --
// For the block moves address updates are computed here -- and commanded here.
// Strobes for the second address update are generally co-incident with count updates, but
// we provide seperate strobe update lines for clarity.
//
// BASIC ARCHITECTURE OF THIS FILE pc and sp not shown, but are inputs to src mux.
// _____ and may be updated from adder output.
// | |
// | | pc-1 register is required to implement relative jumps.
// | |
// _____ |lit | |\
// | | | | | \
// | | |src2 | | \ _____ _____
// | | | |----->| | | | | |
// |src | |_____| |adder|------->| | | |
// |mux | | | | | | |
// | |------------------->| / |2/1 |------->|wb |
// | | | | / |mux | |adr |
// |_____| | |/ | | | |
// ------------------->| | | |
// |_____| |_____|
//
//
//
//
// Operand Stores:
// At first cut, I thought I'ld execute operand stores immediately from the memory sequencer
// (essentially before ir2 got the store data). While this might be modestly faster in
// systems that take multiple clocks to complete a memory store, On consideration, I decided
// to forgo the extra speed for conceptual simplicity.... execute operand stores on op_ph1,
// and let the inst_exec engine suply the operand.
//
// On second thought, above is not only wastful of time, but also inconsistent with the overall
// schems of things - and so somewhat more complex. If we simply execute the OS from ir1,
// There is less state to contdend with, as well as extra speed.
//
// Block Moves fundamentally execute from ir2. We initiate the first operand fetch from ir1.
//
// 3/18/2004 Second time through. In impleenting the execution logic it became clear that
// there were "minor" problems with the handling of the DD and FD prefix insts (especially
// DDCD and FDCB --- collectively called PFxCB below. On review, I had to question the
// value of "breaking up" the ir0 execution engine between the istate sequencer and the
// memstate sequencer. While I dislike state sequencers of much more than 16 states --
// the interaction between these sequencers was becomming harder to track than a single
// state macine. Thus - this file is getting re-worked. I will call it memstate2 (at least
// for awhile) as I wish to keep the old file around. I want to show (in the state machine
// logic) what the next memory operation is.... guess the best method consistent with my
// documentation practices is to define a register (mem_op) = { if, wb_we_o, wb_cyc_o }.
// This will require auxillary logic for computing the address --- but most of the decodes
// required will be there anyway.
// On further reflection, I think I will bite-the-bullet and use an always to define next_state.
// I don't like to use always to define wires, but I also want to dicument the setting of
// exec_ir2 in the same place - that is 3 different things.
//
// Hazards:
// There are 2 kinds of hazards: mem_hazard => we are storing into the next instruction location
// reg_hazard => we are modifying a register (ir2) that we are using
// here (ir1)
// In the former case, we throw out the instruction that arrives on the next tick, and restart the
// instruction pipeline, In the latter case, we simply wait a tick for the ir2 operaton to
// complete before starting the ir1 operation
//-------1---------2---------3--------CVS Log -----------------------7---------8---------9--------0
//
// $Id: z80_memstate2.v,v 1.1 2004-04-27 21:27:13 bporcella Exp $
//
// $Date: 2004-04-27 21:27:13 $
// $Revision: 1.1 $
// $Author: bporcella $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.8 2004/04/19 19:13:28 bporcella
// real lint problems pretty much fixed -- need another look - but need to get on to other things first
//
// Revision 1.7 2004/04/19 05:09:11 bporcella
// fixed some lint problems --
//
// Revision 1.6 2004/04/18 18:50:09 bporcella
// fixed some lint problems --
//
// Revision 1.5 2004/04/17 15:18:02 bporcella
// 4th lint try
// Miha claims reports are now correct
//
// Revision 1.4 2004/04/16 18:16:57 bporcella
// try lint
//
// Revision 1.3 2004/04/16 17:06:54 bporcella
// no code change - added a comment and test lint
//
// Revision 1.2 2004/04/16 16:21:04 bporcella
// no code change - added a comment and test lint
//
// Revision 1.1.1.1 2004/04/13 23:50:19 bporcella
// import first files
//
//
//
//-------1---------2---------3--------Module Name and Port List------7---------8---------9--------0
module z80_memstate2(wb_adr_o, wb_we_o, wb_cyc_o, wb_stb_o, wb_tga_o, wb_dat_o,
exec_ir2, ir1, ir2, ir1dd, ir1fd, ir2dd, ir2fd, nn, sp,
upd_ar, upd_br, upd_cr, upd_dr, upd_er, upd_hr, upd_lr,upd_fr,
beq0, ceq0,
ar, fr, br, cr, dr, er, hr, lr, intr,
ixr, iyr,
wb_dat_i, wb_ack_i, wb_clk_i, rst_i,
int_req_i,
add16,
wb_clk_i,
rst_i
 
 
);
 
//-------1---------2---------3--------Output Ports---------6---------7---------8---------9--------0
// mod only to checkout lint
// mod again for lint check -- first check pretty wierd
// 3rd lint try
// 4th lint try
output [15:0] wb_adr_o;
output wb_we_o;
output wb_cyc_o;
output wb_stb_o;
//output wb_lock; // bit set and clear insts should be atomic - could matter sometime
output [1:0] wb_tga_o;
output [7:0] wb_dat_o; // from nn
//output [15:0] add_out; (may not wb_adr_o) 4/18/2004?? why?
 
output exec_ir2;
output [9:0] ir1, ir2;
output ir1dd, ir2dd;
output ir1fd, ir2fd;
output [15:0] nn;
output [15:0] sp;
 
 
 
 
//-------1---------2---------3--------Input Ports----------6---------7---------8---------9--------0
input upd_ar, upd_br, upd_cr, upd_dr, upd_er, upd_hr, upd_lr,upd_fr;
 
input beq0, ceq0;
input [7:0] ar, fr, br, cr, dr, er, hr, lr, intr;
input [15:0] ixr, iyr;
input [7:0] wb_dat_i;
input wb_ack_i, wb_clk_i, rst_i;
input int_req_i;
input [15:0] add16; // ir2 execution engine output for sp updates
 
 
//-------1---------2---------3--------Parameters-----------6---------7---------8---------9--------0
`include "opcodes.v" // states of the main memory sequencer
 
parameter TAG_IO = 2'b01, // need to review general wb usage to undrstand how best to
TAG_INT = 2'b10; // document this.
// 12na // 1 is ir1 2 is ir2 n is nn gets memory a is activate ir2
parameter IPIPE_NOP = 4'b0000, // guess I could define single bits and add them up
IPIPE_A2 = 4'b0001, // would keep from getting lint bitching -- but heck
IPIPE_ENN = 4'b0010, // I'm married -> an expert at ignoring such stuff :-)
IPIPE_ENNA2 = 4'b0011,
IPIPE_EN2 = 4'b0100,
IPIPE_EN2A2 = 4'b0101,
IPIPE_ENNEN2 = 4'b0110,
IPIPE_ENNEN2A2 = 4'b0111,
IPIPE_EN1 = 4'b1000,
IPIPE_EN1A2 = 4'b1001,
IPIPE_BOGUS = 4'b1010, // no reason (yet) to load both n and ir1
IPIPE_BOUS2 = 4'b1011,
IPIPE_EN12 = 4'b1100,
IPIPE_EN12A2 = 4'b1101,
IPIPE_BOGUS3 = 4'b1110,
IPIPE_BOGUS4 = 4'b1111;
// well at first cut I tried to make this 2 state macines both less than 16 states.
// this is 56 states at first cut. Assignemnt is subject to change.
 
// ------ mem state decoder state machine states --------------------------------
parameter DEC_IDLE = 6'h00,
DEC_HALT = 6'h01,
DEC_IF1 = 6'h02,
DEC_IF2 = 6'h03,
DEC_IF2A = 6'h04,
DEC_EXEC = 6'h05,
DEC_CB = 6'h06,
DEC_DDFD = 6'h07,
DEC_ED = 6'h08,
DEC_EDNN1 = 6'h09,
DEC_EDNN2 = 6'h0a,
DEC_EDRD1 = 6'h0b,
DEC_EDRD2 = 6'h0c,
DEC_EDWR = 6'h0d,
DEC_EDBCP1 = 6'h0e,
DEC_EDBCP2 = 6'h0f,
DEC_EDBCP3 = 6'h10,
DEC_EDBIN1 = 6'h11,
DEC_EDBIN2 = 6'h12,
DEC_EDBIN3 = 6'h13,
DEC_EDBOUT1 = 6'h14,
DEC_EDBOUT2 = 6'h15,
DEC_EDBOUT3 = 6'h16,
DEC_EDBMV1 = 6'h17,
DEC_EDBMV2 = 6'h18,
DEC_EDBMV3 = 6'h19,
DEC_N = 6'h1a,
DEC_NIN = 6'h1b,
DEC_NN = 6'h1c,
DEC_NNCALL1 = 6'h1d,
DEC_NNCALL2 = 6'h1e,
DEC_NNOS1 = 6'h1f,
DEC_NNOS2 = 6'h20,
DEC_NNOS3 = 6'h21,
DEC_NNOF1 = 6'h22,
DEC_NNOF2 = 6'h23,
DEC_NNOF3 = 6'h24,
DEC_NNOF4 = 6'h25,
DEC_DDOS = 6'h26,
DEC_DDOF = 6'h27,
DEC_OF = 6'h28,
DEC_POP = 6'h29,
DEC_PUSH = 6'h2a,
DEC_RMW = 6'h2b,
DEC_RMW2 = 6'h2c,
DEC_CBM = 6'h2d,
DEC_PFxCB = 6'h2e,
DEC_PFxCB2 = 6'h2f,
DEC_PFxCB3 = 6'h30,
DEC_PFxCB4 = 6'h31,
DEC_INT1 = 6'h32,
DEC_INT2 = 6'h33,
DEC_INT3 = 6'h34,
DEC_INT4 = 6'h35,
DEC_INT5 = 6'h36,
DEC_RET = 6'h37,
DEC_NNJMP = 6'h38,
DEC_RET2 = 6'h39 ;
// initial decode assignemnts. These assignemens are made to wires on an initial decode
// to help document next state transitions
parameter I1_CB = 4'h0,
I1_DDFD = 4'h1,
I1_ED = 4'h2,
I1_JMP = 4'h3,
I1_N = 4'h4,
I1_NN = 4'h5,
I1_OF = 4'h6,
I1_OS = 4'h7,
I1_POP = 4'h8,
I1_PUSH = 4'h9,
I1_RET = 4'ha,
I1_RMW = 4'hb,
I1_RST = 4'hc,
I1_R2R = 4'hd ;
 
 
// A note here on the choices of mnemonics..... in general, the target registers of
// memory ops are specified by an instruction register (ir1 for stores ir2 for loads).
// so Menomics in general are specifying the address source. However, there are exceptions.
//
parameter MEM_NOP = 5'h00,
MEM_IFPP1 = 5'h01,
MEM_OS1 = 5'h02, // only invoked on I1 OS multiple address sources and data sources
MEM_OF1 = 5'h03, // Address from HL unless LD A,(BC) or LD A,(DE) (used for rmw)
MEM_OFSP = 5'h04, // works for both POP and RET
MEM_OSSP = 5'h05, // if DEC_EXEC op from ir1 else msb nn (implies we store from lsb nn)
// used in CALL also.
MEM_OFIXpD = 5'h06, // used for prefix op fetches - all single bytes
MEM_OSIXpD = 5'h07, // data source is same as MEM_OS1
MEM_OSADR = 5'h08, // used (at lesat) for prefixed rmw -- perhaps others.
MEM_CALL = 5'h09, // pc<=nn, nn<=pc, wb_adr_o<=sp OS
MEM_OSNN = 5'h0a, // if DEC_EXEC op from ir1 else msb nn
MEM_OFNN = 5'h0b, // striaghtfoward
MEM_OFADRP1 = 5'h0c, // used (at least) when double ops above
MEM_OSADRP1 = 5'h0d, // "" "" ""
MEM_IFRST = 5'h0e, // special address transfer
MEM_IFREL_N = 5'h0f, // special address transfer for jmp rel
MEM_JMPHL = 5'h10, // another special jump transfer
MEM_IFNN = 5'h11, // used by call and return
MEM_OFHL_PM = 5'h12, // special block move ops
MEM_OSHL_PM = 5'h13, // special block move ops
MEM_OSDE_PM = 5'h14, // special block move ops
MEM_IOF_C = 5'h15, // special i/o ops
MEM_IOS_C = 5'h16, // operand is ar
MEM_IOF_N = 5'h17,
MEM_IOS_N = 5'h18,
MEM_OS_HL_N = 5'h19,
MEM_OSSP_PCM2 = 5'h1a, // int code (call
MEM_OSSP_P = 5'h1b, //
MEM_INTA = 5'h1c,
MEM_IFINT = 5'h1d,
MEM_DECPC = 5'h1e ;
 
 
 
 
 
 
 
 
//-------1---------2---------3--------Wires----------------6---------7---------8---------9--------0
 
 
//wire use_sp; // old names probably from first go-around
//wire use_pc;
//wire use_hl;
//wire use_de;
//wire use_bc;
//wire use_flags;
wire cb_mem;
//wire br_test8t; // branch test true (8 test field)
//wire br_test4t; // branch test true (4 test field)
//wire ofos;
//wire any_os; // most terms above only valid on mem_exec this includes all stores
wire wb_rdy_nhz;
wire dec_blk_inc;
wire we_next;
wire hazard;
wire wb_int;
wire [15:0] hl, de, bc;
wire [3:0] mem_exec_dec;
 
//wire use_a ;old names for hazard dect. remove
//wire use_b ;
//wire use_c ;
//wire use_d ;
//wire use_e ;
//wire use_h ;
//wire use_l ;
// don't forget that as 1r1 is executed it is transferred to ir2. Anything I need to know
// about subsequent operations must be stored.
// 6 5 4 15
// assign {next_dec_state, next_mem_state, next_pipe_state} = next_state;
wire [5:0] next_dec_state;
wire [4:0] next_mem_state;
wire [3:0] next_pipe_state;
wire ed_dbl_rd;
//-------1---------2---------3--------Registers------------6---------7---------8---------9--------0
 
reg [15:0] pc;
reg [15:0] sp;
reg [15:0] wb_adr_o;
reg wb_we_o;
reg wb_cyc_o;
reg wb_stb_o;
//reg wb_lock; Not used (yet -- don't delete)
reg [1:0] wb_tga_o;
 
reg blk_inc_flg;
reg [9:0] ir1, ir2;
reg ir1dd, ir2dd;
reg ir1fd, ir2fd;
reg [15:0] nn;
 
reg [14:0] next_state; // a wire assigned in an alowys loop.
 
reg [5:0] dec_state; // the register set each clock from next_dec_state;
 
//reg of16_reg, os16_reg, rmw8_reg, call_reg, ret_reg, ioi;
//reg push_reg;
//reg pop_reg;
reg inst_haz;
reg exec_ir2;
reg blk_rpt_flg;
reg blk_io_flg;
reg flag_os1;
reg int_en, en_int_next;
reg wb_irq_sync;
//-------1---------2---------3--------Assignments----------6---------7---------8---------9--------0
//
// ir is 10 bits most significant codes ir1[9:8] = { EDgrp, CBgrp } DDgrp and FDgrp are modifiers
 
 
assign wb_dat_o = nn[15:8];
 
wire sf, zf, f5f, hf, f3f, pvf, nf, cf;
assign { sf, zf, f5f, hf, f3f, pvf, nf, cf} = fr; // no load on f5f, f3f ok hf nf used in inst_exec.v
 
 
assign hl = {hr, lr};
assign de = {dr, er};
assign bc = {br, cr};
 
 
// this "groups" the instructions to determine first memory operation
 
parameter I1DCNT = 4; // parameter used below simply to make possible change easier.
assign mem_exec_dec =
{I1DCNT {CBgrp == ir1}} & I1_CB |// CBgrp is rotates and bi
{I1DCNT {DDgrp == ir1}} & I1_DDFD|// DDgrp
{I1DCNT {FDgrp == ir1}} & I1_DDFD|// FDgrp FD
{I1DCNT {EDgrp == ir1}} & I1_ED |// EDgrp ED
{I1DCNT {JPsHL == ir1}} & I1_JMP |// JP HL ; E9 // doc
{I1DCNT {ADCsA_N == ir1}} & I1_N |// ADC A,N ; CE XX
{I1DCNT {ADDsA_N == ir1}} & I1_N |// ADD A,N ; C6 XX
{I1DCNT {ANDsN == ir1}} & I1_N |// AND N ; E6 XX
{I1DCNT {CPsN == ir1}} & I1_N |// CP N ; FE XX
{I1DCNT {INsA_6N7 == ir1}} & I1_N |// IN A,(N) ; DB XX
{I1DCNT {JRs$t2 == ir1}} & I1_N |// JR $+2 ; 18 XX
{I1DCNT {JRsC_$t2 == ir1}} & I1_N |// JR C,$+2 ; 38 XX
{I1DCNT {JRsNC_$t2 == ir1}} & I1_N |// JR NC,$+2 ; 30 XX
{I1DCNT {JRsZ_$t2 == ir1}} & I1_N |// JR Z,$+2 ; 28 XX
{I1DCNT {JRsNZ_$t2 == ir1}} & I1_N |// JR NZ,$+2 ; 20 XX
{I1DCNT {LDs6HL7_N == ir1}} & I1_N |// LD (HL),N ; 36 XX
{I1DCNT {LDsA_N == ir1}} & I1_N |// LD A,N ; 3E XX
{I1DCNT {LDsB_N == ir1}} & I1_N |// LD B,N ; 06 XX
{I1DCNT {LDsC_N == ir1}} & I1_N |// LD C,N ; 0E XX
{I1DCNT {LDsD_N == ir1}} & I1_N |// LD D,N ; 16 XX
{I1DCNT {LDsE_N == ir1}} & I1_N |// LD E,N ; 1E XX
{I1DCNT {LDsH_N == ir1}} & I1_N |// LD H,N ; 26 XX
{I1DCNT {LDsL_N == ir1}} & I1_N |// LD L,N ; 2E XX
{I1DCNT {ORsN == ir1}} & I1_N |// OR N ; F6 XX
{I1DCNT {OUTs6N7_A == ir1}} & I1_N |// OUT (N),A ; D3 XX
{I1DCNT {SBCsA_N == ir1}} & I1_N |// SBC A,N ; DE XX
{I1DCNT {SUBsN == ir1}} & I1_N |// SUB N ; D6 XX
{I1DCNT {XORsN == ir1}} & I1_N |// XOR N ; EE XX
{I1DCNT {CALLsC_NN == ir1}} & I1_NN |// CALL C,NN ; DC XX XX
{I1DCNT {CALLsNC_NN == ir1}} & I1_NN |// CALL NC,NN ; D4 XX XX
{I1DCNT {CALLsNN == ir1}} & I1_NN |// CALL NN ; CD XX XX
{I1DCNT {CALLsNZ_NN == ir1}} & I1_NN |// CALL NZ,NN ; C4 XX XX
{I1DCNT {CALLsPE_NN == ir1}} & I1_NN |// CALL PE,NN ; EC XX XX
{I1DCNT {CALLsPO_NN == ir1}} & I1_NN |// CALL PO,NN ; E4 XX XX
{I1DCNT {CALLsP_NN == ir1}} & I1_NN |// CALL P,NN ; F4 XX XX
{I1DCNT {CALLsZ_NN == ir1}} & I1_NN |// CALL Z,NN ; CC XX XX
{I1DCNT {CALLsM_NN == ir1}} & I1_NN |// CALL M,NN ; FC XX XX
{I1DCNT {JP == ir1}} & I1_NN |// JP ; C3 XX XX
{I1DCNT {JPsC == ir1}} & I1_NN |// JP C ; DA XX XX
{I1DCNT {JPsM == ir1}} & I1_NN |// JP M, ; FA XX XX
{I1DCNT {JPsNC == ir1}} & I1_NN |// JP NC, ; D2 XX XX
{I1DCNT {JPsNZ == ir1}} & I1_NN |// JP NZ ; C2 XX XX
{I1DCNT {JPsP == ir1}} & I1_NN |// JP P ; F2 XX XX
{I1DCNT {JPsPE == ir1}} & I1_NN |// JP PE, ; EA XX XX
{I1DCNT {JPsPO == ir1}} & I1_NN |// JP PO ; E2 XX XX
{I1DCNT {JPsZ == ir1}} & I1_NN |// JP Z ; CA XX XX
{I1DCNT {LDs6NN7_A == ir1}} & I1_NN |// LD (NN),A ; 32 XX XX
{I1DCNT {LDs6NN7_HL == ir1}} & I1_NN |// LD (NN),HL ; 22 XX XX
{I1DCNT {LDsA_6NN7 == ir1}} & I1_NN |// LD A,(NN) ; 3A XX XX
{I1DCNT {LDsBC_NN == ir1}} & I1_NN |// LD BC,NN ; 01 XX XX
{I1DCNT {LDsDE_NN == ir1}} & I1_NN |// LD DE,NN ; 11 XX XX
{I1DCNT {LDsHL_6NN7 == ir1}} & I1_NN |// LD HL,(NN) ; 2A XX XX
{I1DCNT {LDsHL_NN == ir1}} & I1_NN |// LD HL,NN ; 21 XX XX
{I1DCNT {LDsSP_NN == ir1}} & I1_NN |// LD SP,NN ; 31 XX XX
{I1DCNT {ADCsA_6HL7 == ir1}} & I1_OF |// ADC A,(HL) ; 8E
{I1DCNT {ADDsA_6HL7 == ir1}} & I1_OF |// ADD A,(HL) ; 86
{I1DCNT {ANDs6HL7 == ir1}} & I1_OF |// AND (HL) ; A6
{I1DCNT {CPs6HL7 == ir1}} & I1_OF |// CP (HL) ; BE
{I1DCNT {LDsA_6BC7 == ir1}} & I1_OF |// LD A,(BC) ; 0A
{I1DCNT {LDsA_6DE7 == ir1}} & I1_OF |// LD A,(DE) ; 1A
{I1DCNT {LDsA_6HL7 == ir1}} & I1_OF |// LD A,(HL) ; 7E
{I1DCNT {LDsB_6HL7 == ir1}} & I1_OF |// LD B,(HL) ; 46
{I1DCNT {LDsC_6HL7 == ir1}} & I1_OF |// LD C,(HL) ; 4E
{I1DCNT {LDsD_6HL7 == ir1}} & I1_OF |// LD D,(HL) ; 56
{I1DCNT {LDsE_6HL7 == ir1}} & I1_OF |// LD E,(HL) ; 5E
{I1DCNT {LDsH_6HL7 == ir1}} & I1_OF |// LD H,(HL) ; 66
{I1DCNT {LDsL_6HL7 == ir1}} & I1_OF |// LD L,(HL) ; 6E
{I1DCNT {ORs6HL7 == ir1}} & I1_OF |// OR (HL) ; B6
{I1DCNT {SBCs6HL7 == ir1}} & I1_OF |// SBC (HL) ; 9E
{I1DCNT {SUBs6HL7 == ir1}} & I1_OF |// SUB (HL) ; 96
{I1DCNT {XORs6HL7 == ir1}} & I1_OF |// XOR (HL) ; AE
{I1DCNT {LDs6BC7_A == ir1}} & I1_OS |// LD (BC),A ; 02
{I1DCNT {LDs6DE7_A == ir1}} & I1_OS |// LD (DE),A ; 12
{I1DCNT {LDs6HL7_A == ir1}} & I1_OS |// LD (HL),A ; 77
{I1DCNT {LDs6HL7_B == ir1}} & I1_OS |// LD (HL),B ; 70
{I1DCNT {LDs6HL7_C == ir1}} & I1_OS |// LD (HL),C ; 71
{I1DCNT {LDs6HL7_D == ir1}} & I1_OS |// LD (HL),D ; 72
{I1DCNT {LDs6HL7_E == ir1}} & I1_OS |// LD (HL),E ; 73
{I1DCNT {LDs6HL7_H == ir1}} & I1_OS |// LD (HL),H ; 74
{I1DCNT {LDs6HL7_L == ir1}} & I1_OS |// LD (HL),L ; 75
{I1DCNT {POPsAF == ir1}} & I1_POP |// POP AF ; F1
{I1DCNT {POPsBC == ir1}} & I1_POP |// POP BC ; C1
{I1DCNT {POPsDE == ir1}} & I1_POP |// POP DE ; D1
{I1DCNT {POPsHL == ir1}} & I1_POP |// POP HL ; E1
{I1DCNT {PUSHsAF == ir1}} & I1_PUSH|// PUSH AF ; F5
{I1DCNT {PUSHsBC == ir1}} & I1_PUSH|// PUSH BC ; C5
{I1DCNT {PUSHsDE == ir1}} & I1_PUSH|// PUSH DE ; D5
{I1DCNT {PUSHsHL == ir1}} & I1_PUSH|// PUSH HL ; E5
{I1DCNT {ADCsA_A == ir1}} & I1_R2R |// ADC A,A ; 8F
{I1DCNT {ADCsA_B == ir1}} & I1_R2R |// ADC A,B ; 88
{I1DCNT {ADCsA_C == ir1}} & I1_R2R |// ADC A,C ; 89
{I1DCNT {ADCsA_D == ir1}} & I1_R2R |// ADC A,D ; 8A
{I1DCNT {ADCsA_E == ir1}} & I1_R2R |// ADC A,E ; 8B
{I1DCNT {ADCsA_H == ir1}} & I1_R2R |// ADC A,H ; 8C
{I1DCNT {ADCsA_L == ir1}} & I1_R2R |// ADC A,L ; 8D
{I1DCNT {ADDsA_A == ir1}} & I1_R2R |// ADD A,A ; 87
{I1DCNT {ADDsA_B == ir1}} & I1_R2R |// ADD A,B ; 80
{I1DCNT {ADDsA_C == ir1}} & I1_R2R |// ADD A,C ; 81
{I1DCNT {ADDsA_D == ir1}} & I1_R2R |// ADD A,D ; 82
{I1DCNT {ADDsA_E == ir1}} & I1_R2R |// ADD A,E ; 83
{I1DCNT {ADDsA_H == ir1}} & I1_R2R |// ADD A,H ; 84
{I1DCNT {ADDsA_L == ir1}} & I1_R2R |// ADD A,L ; 85
{I1DCNT {ADDsHL_BC == ir1}} & I1_R2R |// ADD HL,BC ; 09
{I1DCNT {ADDsHL_DE == ir1}} & I1_R2R |// ADD HL,DE ; 19
{I1DCNT {ADDsHL_HL == ir1}} & I1_R2R |// ADD HL,HL ; 29
{I1DCNT {ADDsHL_SP == ir1}} & I1_R2R |// ADD HL,SP ; 39
{I1DCNT {ANDsA == ir1}} & I1_R2R |// AND A ; A7
{I1DCNT {ANDsB == ir1}} & I1_R2R |// AND B ; A0
{I1DCNT {ANDsC == ir1}} & I1_R2R |// AND C ; A1
{I1DCNT {ANDsD == ir1}} & I1_R2R |// AND D ; A2
{I1DCNT {ANDsE == ir1}} & I1_R2R |// AND E ; A3
{I1DCNT {ANDsH == ir1}} & I1_R2R |// AND H ; A4
{I1DCNT {ANDsL == ir1}} & I1_R2R |// AND L ; A5
{I1DCNT {CCF == ir1}} & I1_R2R |// CCF ; 3F
{I1DCNT {CPL == ir1}} & I1_R2R |// CPL ; 2F
{I1DCNT {CPsA == ir1}} & I1_R2R |// CP A ; BF
{I1DCNT {CPsB == ir1}} & I1_R2R |// CP B ; B8
{I1DCNT {CPsC == ir1}} & I1_R2R |// CP C ; B9
{I1DCNT {CPsD == ir1}} & I1_R2R |// CP D ; BA
{I1DCNT {CPsE == ir1}} & I1_R2R |// CP E ; BB
{I1DCNT {CPsH == ir1}} & I1_R2R |// CP H ; BC
{I1DCNT {CPsL == ir1}} & I1_R2R |// CP L ; BD
{I1DCNT {DAA == ir1}} & I1_R2R |// DAA ; 27
{I1DCNT {DECsA == ir1}} & I1_R2R |// DEC A ; 3D
{I1DCNT {DECsB == ir1}} & I1_R2R |// DEC B ; 05
{I1DCNT {DECsBC == ir1}} & I1_R2R |// DEC BC ; 0B
{I1DCNT {DECsC == ir1}} & I1_R2R |// DEC C ; 0D
{I1DCNT {DECsD == ir1}} & I1_R2R |// DEC D ; 15
{I1DCNT {DECsDE == ir1}} & I1_R2R |// DEC DE ; 1B
{I1DCNT {DECsE == ir1}} & I1_R2R |// DEC E ; 1D
{I1DCNT {DECsH == ir1}} & I1_R2R |// DEC H ; 25
{I1DCNT {DECsHL == ir1}} & I1_R2R |// DEC HL ; 2B
{I1DCNT {DECsL == ir1}} & I1_R2R |// DEC L ; 2D
{I1DCNT {DECsSP == ir1}} & I1_R2R |// DEC SP ; 3B
{I1DCNT {DI == ir1}} & I1_R2R |// DI ; F3
{I1DCNT {DJNZs$t2 == ir1}} & I1_R2R |// DJNZ $+2 ; 10 XX
{I1DCNT {EI == ir1}} & I1_R2R |// EI ; FB
{I1DCNT {EXX == ir1}} & I1_R2R |// EXX ; D9
{I1DCNT {EXsAF_AFp == ir1}} & I1_R2R |// EX AF,AF' ; 08
{I1DCNT {EXsDE_HL == ir1}} & I1_R2R |// EX DE,HL ; EB
{I1DCNT {HALT == ir1}} & I1_R2R |// HALT ; 76
{I1DCNT {INCsA == ir1}} & I1_R2R |// INC A ; 3C
{I1DCNT {INCsB == ir1}} & I1_R2R |// INC B ; 04
{I1DCNT {INCsBC == ir1}} & I1_R2R |// INC BC ; 03
{I1DCNT {INCsC == ir1}} & I1_R2R |// INC C ; 0C
{I1DCNT {INCsD == ir1}} & I1_R2R |// INC D ; 14
{I1DCNT {INCsDE == ir1}} & I1_R2R |// INC DE ; 13
{I1DCNT {INCsE == ir1}} & I1_R2R |// INC E ; 1C
{I1DCNT {INCsH == ir1}} & I1_R2R |// INC H ; 24
{I1DCNT {INCsHL == ir1}} & I1_R2R |// INC HL ; 23
{I1DCNT {INCsL == ir1}} & I1_R2R |// INC L ; 2C
{I1DCNT {INCsSP == ir1}} & I1_R2R |// INC SP ; 33
{I1DCNT {LDsA_A == ir1}} & I1_R2R |// LD A,A ; 7F
{I1DCNT {LDsA_B == ir1}} & I1_R2R |// LD A,B ; 78
{I1DCNT {LDsA_C == ir1}} & I1_R2R |// LD A,C ; 79
{I1DCNT {LDsA_D == ir1}} & I1_R2R |// LD A,D ; 7A
{I1DCNT {LDsA_E == ir1}} & I1_R2R |// LD A,E ; 7B
{I1DCNT {LDsA_H == ir1}} & I1_R2R |// LD A,H ; 7C
{I1DCNT {LDsA_L == ir1}} & I1_R2R |// LD A,L ; 7D
{I1DCNT {LDsB_A == ir1}} & I1_R2R |// LD B,A ; 47
{I1DCNT {LDsB_B == ir1}} & I1_R2R |// LD B,B ; 40
{I1DCNT {LDsB_C == ir1}} & I1_R2R |// LD B,C ; 41
{I1DCNT {LDsB_D == ir1}} & I1_R2R |// LD B,D ; 42
{I1DCNT {LDsB_E == ir1}} & I1_R2R |// LD B,E ; 43
{I1DCNT {LDsB_H == ir1}} & I1_R2R |// LD B,H ; 44
{I1DCNT {LDsB_L == ir1}} & I1_R2R |// LD B,L ; 45
{I1DCNT {LDsC_A == ir1}} & I1_R2R |// LD C,A ; 4F
{I1DCNT {LDsC_B == ir1}} & I1_R2R |// LD C,B ; 48
{I1DCNT {LDsC_C == ir1}} & I1_R2R |// LD C,C ; 49
{I1DCNT {LDsC_D == ir1}} & I1_R2R |// LD C,D ; 4A
{I1DCNT {LDsC_E == ir1}} & I1_R2R |// LD C,E ; 4B
{I1DCNT {LDsC_H == ir1}} & I1_R2R |// LD C,H ; 4C
{I1DCNT {LDsC_L == ir1}} & I1_R2R |// LD C,L ; 4D
{I1DCNT {LDsD_A == ir1}} & I1_R2R |// LD D,A ; 57
{I1DCNT {LDsD_B == ir1}} & I1_R2R |// LD D,B ; 50
{I1DCNT {LDsD_C == ir1}} & I1_R2R |// LD D,C ; 51
{I1DCNT {LDsD_D == ir1}} & I1_R2R |// LD D,D ; 52
{I1DCNT {LDsD_E == ir1}} & I1_R2R |// LD D,E ; 53
{I1DCNT {LDsD_H == ir1}} & I1_R2R |// LD D,H ; 54
{I1DCNT {LDsD_L == ir1}} & I1_R2R |// LD D,L ; 55
{I1DCNT {LDsE_A == ir1}} & I1_R2R |// LD E,A ; 5F
{I1DCNT {LDsE_B == ir1}} & I1_R2R |// LD E,B ; 58
{I1DCNT {LDsE_C == ir1}} & I1_R2R |// LD E,C ; 59
{I1DCNT {LDsE_D == ir1}} & I1_R2R |// LD E,D ; 5A
{I1DCNT {LDsE_E == ir1}} & I1_R2R |// LD E,E ; 5B
{I1DCNT {LDsE_H == ir1}} & I1_R2R |// LD E,H ; 5C
{I1DCNT {LDsE_L == ir1}} & I1_R2R |// LD E,L ; 5D
{I1DCNT {LDsH_A == ir1}} & I1_R2R |// LD H,A ; 67
{I1DCNT {LDsH_B == ir1}} & I1_R2R |// LD H,B ; 60
{I1DCNT {LDsH_C == ir1}} & I1_R2R |// LD H,C ; 61
{I1DCNT {LDsH_D == ir1}} & I1_R2R |// LD H,D ; 62
{I1DCNT {LDsH_E == ir1}} & I1_R2R |// LD H,E ; 63
{I1DCNT {LDsH_H == ir1}} & I1_R2R |// LD H,H ; 64
{I1DCNT {LDsH_L == ir1}} & I1_R2R |// LD H,L ; 65
{I1DCNT {LDsL_A == ir1}} & I1_R2R |// LD L,A ; 6F
{I1DCNT {LDsL_B == ir1}} & I1_R2R |// LD L,B ; 68
{I1DCNT {LDsL_C == ir1}} & I1_R2R |// LD L,C ; 69
{I1DCNT {LDsL_D == ir1}} & I1_R2R |// LD L,D ; 6A
{I1DCNT {LDsL_E == ir1}} & I1_R2R |// LD L,E ; 6B
{I1DCNT {LDsL_H == ir1}} & I1_R2R |// LD L,H ; 6C
{I1DCNT {LDsL_L == ir1}} & I1_R2R |// LD L,L ; 6D
{I1DCNT {LDsSP_HL == ir1}} & I1_R2R |// LD SP,HL ; F9
{I1DCNT {NOP == ir1}} & I1_R2R |// NOP ; 00
{I1DCNT {ORsA == ir1}} & I1_R2R |// OR A ; B7
{I1DCNT {ORsB == ir1}} & I1_R2R |// OR B ; B0
{I1DCNT {ORsC == ir1}} & I1_R2R |// OR C ; B1
{I1DCNT {ORsD == ir1}} & I1_R2R |// OR D ; B2
{I1DCNT {ORsE == ir1}} & I1_R2R |// OR E ; B3
{I1DCNT {ORsH == ir1}} & I1_R2R |// OR H ; B4
{I1DCNT {ORsL == ir1}} & I1_R2R |// OR L ; B5
{I1DCNT {RLA == ir1}} & I1_R2R |// RLA ; 17
{I1DCNT {RLCA == ir1}} & I1_R2R |// RLCA ; 07
{I1DCNT {RRA == ir1}} & I1_R2R |// RRA ; 1F
{I1DCNT {RRCA == ir1}} & I1_R2R |// RRCA ; 0F
{I1DCNT {SBCsA == ir1}} & I1_R2R |// SBC A ; 9F
{I1DCNT {SBCsB == ir1}} & I1_R2R |// SBC B ; 98
{I1DCNT {SBCsC == ir1}} & I1_R2R |// SBC C ; 99
{I1DCNT {SBCsD == ir1}} & I1_R2R |// SBC D ; 9A
{I1DCNT {SBCsE == ir1}} & I1_R2R |// SBC E ; 9B
{I1DCNT {SBCsH == ir1}} & I1_R2R |// SBC H ; 9C
{I1DCNT {SBCsL == ir1}} & I1_R2R |// SBC L ; 9D
{I1DCNT {SCF == ir1}} & I1_R2R |// SCF ; 37
{I1DCNT {SUBsA == ir1}} & I1_R2R |// SUB A ; 97
{I1DCNT {SUBsB == ir1}} & I1_R2R |// SUB B ; 90
{I1DCNT {SUBsC == ir1}} & I1_R2R |// SUB C ; 91
{I1DCNT {SUBsD == ir1}} & I1_R2R |// SUB D ; 92
{I1DCNT {SUBsE == ir1}} & I1_R2R |// SUB E ; 93
{I1DCNT {SUBsH == ir1}} & I1_R2R |// SUB H ; 94
{I1DCNT {SUBsL == ir1}} & I1_R2R |// SUB L ; 95
{I1DCNT {XORsA == ir1}} & I1_R2R |// XOR A ; AF
{I1DCNT {XORsB == ir1}} & I1_R2R |// XOR B ; A8
{I1DCNT {XORsC == ir1}} & I1_R2R |// XOR C ; A9
{I1DCNT {XORsD == ir1}} & I1_R2R |// XOR D ; AA
{I1DCNT {XORsE == ir1}} & I1_R2R |// XOR E ; AB
{I1DCNT {XORsH == ir1}} & I1_R2R |// XOR H ; AC
{I1DCNT {XORsL == ir1}} & I1_R2R |// XOR L ; AD
{I1DCNT {RET == ir1}} & I1_RET |// RET ; C9
{I1DCNT {RETsC == ir1 & cf }} & I1_RET |// RET C ; D8
{I1DCNT {RETsM == ir1 & sf }} & I1_RET |// RET M ; F8
{I1DCNT {RETsNC== ir1 & ~cf }} & I1_RET |// RET NC ; D0
{I1DCNT {RETsP == ir1 & ~sf }} & I1_RET |// RET P ; F0
{I1DCNT {RETsPE== ir1 & pvf }} & I1_RET |// RET PE ; E8
{I1DCNT {RETsPO== ir1 & ~pvf}} & I1_RET |// RET PO ; E0
{I1DCNT {RETsNZ== ir1 & ~zf }} & I1_RET |// RET NZ ; C0
{I1DCNT {RETsZ == ir1 & zf }} & I1_RET |// RET Z ; C8
{I1DCNT {EXs6SP7_HL == ir1}} & I1_RMW |// EX (SP),HL ; E3
{I1DCNT {DECs6HL7 == ir1}} & I1_RMW |// DEC (HL) ; 35
{I1DCNT {INCs6HL7 == ir1}} & I1_RMW |// INC (HL) ; 34
{I1DCNT {RSTs0 == ir1}} & I1_RST |// RST 0 ; C7
{I1DCNT {RSTs10H == ir1}} & I1_RST |// RST 10H ; D7
{I1DCNT {RSTs18H == ir1}} & I1_RST |// RST 18H ; DF
{I1DCNT {RSTs20H == ir1}} & I1_RST |// RST 20H ; E7
{I1DCNT {RSTs28H == ir1}} & I1_RST |// RST 28H ; EF
{I1DCNT {RSTs30H == ir1}} & I1_RST |// RST 30H ; F7
{I1DCNT {RSTs38H == ir1}} & I1_RST |// RST 38H ; FF
{I1DCNT {RSTs8H == ir1}} & I1_RST ;// RST 8H ; CF
//-------- CB decodes -----------------------
 
// First cut below
// CB_RLC = 7'b01_00_000, // these must be compaired with ir[9:3]
// CB_RRC = 7'b01_00_001, // these must be compaired with ir[9:3]
// CB_RL = 7'b01_00_010, // these must be compaired with ir[9:3]
// CB_RR = 7'b01_00_011, // these must be compaired with ir[9:3]
// CB_SLA = 7'b01_00_100, // these must be compaired with ir[9:3]
// CB_SRA = 7'b01_00_101, // these must be compaired with ir[9:3]
// CB_SLL = 7'b01_00_110, // these must be compaired with ir[9:3]
// CB_SRL = 7'b01_00_111, // these must be compaired with ir[9:3]
// CB_BIT = 4'b01_01, // these must be compaired with ir[9:6]
// CB_RES = 4'b01_10, // these must be compaired with ir[9:6]
// CB_SET = 4'b01_11, // these must be compaired with ir[9:6]
 
// note these are all read-modify-writ except CB_BIT
assign cb_mem = (CB_MEM == ir1[2:0]); // this must be compaired with ir[2:0]
 
// The ED Group
// These are the "unique instructions in the 46, 47 rows that NEED? to be implemented
// Not sure I want to worry about all undocumented stuff in these rows - hard to believe
// It will matter.(IM modes are very system dependent - hard to believe even a programmer
// would use undocumented instructions to muck with this stuff)
// reg 2 reg simply executed by ir2 logic
// ED_IMs0 = 10'h246// IM 0 ; ED 46 set IM0
// ED_LDsI_A = 10'h247// LD I,A ; ED 47 move a to I
// ED_IMs1 = 10'h256// IM 1 ; ED 56 set IM1
// ED_LDsA_I = 10'h257// LD A,I ; ED 57 move I to A
// ED_IMs2 = 10'h25E// IM 2 ; ED 5E set IM2
// ED_RRD = 10'h267// RRD ; ED 67 nibble roates A HL
// ED_RLD = 10'h26F// RLD ; ED 6F nibble roates A HL
// set (or clear) repeat flag at DEC_EB.
// set (or clear) inc flag at DEC_EB.
// seperate flows for LD, CP, IN, OUT.
// ED_LDI == ir1// LDI ; ED A0 These are block move
// ED_CPI == ir1// CPI ; ED A1 type insts that don't repeat
// ED_INI == ir1// INI ; ED A2
// ED_OUTI == ir1// OUTI ; ED A3
// ED_LDD == ir1// LDD ; ED A8
// ED_CPD == ir1// CPD ; ED A9
// ED_IND == ir1// IND ; ED AA
// ED_OUTD == ir1// OUTD ; ED AB
wire dec_blk_rpt =
ED_LDIR == ir1 |// LDIR ; ED B0 These are block move
ED_CPIR == ir1 |// CPIR ; ED B1 type insts that DO repeat
ED_INIR == ir1 |// INIR ; ED B2
ED_OTIR == ir1 |// OTIR ; ED B3
ED_LDDR == ir1 |// LDDR ; ED B8
ED_CPDR == ir1 |// CPDR ; ED B9
ED_INDR == ir1 |// INDR ; ED BA
ED_OTDR == ir1 ;// OTDR ; ED BB
wire ed_blk_mv = ED_LDIR == ir1 | ED_LDI == ir1 |
ED_LDDR == ir1 | ED_LDD == ir1 ;
wire ed_blk_cp = ED_CPIR == ir1 | ED_CPI == ir1 |
ED_CPDR == ir1 | ED_CPD == ir1 ;
wire ed_blk_in = ED_INIR == ir1 | ED_INI == ir1 |
ED_INDR == ir1 | ED_IND == ir1 ;
 
wire ed_blk_out = ED_OTIR == ir1 | ED_OUTI == ir1 |
ED_OTDR == ir1 | ED_OUTD == ir1 ;
 
wire dec_blk_io = ed_blk_in | ed_blk_in;
 
wire blk_done = ~blk_rpt_flg | beq0 & ceq0 | blk_io_flg & ceq0;
 
assign dec_blk_inc = ED_LDIR == ir1 |
ED_CPIR == ir1 |
ED_INIR == ir1 |
ED_OTIR == ir1 |
ED_LDI == ir1 |
ED_CPI == ir1 |
ED_INI == ir1 |
ED_OUTI == ir1 ;
 
 
//The ED70 instruction reads from I/O port C,
//but does not store the result.
//It just affects the flags. Hard to test. like the other IN x,(C) instruction.
//
//ED71 simply outs the value 0 to I/O port C.
// This suggests that we should decode as follows:
// I hope if I don't get all the IM duplicates right it won't be a tragedy
// ED_INsREG_6C7 = 7'b1001___000,// compair with {ir[7:6],ir[2:0]}
//
// ED_SBCsHL_REG = 8'b1001__0010, // compair with {ir[9:6],ir[3:0]}
// ED_ADCsHL_REG = 8'b1001__1010, // compair with {ir[9:6],ir[3:0]}
// ED_LDs6NN7_REG = 8'b1001__0011, // compair with {ir[9:6],ir[3:0]} REG = BC,DE,HL,SP
// ED_LDsREG_6NN7 = 8'b1001__1011, // compair with {ir[9:6],ir[3:0]} REG = BC,DE,HL,SP
// ED_NEG = 7'b1001___100, // compair with {ir[9:6],ir[2:0]} all A<= -A
// ED_RETN = 7'b1001___101, // compair with {ir[9:6],ir[2:0]} and !reti
wire ed_nn = ED_LDs6NN7_REG == {ir1[9:6],ir1[3:0]} |
ED_LDsREG_6NN7 == {ir1[9:6],ir1[3:0]} ;
 
// we use all these to enable interrupts
wire ed_retn = ED_RETN == {ir1[9:6],ir1[2:0]};
 
assign ed_dbl_rd = ED_LDsREG_6NN7 == {ir1[9:6],ir1[3:0]};
 
// assign cb_mem = CB_MEM = ir1[2:0]; // CB_MEM = 3'h110,
 
 
 
wire jmpr_true =
JRs$t2 == ir1 |
JRsC_$t2 == ir1 & fr[0] |
JRsNC_$t2 == ir1 & ~fr[0] |
JRsZ_$t2 == ir1 & fr[6] |
JRsNZ_$t2 == ir1 & ~fr[6] ;
//assign { sf, zf. f5f, hf, f3f, pvf, nf, cf} = fr;
wire callnn_true = CALLsC_NN == ir1 & cf |
CALLsNC_NN == ir1 & ~cf |
CALLsNN == ir1 |
CALLsNZ_NN == ir1 & ~zf |
CALLsPE_NN == ir1 & pvf |
CALLsPO_NN == ir1 & ~pvf|
CALLsP_NN == ir1 & ~sf |
CALLsZ_NN == ir1 & zf |
CALLsM_NN == ir1 & sf ;
 
wire jmpnn_true = JPsC == ir1 & cf |
JPsNC == ir1 & ~cf |
JP == ir1 |
JPsNZ == ir1 & ~zf |
JPsPE == ir1 & pvf |
JPsPO == ir1 & ~pvf|
JPsP == ir1 & ~sf |
JPsZ == ir1 & zf |
JPsM == ir1 & sf ;
 
// PUSHsAF == ir1
// PUSHsBC == ir1
// PUSHsDE == ir1
// PUSHsHL == ir1
 
wire os_a = LDs6BC7_A == ir1 | // LD (BC),A ; 02
LDs6DE7_A == ir1 | // LD (DE),A ; 12
LDs6HL7_A == ir1 | // LD (HL),A ; 77
LDs6NN7_A == ir1 | // LD (NN),A ; 32 XX XX
PUSHsAF == ir1 |
OUTs6N7_A == ir1 |
(ED_OUTs6C7_REG == {ir1[9:6],ir1[2:0]}) & REG8_A == ir1[5:3] ;
 
wire os_b = LDs6HL7_B == ir1 | // LD (HL),B ; 70
ED_LDs6NN7_REG == {ir1[9:6],ir1[3:0]} & DBL_REG_BC == ir1[5:4] |
ED_OUTs6C7_REG == {ir1[9:6],ir1[2:0]} & REG8_B == ir1[5:3] ;
wire os_c = LDs6HL7_C == ir1 | // LD (HL),C ; 71
PUSHsBC == ir1 | // PUSH BC
ED_OUTs6C7_REG == {ir1[9:6],ir1[2:0]} & REG8_C == ir1[5:3] ;
wire os_d = LDs6HL7_D == ir1 | // LD (HL),D ; 72
ED_LDs6NN7_REG == {ir1[9:6],ir1[3:0]} & DBL_REG_DE == ir1[5:4] |
ED_OUTs6C7_REG == {ir1[9:6],ir1[2:0]} & REG8_D == ir1[5:3] ;
wire os_e = LDs6HL7_E == ir1 | // LD (HL),E ; 73
PUSHsDE == ir1 | // PUSH DE
ED_OUTs6C7_REG == {ir1[9:6],ir1[2:0]} & REG8_E == ir1[5:3] ;
wire os_h = LDs6HL7_H == ir1 | // LD (HL),H ; 74
LDs6NN7_HL == ir1 | // LD (NN),HL ; 22 XX XX
ED_LDs6NN7_REG == {ir1[9:6],ir1[3:0]} & DBL_REG_HL == ir1[5:4] |
ED_OUTs6C7_REG == {ir1[9:6],ir1[2:0]} & REG8_H == ir1[5:3] ;
 
wire os_l = LDs6HL7_L == ir1 | // LD (HL),L ; 75
PUSHsHL == ir1 |
ED_OUTs6C7_REG == {ir1[9:6],ir1[2:0]} & REG8_L == ir1[5:3] ;
 
// wire os_sp = ED_LDs6NN7_REG == {ir1[9:6],ir1[3:0]} & DBL_REG_SP == ir1[5:4]; not used ?
 
wire os_f = PUSHsAF == ir1 ;
 
 
//---------------- inst hazard ----------------------------------------------------------
//
// On some reflection, I don't think I'm going to worry about this immediately - it
// should be easy to kludge in a fix if necessary -- and there are more important things
// todo. It is a very bad programming practice to muck with the instruction stream in any
// case -- I have to believe most target applications do not do this -- although I'll probably
// get hit pretty early with a instruction test that does. Oh well -- if that happens we fix
// it.
// Well -- think some here -- the hazard is because of a change in design.
// If used to any extent.. Somebody WILL
// want this to act the same way as the origional - even if the programming is "poor".
// >>>>>>>> bite the bullet and do it.
//
// if we do an operand store and the address == pc-1 its an inst hazard, We need to execute the
// store decrement pc and re-fetch. This is a high priority interrupt.
// what about multi-byte stores - like LDs6NN7_A or LDs6NN7_HL - i guess we do an IF - to start
// the pipe before the os -- same logic.
//
 
//-----------------data hazard ----------------------------------------------------------
//
// Issues here have evolved to a degree as the design progressed. However the
// Key has always been that for each instruction (no matter how complex) there
// is only a single state in which the previous instruction can also be active
// and that is the DEC_EXEC state. If there is a data hazard, we need to delay
// execution of that state until the ir2 execution completes (which it always does
// in a single tick). Note that only the RET instructions test the flag register
// on DEC_EXEC.
//
// WARNING: be very careful about this. Data hazard logic is very difficult to
// verify as there are so many instruction pairs to test.
//
// Situations 1) operand stores from ir1 when register is updated in ir2
// 2) flag tests when fr is being updated
// 3) sp issues see below LDsSP_HL DECsSP INCsSP
// ANY OTHERS ???
//
// upd_ar, upd_br, upd_cr, upd_dr, upd_er, upd_hr, upd_lr,upd_fr,
wire use_hl_exec = LDsSP_HL == ir1;
wire use_sp_exec = MEM_OFSP == next_mem_state |
MEM_OSSP == next_mem_state ;
wire upd_sp_exec = DECsSP == ir2 |
INCsSP == ir2 ;
 
 
 
wire use_fr_exec = ( RETsC == ir1 |
RETsM == ir1 |
RETsNC == ir1 |
RETsP == ir1 |
RETsPE == ir1 |
RETsPO == ir1 |
RETsNZ == ir1 |
RETsZ == ir1 ) ;
 
assign hazard = (dec_state == DEC_EXEC & exec_ir2 ) & ( upd_fr & use_fr_exec |
upd_ar & os_a |
upd_br & os_b |
upd_cr & os_c |
upd_dr & os_d |
upd_er & os_e |
upd_hr & os_h |
upd_lr & os_l |
upd_hr & use_hl_exec |
upd_lr & use_hl_exec |
upd_sp_exec & use_sp_exec );
 
 
 
 
 
 
// does not include extension stuff as we are mostly looking for hazards here
// course we do use these terms to build more decodes
//
wire opadr_bc = LDsA_6BC7 == ir1 | LDs6BC7_A == ir1;
wire opadr_de = LDsA_6DE7 == ir1 | LDs6DE7_A == ir1;
wire opadr_hl = LDsB_6HL7 == ir1 | ORs6HL7 == ir1 | LDs6HL7_B == ir1 |
LDsD_6HL7 == ir1 | LDsC_6HL7 == ir1 | LDs6HL7_C == ir1 |
LDsH_6HL7 == ir1 | LDsE_6HL7 == ir1 | LDs6HL7_D == ir1 |
ADDsA_6HL7 == ir1 | LDsL_6HL7 == ir1 | LDs6HL7_E == ir1 |
SUBs6HL7 == ir1 | LDsA_6HL7 == ir1 | LDs6HL7_H == ir1 |
ANDs6HL7 == ir1 | ADCsA_6HL7 == ir1 | LDs6HL7_L == ir1 |
XORs6HL7 == ir1 | SBCs6HL7 == ir1 | CPs6HL7 == ir1 ;
//assign use_a = os_a;
//assign use_b = os_b | opadr_bc;
//assign use_c = os_c | opadr_bc;
//assign use_d = os_d | opadr_de;
//assign use_e = os_e | opadr_de;
//assign use_h = os_h | opadr_hl;
//assign use_l = os_l | opadr_hl;
 
 
// old logic not used
//assign use_flags = c_jmp8 | c_jmp4 | c_call | c_ret;
 
 
 
//wire bc_eq0 = beq0 & ceq0;
// ??? not used ? why defined ? I simply re-wrote the test re-name
//assign rpt_blk_mv = (blk_mv_reg ) & !bc_eq0 |
// (blk_cmp_reg) & !bc_eq0 & (nn[7:0] != 8'h0) |
// (blk_in_reg | blk_out_reg) & !b_eq0 ;
 
// BASIC ARCHITECTURE OF THIS FILE pc and sp not shown, but are inputs to src mux.
// _____ and may be updated from adder output.
// | |
// | | pc-1 register is required to implement relative jumps.
// | |
// _____ |lit | |\
// | | | | | \
// | | |src2 | | \ _____ _____
// | | | |----->| | | | | |
// |src | |_____| |adder|------->| | | |
// |mux | | | | | | |
// | |------------------->| / |2/1 |------->|wb |
// | | | | / |mux | |adr |
// |_____| | |/ | | | |
// ------------------->| | | |
// |_____| |_____|
// MEM_NOP
// MEM_IFPP1 MEM_OFIXpD MEM_CALL MEM_IFRST MEM_OFHL_PM MEM_IOF_C
// MEM_OS1, MEM_OSIXpD MEM_OSNN, MEM_IFREL_N MEM_OSHL_PM MEM_IOS_C
// MEM_OF1, MEM_OSADR MEM_OFNN MEM_JMPHL MEM_OSDE_PM MEM_IOF_N
// MEM_OFSP MEM_OSSP_PCM2 MEM_OFADRP1 MEM_IFNN MEM_INTA MEM_IOS_N
// MEM_OSSP MEM_OSSP_P MEM_OSADRP1 MEM_IFINT MEM_OS_HL_N
//
 
wire src_sp = next_mem_state == MEM_OF1 & EXs6SP7_HL == ir1 | //special case rmw
next_mem_state == MEM_OFSP |
next_mem_state == MEM_OSSP |
next_mem_state == MEM_CALL ;
wire src_pc = next_mem_state == MEM_IFPP1 |
next_mem_state == MEM_IFREL_N ;
 
wire src_nn = next_mem_state == MEM_IFNN |
next_mem_state == MEM_OSNN |
next_mem_state == MEM_OFNN ;
 
wire src_de = dec_state == DEC_EXEC & LDsA_6DE7 == ir1 | // MEM_OS1 MEM_OF1
dec_state == DEC_EXEC & LDs6DE7_A == ir1 | // are both true at this time
next_mem_state == MEM_OSDE_PM ;
wire src_bc = dec_state == DEC_EXEC & LDsA_6BC7 == ir1 |
dec_state == DEC_EXEC & LDs6BC7_A == ir1 |
next_mem_state ==MEM_IOF_C |
next_mem_state ==MEM_IOS_C ;
 
 
// don't forget that hl source can be modified by prefix
// this gets messy as we use wb_adr_o for some of these.
//
wire src_hl = next_mem_state == MEM_OF1 &
(dec_state == DEC_EXEC) &
!src_de & !src_bc & !src_sp |
next_mem_state == MEM_OS1 &
(dec_state == DEC_EXEC) &
!src_de & !src_bc |
next_mem_state == MEM_OFHL_PM |
next_mem_state == MEM_OSHL_PM |
next_mem_state == MEM_OS_HL_N |
next_mem_state == MEM_JMPHL ;
wire src_ix = next_mem_state == MEM_OFIXpD & ir1dd |
next_mem_state == MEM_OSIXpD & ir1dd ;
 
wire src_iy = next_mem_state == MEM_OFIXpD & ir1fd |
next_mem_state == MEM_OSIXpD & ir1fd ;
wire src_adr = next_mem_state == MEM_OFADRP1 |
next_mem_state == MEM_OSADRP1 |
next_mem_state == MEM_NOP |
next_mem_state == MEM_OSADR ;
 
wire src_int = next_mem_state == MEM_IOF_N |
next_mem_state == MEM_IOS_N ;
 
wire [15:0] src_mux = {16{ src_sp }} & sp |
{16{ src_pc }} & pc |
{16{ src_nn }} & nn |
{16{ src_hl }} & hl |
{16{ src_de }} & de |
{16{ src_bc }} & bc |
{16{ src_ix }} & ixr |
{16{ src_iy }} & iyr |
{16{ src_adr }} & wb_adr_o |
{16{ src_int }} & { intr, nn[15:8] } |
{16{next_mem_state == MEM_IFRST}} & {10'h0, ir1[6:4], 3'h0} ;
wire block_mv_inc = (dec_state == DEC_ED) ? dec_blk_inc : blk_inc_flg; // flag set at DEC_ED
 
 
 
wire inc = next_mem_state ==MEM_OFADRP1 |
next_mem_state ==MEM_OSADRP1 |
next_mem_state ==MEM_OFHL_PM & block_mv_inc |
next_mem_state ==MEM_OSHL_PM & block_mv_inc |
next_mem_state ==MEM_OSDE_PM & block_mv_inc |
next_mem_state ==MEM_OFSP |
next_mem_state ==MEM_IFPP1 |
next_mem_state ==MEM_OSSP_PCM2 |
next_mem_state ==MEM_OSSP_P ;
 
wire dec = next_mem_state ==MEM_OFHL_PM & ~block_mv_inc |
next_mem_state ==MEM_OSHL_PM & ~block_mv_inc |
next_mem_state ==MEM_OSDE_PM & ~block_mv_inc |
next_mem_state == MEM_OFSP ;
 
wire reln = next_mem_state == MEM_IFREL_N |
next_mem_state == MEM_OFIXpD |
next_mem_state == MEM_OSIXpD ;
 
wire [15:0] src2 = {16{ inc }} & 16'h0001 |
{16{ dec }} & 16'hffff |
{16{ reln }} & {{8{nn[15]}},nn[15:8]}|
{16{~(reln | inc | dec)}} & 16'h0 ;// lint complains that this signal
// has no load -YES it is not needed -
// more for information -- amazing complaint though
 
wire [15:0] adr_alu = src2 + src_mux;
 
wire pre_inc_dec = next_mem_state == MEM_CALL |
next_mem_state == MEM_OSSP_P |
next_mem_state == MEM_OSSP ;
 
 
wire [15:0] mux21 = pre_inc_dec ? adr_alu : src_mux;
 
assign wb_rdy_nhz = (!wb_cyc_o | wb_ack_i ) & ~hazard; // wishbone ready with no hazard
wire wb_rdy = !wb_cyc_o | wb_ack_i;
 
assign we_next = next_mem_state == MEM_OS1 |
next_mem_state == MEM_OSSP |
next_mem_state == MEM_OSIXpD |
next_mem_state == MEM_OSADR |
next_mem_state == MEM_OSSP_PCM2 |
next_mem_state == MEM_OSSP_P |
next_mem_state == MEM_CALL |
next_mem_state == MEM_OSNN |
next_mem_state == MEM_OSADRP1 |
next_mem_state == MEM_OSHL_PM |
next_mem_state == MEM_OSDE_PM |
next_mem_state == MEM_OS_HL_N |
next_mem_state == MEM_IOS_C |
next_mem_state == MEM_IOS_N ;
 
 
//-------1---------2---------3--------State Machines-------6---------7---------8---------9--------0
// we do this just to save virtual paper below.
// 6 5 4 15
assign {next_dec_state, next_mem_state, next_pipe_state} = next_state;
 
always @(ir1 or wb_int or inst_haz or dec_state or mem_exec_dec or cb_mem or ed_nn or
ed_blk_cp or ed_blk_in or ed_blk_out or ed_retn or ed_blk_mv or ed_dbl_rd or blk_done or
fr or jmpr_true or callnn_true or jmpnn_true )
begin
case (dec_state)
DEC_IDLE: next_state = {DEC_IF1, MEM_NOP, IPIPE_NOP};
DEC_HALT:
if (wb_int) next_state = {DEC_INT1,MEM_NOP ,IPIPE_NOP};// stay here until interrupt or reset
else next_state = {DEC_HALT,MEM_NOP ,IPIPE_NOP};
DEC_IF1 : next_state = {DEC_IF2 ,MEM_IFPP1 ,IPIPE_NOP};
DEC_IF2 : next_state = {DEC_EXEC,MEM_IFPP1 ,IPIPE_EN1};
DEC_IF2A: next_state = {DEC_EXEC,MEM_IFPP1 ,IPIPE_NOP};
DEC_EXEC:
if (inst_haz) next_state = {DEC_IF1, MEM_DECPC , IPIPE_NOP};
else if (wb_int) next_state = {DEC_INT1,MEM_NOP ,IPIPE_NOP};
else
case (mem_exec_dec) // full case but can all tools understand ? just make a default
I1_CB : next_state = {DEC_CB, MEM_IFPP1, IPIPE_EN1};// IF2_NOP -> nn <= (MEM)
I1_DDFD : next_state = {DEC_DDFD, MEM_IFPP1, IPIPE_EN1};// gets real inst
I1_ED : next_state = {DEC_ED, MEM_IFPP1, IPIPE_EN1};
I1_JMP : next_state = {DEC_IF2, MEM_JMPHL, IPIPE_NOP};
I1_N : next_state = {DEC_N, MEM_IFPP1, IPIPE_ENN};
I1_NN : next_state = {DEC_NN, MEM_IFPP1, IPIPE_ENN};
I1_OF : next_state = {DEC_OF, MEM_OF1, IPIPE_EN12};//transfer, don't activate
I1_OS : next_state = {DEC_IF2, MEM_OS1, IPIPE_EN1}; // -> ir2_NOP
I1_POP : next_state = {DEC_POP, MEM_OFSP, IPIPE_EN12};
I1_PUSH : next_state = {DEC_PUSH, MEM_OSSP, IPIPE_EN12};
I1_RET : next_state = {DEC_RET, MEM_OFSP, IPIPE_EN12};
I1_RMW : next_state = {DEC_RMW, MEM_OF1, IPIPE_EN12};//can't activate till data rdy
I1_RST : next_state = {DEC_IF2, MEM_IFRST, IPIPE_ENN};
I1_R2R : next_state = {DEC_EXEC, MEM_IFPP1, IPIPE_EN12A2};
default : next_state = {DEC_EXEC, MEM_IFPP1, IPIPE_EN12A2}; //I1_R2R
endcase
DEC_CB: if (cb_mem) next_state = {DEC_CBM, MEM_OF1, IPIPE_EN12};
else next_state = {DEC_EXEC, MEM_IFPP1, IPIPE_EN12A2};
DEC_DDFD: // except for CB and EB these all act the same H and L get modified by prefix
case (mem_exec_dec)
I1_CB : next_state = {DEC_PFxCB,MEM_IFPP1, IPIPE_EN1};// IF2_NOP -> nn <= (MEM)
I1_DDFD : next_state = {DEC_DDFD, MEM_IFPP1, IPIPE_EN1};
I1_ED : next_state = {DEC_ED, MEM_IFPP1, IPIPE_EN1};//How do we clear the prefix?
I1_JMP : next_state = {DEC_IF2, MEM_JMPHL, IPIPE_NOP};
I1_N : next_state = {DEC_N, MEM_IFPP1, IPIPE_ENN};
I1_NN : next_state = {DEC_NN, MEM_IFPP1, IPIPE_ENN};
I1_OF : next_state = {DEC_DDOF, MEM_IFPP1, IPIPE_ENN}; // d to nn - need to get d
// LD A,(BC) LD A,(DE) will
// become ix+d - do we care ?
// i hope not
I1_OS : next_state = {DEC_DDOS, MEM_IFPP1, IPIPE_ENN}; // d to nn
I1_POP : next_state = {DEC_POP, MEM_OFSP, IPIPE_EN12};
I1_PUSH : next_state = {DEC_PUSH, MEM_OSSP, IPIPE_EN12};
I1_RET : next_state = {DEC_RET, MEM_OFSP, IPIPE_EN12};
I1_RMW : next_state = {DEC_RMW, MEM_OF1, IPIPE_EN12};
I1_RST : next_state = {DEC_IF2, MEM_IFRST, IPIPE_NOP}; // just dump next inst
I1_R2R : next_state = {DEC_EXEC, MEM_IFPP1, IPIPE_EN12A2}; //I1_R2R
default : next_state = {DEC_EXEC, MEM_IFPP1, IPIPE_EN12A2}; //I1_R2R
endcase
DEC_ED:
if (ed_nn) next_state = {DEC_EDNN1, MEM_IFPP1, IPIPE_ENN};
// we need to set inc and io and repeat flags on this state for continued block
// processing -- keep the states of this machine somewhat manageable.
else if (ed_blk_cp ) next_state = {DEC_EDBCP1, MEM_OFHL_PM, IPIPE_EN12};// MEM_OFHL_PM triggers --BC
else if (ed_blk_in ) next_state = {DEC_EDBIN1, MEM_IOF_C, IPIPE_EN12};// MEM_IOF_C triggers --B
else if (ed_blk_out) next_state = {DEC_EDBOUT1,MEM_OFHL_PM, IPIPE_EN12};
else if (ed_blk_mv ) next_state = {DEC_EDBMV1, MEM_OFHL_PM, IPIPE_EN12};
else if (ed_retn ) next_state = {DEC_RET, MEM_OFSP, IPIPE_EN12};// see int logic below
else next_state = {DEC_EXEC, MEM_IFPP1, IPIPE_EN12A2};
// double register reads and writes here
DEC_EDNN1: next_state = {DEC_EDNN2, MEM_NOP, IPIPE_ENN}; // address to nn
DEC_EDNN2:
if (ed_dbl_rd) next_state = {DEC_EDRD1, MEM_OFNN, IPIPE_NOP};
else next_state = {DEC_EDWR, MEM_OSNN, IPIPE_NOP};// OSNN selects data ok?
DEC_EDRD1: next_state = {DEC_EDRD2, MEM_OFADRP1, IPIPE_ENN}; // 1st byte 2n
DEC_EDRD2: next_state = {DEC_IF2, MEM_IFPP1, IPIPE_ENNA2}; // 2nd byte 2nn
DEC_EDWR: next_state = {DEC_IF1, MEM_OSADRP1, IPIPE_NOP};
// ED block moves
DEC_EDBCP1:
if (blk_done) next_state = {DEC_EXEC, MEM_IFPP1,IPIPE_ENNA2};
else if(wb_int) next_state = {DEC_INT1, MEM_NOP, IPIPE_ENNA2};
else next_state = {DEC_EDBCP2, MEM_NOP, IPIPE_ENNA2};//set flags
DEC_EDBCP2: next_state = {DEC_EDBCP3, MEM_NOP, IPIPE_NOP};//wait for fr. alu_out is slow
DEC_EDBCP3: if (fr[7]) next_state = {DEC_EXEC , MEM_IFPP1, IPIPE_NOP};
else next_state = {DEC_EDBCP1, MEM_OFHL_PM, IPIPE_NOP};
DEC_EDBIN1: next_state = {DEC_EDBIN2, MEM_NOP, IPIPE_ENN};
DEC_EDBIN2: if (blk_done) next_state = {DEC_IF2A, MEM_OSHL_PM,IPIPE_NOP}; // implies nn
else if (wb_int) next_state = {DEC_INT1, MEM_OSHL_PM,IPIPE_NOP};
else next_state = {DEC_EDBIN1,MEM_OSHL_PM,IPIPE_NOP};//set flags
DEC_EDBIN3: next_state = {DEC_EDBIN1, MEM_IOF_C, IPIPE_NOP};
DEC_EDBOUT1: next_state = {DEC_EDBOUT2, MEM_NOP, IPIPE_ENN};
DEC_EDBOUT2:if (blk_done) next_state = {DEC_EXEC, MEM_IOS_C,IPIPE_NOP};
else if (wb_int) next_state = {DEC_INT1, MEM_IOS_C,IPIPE_NOP}; // DEC_EDBOUT: if (blk_rpt)
else next_state = {DEC_EDBOUT3,MEM_IOS_C,IPIPE_NOP};
DEC_EDBOUT3: next_state = {DEC_EDBOUT1,MEM_OFHL_PM, IPIPE_NOP};
 
DEC_EDBMV1: next_state = {DEC_EDBMV2, MEM_NOP, IPIPE_ENN};
DEC_EDBMV2: if (blk_done) next_state = {DEC_EXEC, MEM_OSDE_PM,IPIPE_NOP};
else if (wb_int) next_state = {DEC_INT1, MEM_OSDE_PM,IPIPE_NOP}; //DEC_EDBOUT: if (blk_rpt)
else next_state = {DEC_EDBMV3,MEM_OSDE_PM,IPIPE_NOP};
DEC_EDBMV3: next_state = {DEC_EDBMV1,MEM_OFHL_PM, IPIPE_NOP};
DEC_N:
if (INsA_6N7== ir1) next_state = {DEC_NIN, MEM_IOF_N, IPIPE_EN12};
else if (OUTs6N7_A==ir1) next_state = {DEC_IF1, MEM_IOS_N, IPIPE_EN12};
else if (LDs6HL7_N==ir1) next_state = {DEC_IF1, MEM_OS_HL_N, IPIPE_EN12};
else if (jmpr_true) next_state = {DEC_IF2, MEM_IFREL_N, IPIPE_NOP};
else next_state = {DEC_EXEC, MEM_IFPP1, IPIPE_EN12A2};//r2r or false jumps
DEC_NIN: next_state = {DEC_IF2, MEM_IFPP1, IPIPE_ENNA2};
//ISSUES: LDsSP_NN - load commanded from ir2 decode? and mechaninsm for updating PC on
// JMP and CALL
// on CALL We have IFNN for JMP
// For CALL Use MEM_CALL to transfer pc<=nn, nn<=pc, adr<=sp then MEM_OSSP then IFPP1
// For LDsSP_NN yes update from ir2 decode.
DEC_NN:
if (callnn_true) next_state = {DEC_NNCALL1, MEM_NOP, IPIPE_ENN};// this gets new adr in nn
//if we store from nn we can't do
// a mem op now
else if (jmpnn_true) next_state = {DEC_NNJMP, MEM_NOP, IPIPE_ENN}; // gotta get nn before we can
// transfer to adr.
else if (LDs6NN7_A==ir1) next_state = {DEC_NNOS3, MEM_IFPP1, IPIPE_ENN};
else if (LDs6NN7_HL==ir1) next_state = {DEC_NNOS1, MEM_IFPP1, IPIPE_ENN};
else if (LDsA_6NN7==ir1) next_state = {DEC_NNOF3, MEM_IFPP1, IPIPE_ENN};
else if (LDsHL_6NN7==ir1) next_state = {DEC_NNOF1, MEM_IFPP1, IPIPE_ENN};
else next_state = { DEC_IF2, MEM_IFPP1, IPIPE_ENNEN2A2};
DEC_NNCALL1: next_state = {DEC_NNCALL2, MEM_CALL , IPIPE_NOP};
DEC_NNCALL2: next_state = {DEC_IF1, MEM_OSSP, IPIPE_ENN};//A1 activates r2r xfers from ir1
DEC_NNJMP: next_state = {DEC_IF2, MEM_IFNN , IPIPE_NOP};
// ISSUE: we blow out ir1 here - so need to keep some status to execute OSNN2.
// general solution if not DEC_EXEC we get op frmo nn high byte.
// note that first MEM_OSNN trabsferrs nn to wb_adr_o.
DEC_NNOS1: next_state = {DEC_NNOS2, MEM_OSNN, IPIPE_EN1};
DEC_NNOS2: next_state = {DEC_IF2A, MEM_OSNN, IPIPE_NOP};
DEC_NNOS3: next_state = {DEC_IF2A, MEM_OSNN, IPIPE_EN1};
DEC_NNOF1: next_state = {DEC_NNOF2, MEM_OFNN, IPIPE_EN12};
DEC_NNOF2: next_state = {DEC_NNOF4, MEM_OFNN, IPIPE_ENN};
DEC_NNOF3: next_state = {DEC_NNOF4, MEM_OFNN, IPIPE_EN12};
DEC_NNOF4: next_state = {DEC_EXEC, MEM_IFPP1, IPIPE_ENNA2};
DEC_DDOS: next_state = {DEC_IF2A, MEM_OSIXpD, IPIPE_EN12};
DEC_DDOF: next_state = {DEC_OF , MEM_OFIXpD, IPIPE_EN12};
DEC_OF: next_state = {DEC_EXEC, MEM_IFPP1 , IPIPE_ENNA2};
DEC_POP: next_state = {DEC_NNOF4, MEM_OFSP, IPIPE_ENN };
DEC_PUSH: next_state = {DEC_IF2A , MEM_OSSP, IPIPE_NOP };
DEC_RET: next_state = { DEC_RET2, MEM_OFSP, IPIPE_ENN };
DEC_RET2: next_state = { DEC_NNCALL2, MEM_NOP, IPIPE_ENN };
// blow off a tick so we don't gronk adr
DEC_RMW: next_state = {DEC_RMW2, MEM_NOP, IPIPE_ENNA2}; //activate
DEC_RMW2: next_state = {DEC_IF1 , MEM_OSADR, IPIPE_NOP }; // from nn
// IF memory -- rmw else these are all reg 2 reg
DEC_CBM: if (CB_BIT==ir1[9:6]) next_state = {DEC_IF2, MEM_IFPP1, IPIPE_ENNA2};
else next_state = {DEC_RMW2 , MEM_NOP, IPIPE_ENNA2};
// The DDCB anf FDCB all assume memory operands
// These beauties always rmw memory. If a register op is default, they also
// update the register. Programmers think of this as 2 ops for the price of 1.
// unfortunately it is 2 ops for the price of 4.-- its not the number of lines
// of assembler code that count but the number of bytes assembled. Oh well I signed
// up for this...... and had a notion of what I was getting into.
//
DEC_PFxCB: next_state = { DEC_PFxCB2, MEM_IFPP1, IPIPE_ENN}; // this gets d
DEC_PFxCB2: next_state = { DEC_PFxCB3, MEM_OFIXpD, IPIPE_EN1}; //actual inst
DEC_PFxCB3: next_state = { DEC_PFxCB4, MEM_IFPP1, IPIPE_ENNEN2A2};
DEC_PFxCB4: next_state = { DEC_IF2A, MEM_OSADR, IPIPE_EN1}; //execute ir2
// crap gotta subtract 2 (we always increment pc 2 times relative to the inst
// that got interrupted. also can't push and dec pc without 2 adders.
// choices: 1) fix up pc in 2 ticks 2) fix in 1 tick 3) add adder and do it fast
// if there's anyone who knows is there anyone who cares.
// guess I'll do it fast -- just a 16 bit subtractor. heck silicon is
// cheap.
DEC_INT1: next_state = {DEC_INT2, MEM_OSSP_PCM2, IPIPE_NOP}; //must derement PC
DEC_INT2: next_state = {DEC_INT3, MEM_OSSP_P, IPIPE_NOP}; //must dec sp and PC 2 ops?
DEC_INT3: next_state = {DEC_INT4, MEM_INTA, IPIPE_NOP};
DEC_INT4: next_state = {DEC_INT5, MEM_NOP, IPIPE_ENN};
DEC_INT5: next_state = {DEC_IF2, MEM_IFINT, IPIPE_NOP};
default: next_state = {DEC_IDLE, MEM_NOP, IPIPE_NOP};
endcase
end
 
 
always @(posedge wb_clk_i or posedge rst_i)
if (rst_i) dec_state <= DEC_IDLE;
else if (wb_rdy_nhz ) dec_state <= next_dec_state;
 
 
//-----------------------instruction register #1 ----------------------------------
// // next_pipe_state {ir1,ir2,nn,act_ir2}
 
wire update_prefix = dec_state == DEC_EXEC | dec_state == DEC_DDFD;
always @(posedge wb_clk_i or posedge rst_i)
if (rst_i) ir1 <= NOP;
else if (wb_rdy_nhz & next_pipe_state[3]) ir1 <= {2'b0, wb_dat_i} ;
else if ( wb_rdy_nhz &update_prefix ) ir1 <= {ir1[7:0]==8'hed, ir1[7:0]==8'hcd, ir1[7:0]};
 
//----------- prefix states -----------------------------------------
// strings of prefix insts are ignored up to last one. Also dded and fded are ignored
// but ddcd and fdcd are defined prefix sets.
//
always @(posedge wb_clk_i)
if (wb_rdy_nhz & next_pipe_state[3]) {ir1dd, ir1fd } <= 2'b0;
else if ( wb_rdy_nhz & update_prefix )
{ir1dd, ir1fd } <= {ir1dd | (ir1[7:0]==8'hdd ) & (ir1[7:0]!=8'hed) & (ir1[7:0]!=8'hfd),
ir1fd | (ir1[7:0]==8'hfd ) & (ir1[7:0]!=8'hed) & (ir1[7:0]!=8'hdd) };
//------------------- inst reg #2 -----------------------------------
// This stuff is key to the data hazard logic. Hazards arise only AFTER activation of
// a previous instruction. Fundamentally all state changes related to ir1 may be
// delayed eithor by a delay in wb response, or by a hazard. Ir2 state changes
// are keyed off exec_ir2 - and always happen immediately. ( exec_ir2 always is
// immediately reset - unless of course a new instruction is transferred and executed.
//
//
//
always @(posedge wb_clk_i or posedge rst_i)
if (rst_i) ir2 <= 10'h0;
else if (wb_rdy_nhz & next_pipe_state[2]) ir2 <= ir1;
always @(posedge wb_clk_i or posedge rst_i)
if (rst_i)
begin
ir2dd <= 1'b0;
ir2fd <= 1'b0;
end
else if (wb_rdy_nhz & next_pipe_state[2])
begin
ir2dd <= ir1dd;
ir2fd <= ir1fd;
end
always @(posedge wb_clk_i )
if (wb_rdy_nhz & next_pipe_state[0]) exec_ir2 <= 1'b1;
else exec_ir2 <= 1'b0;
 
 
 
 
 
//--------------- block move flags ------------------------
always @(posedge wb_clk_i)
if (dec_state == DEC_ED) blk_inc_flg <= dec_blk_inc;
 
always @(posedge wb_clk_i)
if (dec_state == DEC_ED) blk_rpt_flg <= dec_blk_rpt;
 
 
always @(posedge wb_clk_i)
if (dec_state == DEC_ED) blk_io_flg <= dec_blk_io;
 
 
//-------------------------- memory interface stuff ----------------------------
 
 
// -- wb_adr_o
always @(posedge wb_clk_i) if (wb_rdy) wb_adr_o <= mux21;
 
// -- wb_we_o;
 
always @(posedge wb_clk_i or posedge rst_i)
if (rst_i) wb_we_o <= 1'b0;
else if (wb_rdy_nhz) wb_we_o <= we_next;
// -- wb_cyc_o
// below is old logic -- appears not needed
//wire no_wb_start = mem_idle | mem_halt | mem_op3 & blk_cmp_reg | mem_op1 & rmw_reg;
always @(posedge wb_clk_i or posedge rst_i)
if (rst_i) wb_cyc_o <= 1'b0;
else if (wb_rdy_nhz) wb_cyc_o <= next_mem_state != MEM_NOP ;
 
// -- wb_stb_o;
 
always @(posedge wb_clk_i or posedge rst_i)
if (rst_i) wb_stb_o <= 1'b0;
else if (wb_rdy_nhz) wb_stb_o <= next_mem_state != MEM_NOP ;
 
 
// -- wb_lock lets not worry about lock unless somebody thinks it matters.
 
// -- wb_tga_o
always @(posedge wb_clk_i or posedge rst_i)
if (rst_i) wb_tga_o <= 2'b0;
else if (wb_rdy_nhz)
begin
if (next_mem_state == MEM_IOF_C |
next_mem_state == MEM_IOS_C |
next_mem_state == MEM_IOF_N |
next_mem_state == MEM_IOS_N ) wb_tga_o <= TAG_IO;
 
else if (next_mem_state == MEM_INTA ) wb_tga_o <= TAG_INT;
else wb_tga_o <= 2'b0 ;
end
 
//------------ the input-output data register (nn) -----------------------------------------
// basicaly we store lsb's folowed by msb's
// input is always to msb (of input regiser) first (if a 2 byte operand, lsb<=msb before transfer)
// this gets nn to position { msb, lsb } before we execute 2 byte transfer.
//
// if we don't update - we byte swap as well as
// when we read
// IMPORTANT We store from MSB's so that on block moves read and write from same place.
// this makes the output look somewhat bass-ackwards but who is looking?
//
// There is probably a simpler way to do this. Unfortunately there are a lot of
// dependencies here. Ill continue as planned till it proves untractable.
// Issue is that we are using ir1 to provide the op specification -- but in general
// ir1 gets gronked before 2nd store (if it happens) - so we need to capture both
// data first time OSIXpD OS1 OSSP, and MEM_OSNN
//
// on consideration lets make a flag flag_firstos that gets set on first store after
// DEC_EXEC
// ISSUE reads both here and in ir1 need to execute on wb_ack_i ?
// I recall wb_ack_i must stay active until a change in cycle ?
// need to review wb spec.
//
//issue: how is EXs6SP7_HL implemented -- it is known as a rmw - and only trick for this file is
// that nn must be properly updates with ir2
always @(posedge wb_clk_i or posedge rst_i)
if (rst_i) flag_os1 <= 1'b0;
else if ((DEC_EXEC == next_dec_state) & wb_rdy) flag_os1 <= 1'b0;
else if ( we_next ) flag_os1 <= 1'b1;
 
 
wire [15:0] pc_2 = pc - 16'h2;
always @(posedge wb_clk_i)
if (wb_rdy_nhz)
begin
if ( we_next & flag_os1) nn <= { nn[7:0], nn[15:8] } ;
else if(we_next & ( next_mem_state == MEM_CALL)) nn <= {pc[7:0], pc[15:8]};
else if(we_next & ( next_mem_state == MEM_OSSP_PCM2)) nn <= {pc_2[7:0], pc_2[15:8]};
else if(EXs6SP7_HL== ir2 & ir2dd & exec_ir2) nn <= ixr;
else if(EXs6SP7_HL== ir2 & ir2fd & exec_ir2) nn <= iyr;
else if(EXs6SP7_HL== ir2 & exec_ir2) nn <= hl;
// these are the general cases with ir1 providing register specification
else if(we_next & ( next_mem_state == MEM_OS1 |
next_mem_state == MEM_OSIXpD |
next_mem_state == MEM_OSSP |
next_mem_state == MEM_OSNN ) )
begin
if (os_a) nn[15:8] <= ar;
if (os_b) nn[15:8] <= br;
if (os_c) nn <= {cr, br }; // use for PUSHsBC
if (os_d) nn[15:8] <= dr;
if (os_e) nn <= {er, dr }; // use for PUSHsDE
if (os_h) nn[15:8] <= hr;
if (os_l) nn <= {lr, hr }; // use for PUSHsHL
if (os_f) nn <= {fr, ar }; // use for PUSHsAF
end
// 4/19/2004 previously no if here - if not needed we don't need next_pipe_state[1] eithor
else if (next_pipe_state[1]) nn <= { wb_dat_i, nn[15:8] };
end
 
 
//------------------- pc and sp ----------------------------------------------------
always @(posedge wb_clk_i or posedge rst_i)
if (rst_i) pc <= 16'h0;
else if (wb_rdy_nhz)
begin
if (next_mem_state == MEM_DECPC) pc <= pc - 16'h1; // decrementer could perhaps be shared.
if (next_mem_state == MEM_IFPP1) pc <= adr_alu;
if (next_mem_state == MEM_CALL ) pc <= nn; //Use MEM_CALL to exchange pc<=>nn
if (next_mem_state == MEM_IFRST) pc <= src_mux;
if (next_mem_state == MEM_JMPHL) pc <= src_mux;
if (next_mem_state == MEM_IFNN ) pc <= src_mux;
if (next_mem_state == MEM_IFINT) pc <= src_mux;
end
 
//---------------------------------- sp -----------------------------------------------------
//
// with pc updates are always made from ir1 as the PC is so critical to instruction flow.
// (this of course creates the possibility of an "inst_hazard" - where data is stored in an
// instruction already fetched - see below)
// with sp the situation is not so simple.
// Issues - especially regarding hazards.
//
// LDsSP_NN this should be done from ir2 - no hazard as active state is ALWAYS IF2
//
// ADDsHL_SP The add is a pre-add so sp cannot be modified before inst is executed from ir2
// DECsSP Just do it with ir1 at DEC_EXEC gotcha need -- IFPP1 in general use ir2 -> hazard
// EXs6SP7_HL rmw - no change to sp - no issue here
// INCsSP Just do it with ir1 at DEC_EXEC gotcha -- IFPP1 use ir2 -> hazard
// LDsSP_HL do from ir1 and use standard hazard logic (if H or L is being
// updated -- wait)
//
// ED_LDs6NN7_REG REG== SP // needs to be done from ir2
// ED_LDsREG_6NN7 REG== SP // do from ir2 - no hazard as executed on IF2 - refill pipe
 
always @(posedge wb_clk_i )
if (exec_ir2 ) // this has priority of course
begin
if (LDsSP_NN == ir2) sp <= nn;
if (ED_LDsREG_6NN7 == ir2) sp <= nn;
if ( DECsSP == ir2 ) sp <= add16;
if ( INCsSP == ir2 ) sp <= add16;
end
else if (wb_rdy_nhz)
begin
if ( DECsSP == ir1 & dec_state == DEC_EXEC) sp <= adr_alu;
if ( INCsSP == ir1 & dec_state == DEC_EXEC) sp <= adr_alu;
if ( LDsSP_HL == ir1 & dec_state == DEC_EXEC) sp <= {hr,lr};
if (next_mem_state == MEM_OFSP ) sp <= adr_alu;
if (next_mem_state == MEM_OSSP ) sp <= adr_alu;
if (next_mem_state == MEM_OSSP_PCM2 ) sp <= adr_alu;
if (next_mem_state == MEM_OSSP_P ) sp <= adr_alu;
end
//----------------- inst hazard logic ------------------------------------------
 
 
 
always @(posedge wb_clk_i or posedge rst_i)
if (rst_i) inst_haz <= 1'b0;
else if (we_next & (pc - 16'h1) == mux21) inst_haz <= 1'b1;
else if (dec_state == DEC_EXEC) inst_haz <= 1'b0; // highest priority interrupt
 
//-------------------- int logic ----------------------------------------
// We have a wishbone interrupt system - which i guess does not preclude a
// non-maskable interrupt...... but bottom line is that such an interrupt is
// definately out of favor with current system thinking. Within an embedded system
// ( the target application here ) a single interrupt controller capable of handeling
// as many interrupts as desired is the best choice.
// Therefore we enable only mode 2 interrupts and a single enable ff.
//
// This begs the question of what to do with the "RETI" instruction -- ED4D. We opt to
// enable interrupts with this instruction (and all its "aliases").
//
always @(posedge wb_clk_i or posedge rst_i)
if (rst_i) int_en <= 1'b0;
else if (wb_rdy_nhz)
begin
if ((dec_state == DEC_EXEC) & (DI== ir1)) int_en <= 1'b0;
else if ((dec_state == DEC_EXEC) & en_int_next) int_en <= 1'b1;
else if ((dec_state == DEC_ED) & ed_retn) int_en <= 1'b0;
if (dec_state == DEC_INT1) int_en <= 1'b0;
end
 
 
always @(posedge wb_clk_i or posedge rst_i)
if (rst_i) en_int_next <=1'b0;
else if (wb_rdy_nhz)
begin
if ((dec_state == DEC_EXEC) & (EI== ir1)) en_int_next <=1'b1;
else if (dec_state == DEC_EXEC) en_int_next <=1'b0;
end
always @(posedge wb_clk_i)
wb_irq_sync <= int_req_i;
 
assign wb_int = wb_irq_sync & int_en;
 
endmodule
/trunk/rtl/z80_sdram_cfg.v
0,0 → 1,98
///////////////////////////////////////////////////////////////////////////////////////////////
////
//// file name: z80_sdram_cfg
//// description: configure address range and mux data for on-board sdram
//// project: wb_z80 ////
////
//// Author: B.J. Porcella
//// bporcella@sbcglobal.net
////
////
////
///////////////////////////////////////////////////////////////////////////////////////////////
////
//// Copyright (C) 2000-2002 B.J. Porcella
//// Real Time Solutions
////
////
//// This source file may be used and distributed without
//// restriction provided that this copyright statement is not
//// removed from the file and that any derivative work contains
//// the original copyright notice and the associated disclaimer.
////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//// POSSIBILITY OF SUCH DAMAGE.
////
///////////////////////////////////////////////////////////////////////////////////////////////
// CVS Log
//
// $Id: z80_sdram_cfg.v,v 1.1 2004-04-27 21:27:13 bporcella Exp $
//
// $Date: 2004-04-27 21:27:13 $
// $Revision: 1.1 $
// $Author: bporcella $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.1.1.1 2004/04/13 23:47:42 bporcella
// import first files
//
//
//
//-------1---------2---------3--------Module Name and Port List------7---------8---------9--------0
module z80_sdram_cfg (cfg_ce_spram_o, cfg_do, cfg_ack_o, wb_adr_i, sdram_di, wb_dat_i, wb_ack_i,
wb_stb_i, wb_cyc_i, wb_tga_i);
 
 
//-------1---------2---------3--------Output Ports---------6---------7---------8---------9--------0
output cfg_ce_spram_o;
output [7:0] cfg_do;
output cfg_ack_o;
 
//-------1---------2---------3--------Input Ports----------6---------7---------8---------9--------0
 
input [15:0] wb_adr_i;
input [7:0] sdram_di, wb_dat_i;
input wb_ack_i;
input wb_stb_i;
input wb_cyc_i;
input [1:0] wb_tga_i;
 
//-------1---------2---------3--------Parameters-----------6---------7---------8---------9--------0
//-------1---------2---------3--------Wires------5---------6---------7---------8---------9--------0
//-------1---------2---------3--------Registers--5---------6---------7---------8---------9--------0
//-------1---------2---------3--------Assignments----------6---------7---------8---------9--------0
 
// this assigns the low half of the address space to the on-board sdram. Any given implementation
// might well wish to modify this assigmnment
// Lot of I/O for not much logic --- guess if there were no "rules" I would simply put this stuff
// in the top level.
 
 
 
wire sram_addr = ~wb_adr_i[15] & (wb_tga_i == 2'b00);
 
wire cfg_ce_spram_o = sram_addr & wb_cyc_i & wb_stb_i;
 
wire [7:0] cfg_do = sram_addr ? sdram_di : wb_dat_i;
 
wire cfg_ack_o = cfg_ce_spram_o | wb_ack_i;
 
//-------1---------2---------3--------State Machines-------6---------7---------8---------9--------0
 
 
 
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.