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

Subversion Repositories test

[/] [test/] [trunk/] [wb_z80/] [rtl/] [inst_exec.v] - Rev 53

Compare with Previous | Blame | View Log

///////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                               //
//  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: inst_exec.v,v 1.1 2004-04-17 07:39:21 mihal Exp $
//
//  $Date: 2004-04-17 07:39:21 $
//  $Revision: 1.1 $
//  $Author: mihal $
//  $Locker:  $
//  $State: Exp $
//
// Change History:
//      $Log: not supported by cvs2svn $
//      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 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, intr, 
                  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, intr; 
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          src_dblhr       ;
wire          src_cb_r20      ;
wire          src_pqr20       ;
wire          src_pqr53       ;
wire          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        ;
 
//-------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}      ;
 
assign  src_cb_r20 = (ddcb_grp | fdcb_grp) ? nn[7:0]   :
                             cb_grp        ? src_pqr20 :
                             ar                        ;
 
 
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[7:0] |
                    {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[7:0] |
                    {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_sshr |
                   {16{ir2[5:4]==2'b11}} & sp        ;
 
 
 
 
 
// 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
                              ed_grp ?  8'h0  :  // for ed44 -a
                              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] | 
                 ed_grp                      ;
 
 
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.
//
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
 
   {14{ir2[7:3]==5'b10000}}         & ({c_8out7,c_8out3,  add_8bit,    src_pqr20, 1'b0} )  |// a+src
   {14{ir2[7:3]==5'b10001}}         & ({c_8out7,c_8out3,  add_8bit,    src_pqr20,   cf} )  |// a+src+cf
   {14{ir2[7:3]==5'b10010}}         & ({c_8out7,c_8out3,  add_8bit,   ~src_pqr20, 1'h1} )  |// a-src
   {14{ir2[7:3]==5'b10011}}         & ({c_8out7,c_8out3,  add_8bit,   ~src_pqr20, ~cf } )  |// a-src-cf
   {14{ir2[7:3]==5'b10100}}         & ({1'b0   ,1'b1   , ar & src_pqr, src_pqr20, 1'b0} )  |// a&src
   {14{ir2[7:3]==5'b10101}}         & ({1'b0   ,1'b0   , ar ^ src_pqr, src_pqr20, 1'b0} )  |// a^src
   {14{ir2[7:3]==5'b10110}}         & ({1'b0   ,1'b0   , ar | src_pqr, src_pqr20, 1'b0} )  |// a|src
   {14{ir2[7:3]==5'b10111}}         & ({c_8out7,c_8out3,  add_8bit,    src_pqr20,  1'h1})  |// a-src
   {14{(ir2[7:6]==2'b00)& ~ir2[0] }}& ({     cf,c_8out3,  add_8bit,    src_pqr53,  1'h1})  |// inc_r main
   {14{(ir2[7:6]==2'b00)&  ir2[0] }}& ({     cf,c_8out3,  add_8bit,    src_pqr53,  1'h0})  |// dec_r
   {14{(ir2[7:6]==2'b01)          }}& ({c_8out7,c_8out3,  add_8bit,           ~a,  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]);
 
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} = 
   {17{ir2[3:0] == 4'h9}} & {src_dblhr, src_dbl  ,1'b0 }   |  //ADD
   {17{ir2[3:0] == 4'hb}} & {16'hffff , src_dbl  ,1'b0 }   |  //DEC 
   {17{ir2[3:0] == 4'h3}} & {16'h0001 , src_dbl  ,1'b0 }   |  //INC
   {17{ir2[3:0] == 4'h2}} & {src_dblhr, ~src_dbl , ~cf }   |  //SBC
   {17{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 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}} & ( shPsrc | 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[7: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        ;  compair with {ir2[9:6],ir2[3:0]} all 
//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[9:6], ir2[3:0]} == 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_pqr;
    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[9:6], ir2[3:0]} == ED_RRD & exec_ir2) ar[3:0] <= nn[3:0];         
    if ({ir2[9:6], ir2[3:0]} == 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 ;
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[7: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_pqr;
    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[7: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[7: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_pqr;
    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[7:6],ir2[2:0]}) & (ir2[5:3] == REG8_C) & exec_ir2)    
                                           cr <= nn[7:0];    
 
end
 
 
//  update dr
assign up_d_add16 =
    INCsDE       == 10'h13 |  //      INC DE       ; 13
    DECsDE       == 10'h1B  ; //      DEC DE       ; 1B
 
assign upd_d_alu8 =
    INCsD        == 10'h14 |  //      INC D        ; 14
    DECsD        == 10'h15  ; //      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[7: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[7: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_pqr;
    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[7: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[7: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[7: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_pqr;
    if ( up_e_add16   & exec_ir2)      er <= add16;
    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[7: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[7: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 | up_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[7: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 ( up_h_src_pqr & exec_hlir2)      hr <= src_pqr;
    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[7: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 | up_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[7:6],ir2[2:0]}) & (ir2[5:3] == REG8_L);
 
 
 
always @(posedge clk)
begin
    if ( upd_l_alu8 & exec_hlir2)        lr <= alu8_out;
    if ( up_l_src_pqr & exec_hlir2)      lr <= src_pqr;
    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[7: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 ( up_l_src_pqr & exec_ixir2)      ixr[7:0] <= src_pqr;
    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 ( up_h_src_pqr & exec_ixir2)      ixr[15:8] <= src_pqr;
    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 ( up_l_src_pqr & exec_iyir2)      iyr[7:0] <= src_pqr;
    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 ( up_h_src_pqr & exec_iyir2)      iyr[15:8] <= src_pqr;
    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 |  SBCsA_6HL7==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[7:6],ir2[3:0]} | // compair with {ir2[7:6],ir2[3:0]}
    ED_ADCsHL_REG  == {ir2[7:6],ir2[3:0]} ; // compair with {ir2[7: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
//  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)                      )  ; 
 
 
 
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_out11, 
                                       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 ?                            
 
    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)
begin
    if (( ED_LDsI_A == ir2) & exec_ir2) intr <= ar;
end
 
 
endmodule
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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