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

Subversion Repositories tv80

[/] [tv80/] [branches/] [restruc2/] [rtl/] [core/] [tv80_mcode_ed.v] - Rev 86

Go to most recent revision | Compare with Previous | Blame | View Log

//
// TV80 8-Bit Microprocessor Core
// Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org)
//
// Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a 
// copy of this software and associated documentation files (the "Software"), 
// to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, 
// and/or sell copies of the Software, and to permit persons to whom the 
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included 
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
module tv80_mcode_ed
  (/*AUTOARG*/
  // Outputs
  output_vector, 
  // Inputs
  IR, MCycle
  );
 
  parameter             Mode   = 0;
  parameter             Flag_C = 0;
  parameter             Flag_N = 1;
  parameter             Flag_P = 2;
  parameter             Flag_X = 3;
  parameter             Flag_H = 4;
  parameter             Flag_Y = 5;
  parameter             Flag_Z = 6;
  parameter             Flag_S = 7;
 
  output [67:0]         output_vector;
 
  input [7:0]            IR;
  input [6:0]            MCycle                  ;
 
  // regs
  reg [2:0]             MCycles                 ;
  reg [2:0]             TStates                 ;
  reg [1:0]             Prefix                  ; // None,BC,ED,DD/FD
  reg                   Inc_PC                  ;
  reg                   Inc_WZ                  ;
  reg [3:0]             IncDec_16               ; // BC,DE,HL,SP   0 is inc
  reg                   Read_To_Reg             ;
  reg                   Read_To_Acc             ;
  reg [3:0]             Set_BusA_To     ; // B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F
  reg [3:0]             Set_BusB_To     ; // B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0
  reg [3:0]             ALU_Op                  ;
  reg                   Save_ALU                ;
  reg                   PreserveC               ;
  reg                   Arith16                 ;
  reg [2:0]             Set_Addr_To             ; // aNone,aXY,aIOA,aSP,aBC,aDE,aZI
  reg                   IORQ                    ;
  reg                   Jump                    ;
  reg                   JumpE                   ;
  reg                   JumpXY                  ;
  reg                   Call                    ;
  reg                   RstP                    ;
  reg                   LDZ                     ;
  reg                   LDW                     ;
  reg                   LDSPHL                  ;
  reg [2:0]             Special_LD              ; // A,I;A,R;I,A;R,A;None
  reg                   ExchangeDH              ;
  reg                   ExchangeRp              ;
  reg                   ExchangeAF              ;
  reg                   ExchangeRS              ;
  reg                   I_DJNZ                  ;
  reg                   I_CPL                   ;
  reg                   I_CCF                   ;
  reg                   I_SCF                   ;
  reg                   I_RETN                  ;
  reg                   I_BT                    ;
  reg                   I_BC                    ;
  reg                   I_BTR                   ;
  reg                   I_RLD                   ;
  reg                   I_RRD                   ;
  reg                   I_INRC                  ;
  reg                   SetDI                   ;
  reg                   SetEI                   ;
  reg [1:0]             IMode                   ;
  reg                   Halt                    ;
  reg                   NoRead                  ;
  reg                   Write   ;                
 
  parameter             aNone   = 3'b111;
  parameter             aBC     = 3'b000;
  parameter             aDE     = 3'b001;
  parameter             aXY     = 3'b010;
  parameter             aIOA    = 3'b100;
  parameter             aSP     = 3'b101;
  parameter             aZI     = 3'b110;
 
 
  reg [2:0] DDD;
  reg [2:0] SSS;
  reg [1:0] DPAIR;
  reg [7:0] IRB;
 
  always @ (/*AUTOSENSE*/IR or MCycle)
    begin
      DDD = IR[5:3];
      SSS = IR[2:0];
      DPAIR = IR[5:4];
      IRB = IR;
 
      MCycles = 3'b001;
      if (MCycle[0] ) 
        begin
          TStates = 3'b100;
        end 
      else 
        begin
          TStates = 3'b011;
        end
      Prefix = 2'b00;
      Inc_PC = 1'b0;
      Inc_WZ = 1'b0;
      IncDec_16 = 4'b0000;
      Read_To_Acc = 1'b0;
      Read_To_Reg = 1'b0;
      Set_BusB_To = 4'b0000;
      Set_BusA_To = 4'b0000;
      ALU_Op = { 1'b0, IR[5:3] };
      Save_ALU = 1'b0;
      PreserveC = 1'b0;
      Arith16 = 1'b0;
      IORQ = 1'b0;
      Set_Addr_To = aNone;
      Jump = 1'b0;
      JumpE = 1'b0;
      JumpXY = 1'b0;
      Call = 1'b0;
      RstP = 1'b0;
      LDZ = 1'b0;
      LDW = 1'b0;
      LDSPHL = 1'b0;
      Special_LD = 3'b000;
      ExchangeDH = 1'b0;
      ExchangeRp = 1'b0;
      ExchangeAF = 1'b0;
      ExchangeRS = 1'b0;
      I_DJNZ = 1'b0;
      I_CPL = 1'b0;
      I_CCF = 1'b0;
      I_SCF = 1'b0;
      I_RETN = 1'b0;
      I_BT = 1'b0;
      I_BC = 1'b0;
      I_BTR = 1'b0;
      I_RLD = 1'b0;
      I_RRD = 1'b0;
      I_INRC = 1'b0;
      SetDI = 1'b0;
      SetEI = 1'b0;
      IMode = 2'b11;
      Halt = 1'b0;
      NoRead = 1'b0;
      Write = 1'b0;
 
      //----------------------------------------------------------------------------
      //
      //  ED prefixed instructions
      //
      //----------------------------------------------------------------------------
 
      casex (IRB)
        // 8 BIT LOAD GROUP
        8'b01010111  :
          begin
            // LD A,I
            Special_LD = 3'b100;
            TStates = 3'b101;
          end
 
        8'b01011111  :
          begin
            // LD A,R
            Special_LD = 3'b101;
            TStates = 3'b101;
          end
 
        8'b01000111  :
          begin
            // LD I,A
            Special_LD = 3'b110;
            TStates = 3'b101;
          end
 
        8'b01001111  :
          begin
            // LD R,A
            Special_LD = 3'b111;
            TStates = 3'b101;
          end
 
        // 16 BIT LOAD GROUP
        8'b01xx1011 :
          begin
            // LD dd,(nn)
            MCycles = 3'b101;
            case (1'b1) // MCycle
              MCycle[1] :
                begin
                  Inc_PC = 1'b1;
                  LDZ = 1'b1;
                end
 
              MCycle[2] :
                begin
                  Set_Addr_To = aZI;
                  Inc_PC = 1'b1;
                  LDW = 1'b1;
                end
 
              MCycle[3] :
                begin
                  Read_To_Reg = 1'b1;
                  if (IR[5:4] == 2'b11 ) 
                    begin
                      Set_BusA_To = 4'b1000;
                    end 
                  else 
                    begin
                      Set_BusA_To[2:1] = IR[5:4];
                      Set_BusA_To[0] = 1'b1;
                    end
                  Inc_WZ = 1'b1;
                  Set_Addr_To = aZI;
                end // case: 4
 
              MCycle[4] :
                begin
                  Read_To_Reg = 1'b1;
                  if (IR[5:4] == 2'b11 ) 
                    begin
                      Set_BusA_To = 4'b1001;
                    end 
                  else 
                    begin
                      Set_BusA_To[2:1] = IR[5:4];
                      Set_BusA_To[0] = 1'b0;
                    end
                end // case: 5
 
              default :;
            endcase // case(MCycle)
          end // case: 8'b01001011,8'b01011011,8'b01101011,8'b01111011
 
 
        8'b01xx0011  :
          begin
            // LD (nn),dd
            MCycles = 3'b101;
            case (1'b1) // MCycle
              MCycle[1] :
                begin
                  Inc_PC = 1'b1;
                  LDZ = 1'b1;
                end
 
              MCycle[2] :
                begin
                  Set_Addr_To = aZI;
                  Inc_PC = 1'b1;
                  LDW = 1'b1;
                  if (IR[5:4] == 2'b11 ) 
                    begin
                      Set_BusB_To = 4'b1000;
                    end 
                  else 
                    begin
                      Set_BusB_To[2:1] = IR[5:4];
                      Set_BusB_To[0] = 1'b1;
                      Set_BusB_To[3] = 1'b0;
                    end
                end // case: 3
 
              MCycle[3] :
                begin
                  Inc_WZ = 1'b1;
                  Set_Addr_To = aZI;
                  Write = 1'b1;
                  if (IR[5:4] == 2'b11 ) 
                    begin
                      Set_BusB_To = 4'b1001;
                    end 
                  else 
                    begin
                      Set_BusB_To[2:1] = IR[5:4];
                      Set_BusB_To[0] = 1'b0;
                      Set_BusB_To[3] = 1'b0;
                    end
                end // case: 4
 
              MCycle[4] :
                begin
                  Write = 1'b1;
                end
 
              default :;
            endcase // case(MCycle)
          end // case: 8'b01000011,8'b01010011,8'b01100011,8'b01110011
 
        8'b101xx000 :
          begin
            // LDI, LDD, LDIR, LDDR
            MCycles = 3'b100;
            case (1'b1) // MCycle
              MCycle[0] :
                begin
                  Set_Addr_To = aXY;
                  IncDec_16 = 4'b1100; // BC
                end
 
              MCycle[1] :
                begin
                  Set_BusB_To = 4'b0110;
                  Set_BusA_To[2:0] = 3'b111;
                  ALU_Op = 4'b0000;
                  Set_Addr_To = aDE;
                  if (IR[3] == 1'b0 ) 
                    begin
                      IncDec_16 = 4'b0110; // IX
                    end 
                  else 
                    begin
                      IncDec_16 = 4'b1110;
                    end
                end // case: 2
 
              MCycle[2] :
                begin
                  I_BT = 1'b1;
                  TStates = 3'b101;
                  Write = 1'b1;
                  if (IR[3] == 1'b0 ) 
                    begin
                      IncDec_16 = 4'b0101; // DE
                    end 
                  else 
                    begin
                      IncDec_16 = 4'b1101;
                    end
                end // case: 3
 
              MCycle[3] :
                begin
                  NoRead = 1'b1;
                  TStates = 3'b101;
                end
 
              default :;
            endcase // case(MCycle)
          end // case: 8'b10100000 , 8'b10101000 , 8'b10110000 , 8'b10111000
 
        8'b101xx001 :
          begin
            // CPI, CPD, CPIR, CPDR
            MCycles = 3'b100;
            case (1'b1) // MCycle
              MCycle[0] :
                begin
                  Set_Addr_To = aXY;
                  IncDec_16 = 4'b1100; // BC
                end
 
              MCycle[1] :
                begin
                  Set_BusB_To = 4'b0110;
                  Set_BusA_To[2:0] = 3'b111;
                  ALU_Op = 4'b0111;
                  Save_ALU = 1'b1;
                  PreserveC = 1'b1;
                  if (IR[3] == 1'b0 ) 
                    begin
                      IncDec_16 = 4'b0110;
                    end 
                  else 
                    begin
                      IncDec_16 = 4'b1110;
                    end
                end // case: 2
 
              MCycle[2] :
                begin
                  NoRead = 1'b1;
                  I_BC = 1'b1;
                  TStates = 3'b101;
                end
 
              MCycle[3] :
                begin
                  NoRead = 1'b1;
                  TStates = 3'b101;
                end
 
              default :;
            endcase // case(MCycle)
          end // case: 8'b10100001 , 8'b10101001 , 8'b10110001 , 8'b10111001
 
        8'b01xxx100 :
          begin
            // NEG
            ALU_Op = 4'b0010;
            Set_BusB_To = 4'b0111;
            Set_BusA_To = 4'b1010;
            Read_To_Acc = 1'b1;
            Save_ALU = 1'b1;
          end
 
        8'b01000110,8'b01001110,8'b01100110,8'b01101110  :
          begin
            // IM 0
            IMode = 2'b00;
          end
 
        8'b01010110,8'b01110110  :
          // IM 1
          IMode = 2'b01;
 
        8'b01011110,8'b01110111  :
          // IM 2
          IMode = 2'b10;
 
        // 16 bit arithmetic
        8'b01001010,8'b01011010,8'b01101010,8'b01111010  :
          begin
            // ADC HL,ss
            MCycles = 3'b011;
            case (1'b1) // MCycle
              MCycle[1] :
                begin
                  NoRead = 1'b1;
                  ALU_Op = 4'b0001;
                  Read_To_Reg = 1'b1;
                  Save_ALU = 1'b1;
                  Set_BusA_To[2:0] = 3'b101;
                  case (IR[5:4])
                    0,1,2  :
                      begin
                        Set_BusB_To[2:1] = IR[5:4];
                        Set_BusB_To[0] = 1'b1;
                      end
                    default :
                      Set_BusB_To = 4'b1000;
                  endcase
                  TStates = 3'b100;
                end // case: 2
 
              MCycle[2] :
                begin
                  NoRead = 1'b1;
                  Read_To_Reg = 1'b1;
                  Save_ALU = 1'b1;
                  ALU_Op = 4'b0001;
                  Set_BusA_To[2:0] = 3'b100;
                  case (IR[5:4])
                    0,1,2  :
                      begin
                        Set_BusB_To[2:1] = IR[5:4];
                        Set_BusB_To[0] = 1'b0;
                      end
                    default :
                      Set_BusB_To = 4'b1001;
                  endcase // case(IR[5:4])
                end // case: 3
 
              default :;
            endcase // case(MCycle)
          end // case: 8'b01001010,8'b01011010,8'b01101010,8'b01111010
 
        8'b01000010,8'b01010010,8'b01100010,8'b01110010  :
          begin
            // SBC HL,ss
            MCycles = 3'b011;
            case (1'b1) // MCycle
              MCycle[1] :
                begin
                  NoRead = 1'b1;
                  ALU_Op = 4'b0011;
                  Read_To_Reg = 1'b1;
                  Save_ALU = 1'b1;
                  Set_BusA_To[2:0] = 3'b101;
                  case (IR[5:4])
                    0,1,2  :
                      begin
                        Set_BusB_To[2:1] = IR[5:4];
                        Set_BusB_To[0] = 1'b1;
                      end
                    default :
                      Set_BusB_To = 4'b1000;
                  endcase
                  TStates = 3'b100;
                end // case: 2
 
              MCycle[2] :
                begin
                  NoRead = 1'b1;
                  ALU_Op = 4'b0011;
                  Read_To_Reg = 1'b1;
                  Save_ALU = 1'b1;
                  Set_BusA_To[2:0] = 3'b100;
                  case (IR[5:4])
                    0,1,2  :
                      Set_BusB_To[2:1] = IR[5:4];
                    default :
                      Set_BusB_To = 4'b1001;
                  endcase
                end // case: 3
 
              default :;
 
            endcase // case(MCycle)
          end // case: 8'b01000010,8'b01010010,8'b01100010,8'b01110010
 
        8'b01101111  :
          begin
            // RLD
            MCycles = 3'b100;
            case (1'b1) // MCycle
              MCycle[1] :
                begin
                  NoRead = 1'b1;
                  Set_Addr_To = aXY;
                end
 
              MCycle[2] :
                begin
                  Read_To_Reg = 1'b1;
                  Set_BusB_To[2:0] = 3'b110;
                  Set_BusA_To[2:0] = 3'b111;
                  ALU_Op = 4'b1101;
                  TStates = 3'b100;
                  Set_Addr_To = aXY;
                  Save_ALU = 1'b1;
                end
 
              MCycle[3] :
                begin
                  I_RLD = 1'b1;
                  Write = 1'b1;
                end
 
              default :;
            endcase // case(MCycle)
          end // case: 8'b01101111
 
        8'b01100111  :
          begin
            // RRD
            MCycles = 3'b100;
            case (1'b1) // MCycle
              MCycle[1] :
                Set_Addr_To = aXY;
              MCycle[2] :
                begin
                  Read_To_Reg = 1'b1;
                  Set_BusB_To[2:0] = 3'b110;
                  Set_BusA_To[2:0] = 3'b111;
                  ALU_Op = 4'b1110;
                  TStates = 3'b100;
                  Set_Addr_To = aXY;
                  Save_ALU = 1'b1;
                end
 
              MCycle[3] :
                begin
                  I_RRD = 1'b1;
                  Write = 1'b1;
                end
 
              default :;
            endcase // case(MCycle)
          end // case: 8'b01100111
 
        8'b01xxx101 :
          begin
            // RETI, RETN
            MCycles = 3'b011;
            case (1'b1) // MCycle
              MCycle[0] :
                Set_Addr_To = aSP;
 
              MCycle[1] :
                begin
                  IncDec_16 = 4'b0111;
                  Set_Addr_To = aSP;
                  LDZ = 1'b1;
                end
 
              MCycle[2] :
                begin
                  Jump = 1'b1;
                  IncDec_16 = 4'b0111;
                  I_RETN = 1'b1;
                end
 
              default :;
            endcase // case(MCycle)
          end // case: 8'b01000101,8'b01001101,8'b01010101,8'b01011101,8'b01100101,8'b01101101,8'b01110101,8'b01111101
 
        8'b01xxx000 :
          begin
            // IN r,(C)
            MCycles = 3'b010;
            case (1'b1) // MCycle
              MCycle[0] :
                Set_Addr_To = aBC;
 
              MCycle[1] :
                begin
                  IORQ = 1'b1;
                  if (IR[5:3] != 3'b110 ) 
                    begin
                      Read_To_Reg = 1'b1;
                      Set_BusA_To[2:0] = IR[5:3];
                    end
                  I_INRC = 1'b1;
                end
 
              default :;
            endcase // case(MCycle)
          end // case: 8'b01000000,8'b01001000,8'b01010000,8'b01011000,8'b01100000,8'b01101000,8'b01110000,8'b01111000
 
        8'b01xxx001 :
          begin
            // OUT (C),r
            // OUT (C),0
            MCycles = 3'b010;
            case (1'b1) // MCycle
              MCycle[0] :
                begin
                  Set_Addr_To = aBC;
                  Set_BusB_To[2:0]        = IR[5:3];
                  if (IR[5:3] == 3'b110 ) 
                    begin
                      Set_BusB_To[3] = 1'b1;
                    end
                end
 
              MCycle[1] :
                begin
                  Write = 1'b1;
                  IORQ = 1'b1;
                end
 
              default :;
            endcase // case(MCycle)
          end // case: 8'b01000001,8'b01001001,8'b01010001,8'b01011001,8'b01100001,8'b01101001,8'b01110001,8'b01111001
 
        8'b10100010 , 8'b10101010 , 8'b10110010 , 8'b10111010  :
          begin
            // INI, IND, INIR, INDR
            MCycles = 3'b100;
            case (1'b1) // MCycle
              MCycle[0] :
                begin
                  Set_Addr_To = aBC;
                  Set_BusB_To = 4'b1010;
                  Set_BusA_To = 4'b0000;
                  Read_To_Reg = 1'b1;
                  Save_ALU = 1'b1;
                  ALU_Op = 4'b0010;
                end
 
              MCycle[1] :
                begin
                  IORQ = 1'b1;
                  Set_BusB_To = 4'b0110;
                  Set_Addr_To = aXY;
                end
 
              MCycle[2] :
                begin
                  if (IR[3] == 1'b0 ) 
                    begin
		      IncDec_16 = 4'b0110;
                    end 
                  else 
                    begin
		      IncDec_16 = 4'b1110;
                    end
                  TStates = 3'b100;
                  Write = 1'b1;
                  I_BTR = 1'b1;
                end // case: 3
 
              MCycle[3] :
                begin
                  NoRead = 1'b1;
                  TStates = 3'b101;
                end
 
              default :;
            endcase // case(MCycle)
          end // case: 8'b10100010 , 8'b10101010 , 8'b10110010 , 8'b10111010
 
        8'b10100011 , 8'b10101011 , 8'b10110011 , 8'b10111011  :
          begin
            // OUTI, OUTD, OTIR, OTDR
            MCycles = 3'b100;
            case (1'b1) // MCycle
              MCycle[0] :
                begin
                  TStates = 3'b101;
                  Set_Addr_To = aXY;
                  Set_BusB_To = 4'b1010;
                  Set_BusA_To = 4'b0000;
                  Read_To_Reg = 1'b1;
                  Save_ALU = 1'b1;
                  ALU_Op = 4'b0010;
                end
 
              MCycle[1] :
                begin
                  Set_BusB_To = 4'b0110;
                  Set_Addr_To = aBC;
                  if (IR[3] == 1'b0 ) 
                    begin
                      IncDec_16 = 4'b0110;
                    end 
                  else 
                    begin
                      IncDec_16 = 4'b1110;
                    end
                end
 
              MCycle[2] :
                begin
                  if (IR[3] == 1'b0 ) 
                    begin
                      IncDec_16 = 4'b0010;
                    end 
                  else 
                    begin
                      IncDec_16 = 4'b1010;
                    end
                  IORQ = 1'b1;
                  Write = 1'b1;
                  I_BTR = 1'b1;
                end // case: 3
 
              MCycle[3] :
                begin
                  NoRead = 1'b1;
                  TStates = 3'b101;
                end
 
              default :;
            endcase // case(MCycle)
          end // case: 8'b10100011 , 8'b10101011 , 8'b10110011 , 8'b10111011
 
        default : ;
 
      endcase // case(IRB)                  
 
    end // always @ (IR, ISet, MCycle, F, NMICycle, IntCycle)
 
  assign                output_vector = { MCycles,
                                          TStates,   
                                          Prefix,   
                                          Inc_PC,    
                                          Inc_WZ,    
                                          IncDec_16,
                                          Read_To_Reg,
                                          Read_To_Acc,
                                          Set_BusA_To,
                                          Set_BusB_To,
                                          ALU_Op,     
                                          Save_ALU,   
                                          PreserveC,  
                                          Arith16,    
                                          Set_Addr_To,
                                          IORQ,       
                                          Jump,       
                                          JumpE,      
                                          JumpXY,     
                                          Call,       
                                          RstP,       
                                          LDZ,        
                                          LDW,        
                                          LDSPHL,     
                                          Special_LD, 
                                          ExchangeDH, 
                                          ExchangeRp, 
                                          ExchangeAF, 
                                          ExchangeRS, 
                                          I_DJNZ,     
                                          I_CPL,      
                                          I_CCF,      
                                          I_SCF,      
                                          I_RETN,     
                                          I_BT,       
                                          I_BC,       
                                          I_BTR,      
                                          I_RLD,      
                                          I_RRD,      
                                          I_INRC,     
                                          SetDI,      
                                          SetEI,      
                                          IMode,      
                                          Halt,       
                                          NoRead,     
                                          Write }; 
 
  // synopsys dc_script_begin
  // set_attribute current_design "revision" "$Id: tv80_mcode_ed.v,v 1.1.2.1 2004-11-30 21:58:10 ghutchis Exp $" -type string -quiet
  // synopsys dc_script_end
endmodule // T80_MCode
 

Go to most recent revision | 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.