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

Subversion Repositories nextz80

[/] [nextz80/] [trunk/] [NextZ80CPU.v] - Diff between revs 13 and 14

Show entire file | Details | Blame | View Log

Rev 13 Rev 14
Line 5... Line 5...
//
//
// Filename: NextZ80CPU.v
// Filename: NextZ80CPU.v
// Description: Implementation of Z80 compatible CPU
// Description: Implementation of Z80 compatible CPU
// Version 1.0
// Version 1.0
// Creation date: 28Jan2011 - 18Mar2011
// Creation date: 28Jan2011 - 18Mar2011
 
// Updated: 04Jan2019 - single file
//
//
// Author: Nicolae Dumitrache 
// Author: Nicolae Dumitrache 
// e-mail: ndumitrache@opencores.org
// e-mail: ndumitrache@opencores.org
//
//
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
Line 37... Line 38...
// from http://www.opencores.org/lgpl.shtml 
// from http://www.opencores.org/lgpl.shtml 
// 
// 
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
//
//
// Comments:
// Comments:
// This project was developed and tested on a XILINX Spartan3AN board.
 
//
//
//      NextZ80 processor features:
//      NextZ80 processor features:
//              All documented/undocumented intstructions are implemented
//              All documented/undocumented intstructions are implemented
//              All documented/undocumented flags are implemented
//              All documented/undocumented flags are implemented
//              All (doc/undoc)flags are changed accordingly by all (doc/undoc)instructions. 
//              All (doc/undoc)flags are changed accordingly by all (doc/undoc)instructions. 
Line 51... Line 51...
//              R register available
//              R register available
//              Fast conditional jump/call/ret takes only 1 T state if not executed
//              Fast conditional jump/call/ret takes only 1 T state if not executed
//              Fast block instructions: LDxR - 3 T states/byte, INxR/OTxR - 2 T states/byte, CPxR - 4 T states / byte
//              Fast block instructions: LDxR - 3 T states/byte, INxR/OTxR - 2 T states/byte, CPxR - 4 T states / byte
//              Each CPU machine cycle takes (mainly) one clock T state. This makes this processor over 4 times faster than a Z80 at the same 
//              Each CPU machine cycle takes (mainly) one clock T state. This makes this processor over 4 times faster than a Z80 at the same 
//                      clock frequency (some instructions are up to 10 times faster). 
//                      clock frequency (some instructions are up to 10 times faster). 
//              Works at ~40MHZ on Spartan XC3S700AN speed grade -4)
//              Up to 70MHZ on Spartan6 speed grade -2, ~800 LUT6
//              Small size ( ~12%  ~700 slices - on Spartan XC3S700AN )
 
//              Tested with ZEXDOC (fully compliant).
//              Tested with ZEXDOC (fully compliant).
//              Tested with ZEXALL (all OK except CPx(R), LDx(R), BIT n, (IX/IY+d), BIT n, (HL) - fail because of the un-documented XF and YF flags).
//              Tested with ZEXALL (all OK except CPx(R), LDx(R), BIT n, (IX/IY+d), BIT n, (HL) - fail because of the un-documented XF and YF flags).
// 
// 
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
`timescale 1ns / 1ps
`timescale 1ns / 1ps
 
 
module NextZ80
module NextZ80
(
(
                input wire[7:0] DI,
                input   [7:0]DI,
                output wire[7:0] DO,
                input CLK,
                output wire[15:0] ADDR,
                input RESET,
 
                input INT,
 
                input NMI,
 
                input   WAIT,
 
 
 
                output [7:0]DO,
 
                output [15:0]ADDR,
                output reg WR,
                output reg WR,
                output reg MREQ,
                output reg MREQ,
                output reg IORQ,
                output reg IORQ,
                output reg HALT,
                output reg HALT,
                output reg M1,
                output reg M1
                input wire CLK,
 
                input wire RESET,
 
                input wire INT,
 
                input wire NMI,
 
                input   wire WAIT
 
);
);
 
 
// connections and registers
// connections and registers
        reg     [9:0] CPUStatus = 0;      // 0=AF-AF', 1=HL-HL', 2=DE-HL, 3=DE'-HL', 4=HL-X, 5=IX-IY, 6=IFF1,7=IFF2, 9:8=IMODE
        reg     [9:0] CPUStatus = 0;      // 0=AF-AF', 1=HL-HL', 2=DE-HL, 3=DE'-HL', 4=HL-X, 5=IX-IY, 6=IFF1,7=IFF2, 9:8=IMODE
        wire    [7:0] ALU8FLAGS;
        wire    [7:0] ALU8FLAGS;
Line 121... Line 121...
                 .M1(M1),
                 .M1(M1),
                 .WE(WE),
                 .WE(WE),
                 .CLK(CLK),
                 .CLK(CLK),
                 .ALU8OUT(ALU8OUT),
                 .ALU8OUT(ALU8OUT),
                 .DI(DI),
                 .DI(DI),
                 .DO(DO),
 
                 .ADDR(ADDR),
                 .ADDR(ADDR),
                 .CONST(FETCH[7] ? {2'b00, FETCH[5:3], 3'b000} : 8'h66),        // RST/NMI address
                 .CONST(FETCH[7] ? {2'b00, FETCH[5:3], 3'b000} : 8'h66),        // RST/NMI address
                 .ALU80(ALU80),
 
                 .ALU81(ALU81),
 
                 .ALU160(ALU160),
 
                 .ALU161(ALU161),
 
                 .ALU8FLAGS(ALU8FLAGS),
                 .ALU8FLAGS(ALU8FLAGS),
                 .FLAGS(FLAGS),
 
                 .DO_SEL(DO_SEL),
                 .DO_SEL(DO_SEL),
                 .ALU160_sel(ALU160_SEL),
                 .ALU160_sel(ALU160_SEL),
                 .REG_WSEL(REG_WSEL),
                 .REG_WSEL(REG_WSEL),
                 .REG_RSEL(REG_RSEL),
                 .REG_RSEL(REG_RSEL),
                 .DINW_SEL(DINW_SEL),
                 .DINW_SEL(DINW_SEL),
                 .XMASK(xmask),
                 .XMASK(xmask),
                 .ALU16OP(ALU16OP),                     // used for post increment for ADDR, SP mux re-direct
                 .ALU16OP(ALU16OP),                     // used for post increment for ADDR, SP mux re-direct
                 .WAIT(WAIT)
                 .WAIT(WAIT),
 
 
 
                 .DO(DO),
 
                 .ALU80(ALU80),
 
                 .ALU81(ALU81),
 
                 .ALU160(ALU160),
 
                 .ALU161(ALU161),
 
                 .FLAGS(FLAGS)
                 );
                 );
 
 
        ALU8 CPU_ALU8 (
        ALU8 CPU_ALU8 (
                 .D0(ALU80),
                 .D0(ALU80),
                 .D1(ALU81),
                 .D1(ALU81),
                 .FIN(FLAGS),
                 .FIN(FLAGS),
                 .FOUT(ALU8FLAGS),
 
                 .ALU8DOUT(ALU8OUT),
 
                 .OP(ALU8OP),
                 .OP(ALU8OP),
                 .EXOP(FETCH[8:3]),
                 .EXOP(FETCH[8:3]),
                 .LDIFLAGS(REG_WSEL[2]),        // inc16 HL
                 .LDIFLAGS(REG_WSEL[2]),        // inc16 HL
                 .DSTHI(!REG_WSEL[0])
                 .DSTHI(!REG_WSEL[0]),
 
 
 
                 .FOUT(ALU8FLAGS),
 
                 .ALU8DOUT(ALU8OUT)
                 );
                 );
 
 
        ALU16 CPU_ALU16 (
        ALU16 CPU_ALU16 (
                 .D0(ALU160),
                 .D0(ALU160),
                 .D1(ALU161),
                 .D1(ALU161),
                 .DOUT(ADDR),
                 .OP(ALU16OP),
                 .OP(ALU16OP)
 
 
                 .DOUT(ADDR)
                 );
                 );
 
 
        always @(posedge CLK)
        always @(posedge CLK)
                if(!WAIT) begin
                if(!WAIT) begin
                        SRESET <= RESET;
                        SRESET <= RESET;
Line 1496... Line 1499...
                endcase
                endcase
        end
        end
 
 
endmodule
endmodule
 
 
 No newline at end of file
 No newline at end of file
 
module Z80Reg(
 
        input [7:0]rstatus,      // 0=af-af', 1=exx, 2=hl-de, 3=hl'-de',4=hl-ixy, 5=ix-iy, 6=IFF1, 7=IFF2
 
        input M1,
 
        input [5:0]WE,                   // 5 = flags, 4 = PC, 3 = SP, 2 = tmpHI, 1 = hi, 0 = lo
 
        input CLK,
 
        input [15:0]ALU8OUT,     // CPU data out bus (output of alu8)
 
        input [7:0]DI,                   // CPU data in bus
 
        input [15:0]ADDR,                // CPU addr bus
 
        input [7:0]CONST,
 
        input [7:0]ALU8FLAGS,
 
        input [1:0]DO_SEL,       // select DO betwen ALU8OUT lo and th register
 
        input ALU160_sel,               // 0=REG_RSEL, 1=PC
 
        input [3:0]REG_WSEL,     // rdow:        [3:1] 0=BC, 1=DE, 2=HL, 3=A-TL, 4=I-x  ----- [0] = 0HI,1LO
 
        input [3:0]REG_RSEL,     // mux_rdor:   [3:1] 0=BC, 1=DE, 2=HL, 3=A-TL, 4=I-R, 5=SP, 7=tmpSP   ----- [0] = 0HI, 1LO
 
        input DINW_SEL,         // select RAM write data between (0)ALU8OUT, and 1(DI)
 
        input XMASK,                    // 0 if REG_WSEL should not use IX, IY, even if rstatus[4] == 1
 
        input [2:0]ALU16OP,      // ALU16OP
 
        input WAIT,                             // wait
 
 
 
        output reg [7:0]DO,                      // CPU data out bus
 
        output reg [7:0]ALU80,
 
        output reg [7:0]ALU81,
 
        output reg [15:0]ALU160,
 
        output [7:0]ALU161,
 
        output [7:0]FLAGS
 
        );
 
 
 
// latch registers
 
        reg [15:0]pc=0;                           // program counter
 
        reg [15:0]sp;                                    // stack pointer
 
        reg [7:0]r;                                              // refresh
 
        reg [15:0]flg = 0;
 
        reg [7:0]th;                                     // temp high
 
 
 
// internal wires       
 
        wire [15:0]rdor;         // R out from RAM
 
        wire [15:0]rdow;         // W out from RAM
 
        wire [3:0]SELW;          // RAM W port sel
 
        wire [3:0]SELR;          // RAM R port sel
 
        reg  [15:0]DIN;          // RAM W in data
 
        reg [15:0]mux_rdor;      // (3)A reversed mixed with TL, (4)I mixed with R (5)SP
 
 
 
//------------------------------------ RAM block registers ----------------------------------
 
// 0:BC, 1:DE, 2:HL, 3:A-x, 4:I-x, 5:IX, 6:IY, 7:x-x, 8:BC', 9:DE', 10:HL', 11:A'-x, 12: tmpSP, 13:zero
 
   RAM16X8D_regs regs_lo
 
        (
 
      .A(SELW),          // R/W address
 
      .D(DIN[7:0]),      // Write data input
 
      .DPRA(SELR),               // Read-only address
 
      .WCLK(CLK),                // Write clock input
 
      .WE(WE[0] & !WAIT),// Write enable input
 
 
 
      .DPO(rdor[7:0]),   // Read-only data output
 
      .SPO(rdow[7:0])    // R/W data output
 
   );
 
 
 
   RAM16X8D_regs regs_hi
 
        (
 
      .A(SELW),          // R/W address
 
      .D(DIN[15:8]),     // Write data input
 
      .DPRA(SELR),               // Read-only address
 
      .WCLK(CLK),                // Write clock input
 
      .WE(WE[1] & !WAIT),// Write enable input
 
 
 
      .DPO(rdor[15:8]),  // Read-only data output
 
      .SPO(rdow[15:8])   // R/W data output
 
   );
 
 
 
        wire [15:0]ADDR1 = ADDR + !ALU16OP[2]; // address post increment
 
        wire [7:0]flgmux = {ALU8FLAGS[7:3], SELR[3:0] == 4'b0100 ? rstatus[7] : ALU8FLAGS[2], ALU8FLAGS[1:0]}; // LD A, I/R IFF2 flag on parity
 
        always @(posedge CLK)
 
                if(!WAIT) begin
 
                        if(WE[2]) th <= DI;
 
                        if(WE[3]) sp <= ADDR1;
 
                        if(WE[4]) pc <= ADDR1;
 
                        if({REG_WSEL, WE[0]} == 5'b10011) r <= ALU8OUT[7:0];
 
                        else if(M1) r[6:0] <= r[6:0] + 1;
 
                        if(WE[5])
 
                                if(rstatus[0]) flg[15:8] <= flgmux;
 
                                else flg[7:0] <= flgmux;
 
                end
 
 
 
        assign ALU161 = th;
 
        assign FLAGS = rstatus[0] ? flg[15:8] : flg[7:0];
 
 
 
        always @* begin
 
                DIN = DINW_SEL ? {DI, DI} : ALU8OUT;
 
                ALU80 = REG_WSEL[0] ? rdow[7:0] : rdow[15:8];
 
                ALU81 = REG_RSEL[0] ? mux_rdor[7:0] : mux_rdor[15:8];
 
                ALU160 = ALU160_sel ? pc : mux_rdor;
 
 
 
                case({REG_WSEL[3], DO_SEL})
 
                        0:       DO = ALU80;
 
                        1:      DO = th;
 
                        2: DO = FLAGS;
 
                        3: DO = ALU8OUT[7:0];
 
                        4: DO = pc[15:8];
 
                        5: DO = pc[7:0];
 
                        6:      DO = sp[15:8];
 
                        7: DO = sp[7:0];
 
                endcase
 
                case({ALU16OP == 4, REG_RSEL[3:0]})
 
                        5'b01001, 5'b11001:                                                             mux_rdor = {rdor[15:8], r};
 
                        5'b01010, 5'b01011:                                                             mux_rdor = sp;
 
                        5'b01100, 5'b01101, 5'b11100, 5'b11101: mux_rdor = {8'b0, CONST};
 
                        default:                mux_rdor = rdor;
 
                endcase
 
        end
 
 
 
        RegSelect WSelectW
 
        (
 
                .SEL(REG_WSEL[3:1]),
 
                .rstatus({rstatus[5], rstatus[4] & XMASK, rstatus[3:0]}),
 
 
 
                .RAMSEL(SELW)
 
        );
 
 
 
        RegSelect WSelectR
 
        (
 
                .SEL(REG_RSEL[3:1]),
 
                .rstatus(rstatus[5:0]),
 
 
 
                .RAMSEL(SELR)
 
        );
 
 
 
endmodule
 
 
 
 
 
module RegSelect(
 
        input [2:0]SEL,
 
        input [5:0]rstatus,                      // 0=af-af', 1=exx, 2=hl-de, 3=hl'-de',4=hl-ixy, 5=ix-iy
 
 
 
        output reg [3:0]RAMSEL
 
        );
 
 
 
        always @* begin
 
                RAMSEL = 4'bxxxx;
 
                case(SEL)
 
                        0: RAMSEL = {rstatus[1], 3'b000};        // BC
 
                        1:  //DE
 
                                if(rstatus[{1'b1, rstatus[1]}]) RAMSEL = {rstatus[1], 3'b010};          //      HL
 
                                else RAMSEL = {rstatus[1], 3'b001};                             // DE
 
                        2:      // HL
 
                                case({rstatus[5:4], rstatus[{1'b1, rstatus[1]}]})
 
                                        0,4:     RAMSEL = {rstatus[1], 3'b010};          // HL
 
                                        1,5:    RAMSEL = {rstatus[1], 3'b001};          // DE
 
                                        2,3:    RAMSEL = 4'b0101;       //      IX
 
                                        6,7:    RAMSEL = 4'b0110;               // IY
 
                                endcase
 
                        3: RAMSEL = {rstatus[0], 3'b011}; // A-TL
 
                        4:      RAMSEL = 4; // I-R
 
                        5: RAMSEL = 12; // tmp SP
 
                        6: RAMSEL = 13; // zero
 
                        7: RAMSEL = 7;  // temp reg for BIT/SET/RES
 
                endcase
 
        end
 
endmodule
 
 
 
module RAM16X8D_regs(
 
      input [3:0]A,              // R/W address 
 
      input [7:0]D,        // Write data input
 
      input [3:0]DPRA,           // Read-only address
 
      input WCLK,                       // Write clock
 
      input WE,                 // Write enable
 
 
 
      output [7:0]DPO,     // Read-only data output
 
      output [7:0]SPO      // R/W data output
 
   );
 
 
 
        reg [7:0]data[15:0];
 
        assign DPO = data[DPRA];
 
        assign SPO = data[A];
 
 
 
        always @(posedge WCLK)
 
                if(WE) data[A] <= D;
 
 
 
endmodule
 
 
 
//FLAGS: S Z X1 N X2 PV N C
 
//      OP[4:0]
 
//      00000   -       ADD     D0,D1
 
//      00001   -       ADC     D0,D1
 
//      00010   -       SUB     D0,D1
 
//      00011   -       SBC     D0,D1
 
//      00100   -       AND     D0,D1
 
//      00101   -       XOR     D0,D1
 
//      00110   -       OR              D0,D1
 
//      00111   -       CP              D0,D1
 
//      01000   -       INC     D0
 
//      01001   -       CPL     D0
 
// 01010        -       DEC     D0
 
//      01011   -       RRD
 
// 01100        -       RLD
 
//      01101   -       DAA
 
//      01110   -       INC16
 
//      01111   -  DEC16
 
// 10000        -       ADD16LO
 
//      10001   -       ADD16HI
 
//      10010   -       
 
//      10011   -       
 
//      10100   -       CCF, pass D0
 
// 10101        -       SCF, pass D0
 
// 10110        -       
 
//      10111   -       
 
//      11000   -       RLCA    D0
 
//      11001   -       RRCA    D0
 
//      11010   -       RLA     D0
 
//      11011   -       RRA     D0
 
//      11100   -       {ROT, BIT, SET, RES} D0,EXOP 
 
//                                RLC           D0                      C <-- D0 <-- D0[7]
 
//            RRC               D0                      D0[0] --> D0 --> C
 
//            RL                D0                      C <-- D0 <-- C
 
//            RR                D0                      C --> D0 --> C
 
//            SLA               D0                      C <-- D0 <-- 0
 
//            SRA               D0                      D0[7] --> D0 --> C
 
//            SLL               D0                      C <-- D0 <-- 1
 
//            SRL               D0                      0 --> D0 --> C
 
//      11101   -       IN, pass D1
 
//      11110   -       FLAGS <- D0
 
//      11111   -       NEG     D1      
 
///////////////////////////////////////////////////////////////////////////////////
 
module ALU8(
 
    input [7:0] D0,
 
    input [7:0] D1,
 
         input [7:0] FIN,
 
    input [4:0] OP,
 
         input [5:0] EXOP, // EXOP[5:4] = 2'b11 for CPI/D/R
 
         input LDIFLAGS,         // zero HF and NF on inc/dec16
 
         input DSTHI,            // destination lo
 
 
 
    output reg[7:0] FOUT,
 
    output reg [15:0] ALU8DOUT
 
    );
 
 
 
        wire [7:0] daaadjust;
 
        wire cdaa, hdaa;
 
 
 
        daa daa_adjust
 
        (
 
                .flags(FIN),
 
                .val(D0),
 
 
 
                .adjust(daaadjust),
 
                .cdaa(cdaa),
 
                .hdaa(hdaa)
 
        );
 
 
 
        wire parity = ~^ALU8DOUT[15:8];
 
        wire zero = ALU8DOUT[15:8] == 0;
 
        reg csin, cin;
 
        wire [7:0]d0mux = OP[4:1] == 4'b1111 ? 0 : D0;
 
        reg [7:0]_d1mux;
 
        wire [7:0]d1mux = OP[1] ? ~_d1mux : _d1mux;
 
        wire [8:0]sum;
 
        wire hf;
 
        assign {hf, sum[3:0]} = d0mux[3:0] + d1mux[3:0] + cin;
 
        assign sum[8:4] = d0mux[7:4] + d1mux[7:4] + hf;
 
        wire overflow = (d0mux[7] & d1mux[7] & !sum[7]) | (!d0mux[7] & !d1mux[7] & sum[7]);
 
        reg [7:0]dbit;
 
 
 
        always @* begin
 
                ALU8DOUT = 16'hxxxx;
 
                FOUT = 8'hxx;
 
                case({OP[4:2]})
 
                        0,1,4,7: _d1mux = D1;
 
                        2: _d1mux = 1;
 
                        3: _d1mux = daaadjust;          // DAA
 
                        6,5: _d1mux = 8'hxx;
 
                endcase
 
                case({OP[2:0], FIN[0]})
 
                        0,1,2,7,8,9,10,11,12,13: cin = 0;
 
                        3,4,5,6,14,15: cin = 1;
 
                endcase
 
                case(EXOP[3:0])
 
                        0: dbit =  8'b11111110;
 
                        1: dbit =  8'b11111101;
 
                        2: dbit =  8'b11111011;
 
                        3: dbit =  8'b11110111;
 
                        4: dbit =  8'b11101111;
 
                        5: dbit =  8'b11011111;
 
                        6: dbit =  8'b10111111;
 
                        7: dbit =  8'b01111111;
 
                        8: dbit =  8'b00000001;
 
                        9: dbit =  8'b00000010;
 
                        10: dbit = 8'b00000100;
 
                        11: dbit = 8'b00001000;
 
                        12: dbit = 8'b00010000;
 
                        13: dbit = 8'b00100000;
 
                        14: dbit = 8'b01000000;
 
                        15: dbit = 8'b10000000;
 
                endcase
 
                case(OP[3] ? EXOP[2:0] : OP[2:0])
 
                        0,5:     csin = D0[7];
 
                        1:      csin = D0[0];
 
                        2,3:    csin = FIN[0];
 
                        4,7:    csin = 0;
 
                        6:              csin = 1;
 
                endcase
 
                case(OP[4:0])
 
                        0,1,2,3,8,10:    begin           // ADD, ADC, SUB, SBC, INC, DEC
 
                                ALU8DOUT[15:8] = sum[7:0];
 
                                ALU8DOUT[7:0] = sum[7:0];
 
                                FOUT[0] = OP[3] ? FIN[0] : (sum[8] ^ OP[1]); // inc/dec
 
                                FOUT[1] = OP[1];
 
                                FOUT[2] = overflow;
 
                                FOUT[3] = ALU8DOUT[11];
 
                                FOUT[4] = hf ^ OP[1];
 
                                FOUT[5] = ALU8DOUT[13];
 
                                FOUT[6] = zero & (FIN[6] | ~EXOP[5] | ~DSTHI | OP[3]); //(EXOP[5] & DSTHI) ? (zero & FIN[6]) : zero;                            // adc16/sbc16
 
                                FOUT[7] = ALU8DOUT[15];
 
                        end
 
                        16,17:  begin           // ADD16LO, ADD16HI
 
                                ALU8DOUT[15:8] = sum[7:0];
 
                                ALU8DOUT[7:0] = sum[7:0];
 
                                FOUT[0] = sum[8];
 
                                FOUT[1] = OP[1];
 
                                FOUT[2] = FIN[2];
 
                                FOUT[3] = ALU8DOUT[11];
 
                                FOUT[4] = hf ^ OP[1];
 
                                FOUT[5] = ALU8DOUT[13];
 
                                FOUT[6] = FIN[6];
 
                                FOUT[7] = FIN[7];
 
                        end
 
                        7: begin                // CP
 
                                ALU8DOUT[15:8] = sum[7:0];
 
                                FOUT[0] = EXOP[5] ? FIN[0] : !sum[8]; // CPI/D/R
 
                                FOUT[1] = OP[1];
 
                                FOUT[2] = overflow;
 
                                FOUT[3] = D1[3];
 
                                FOUT[4] = !hf;
 
                                FOUT[5] = D1[5];
 
                                FOUT[6] = zero;
 
                                FOUT[7] = ALU8DOUT[15];
 
                        end
 
                        31:     begin           // NEG
 
                                ALU8DOUT[15:8] = sum[7:0];
 
                                FOUT[0] = !sum[8];
 
                                FOUT[1] = OP[1];
 
                                FOUT[2] = overflow;
 
                                FOUT[3] = ALU8DOUT[11];
 
                                FOUT[4] = !hf;
 
                                FOUT[5] = ALU8DOUT[13];
 
                                FOUT[6] = zero;
 
                                FOUT[7] = ALU8DOUT[15];
 
                        end
 
                        4: begin                        // AND
 
                                ALU8DOUT[15:8] = D0 & D1;
 
                                FOUT[0] = 0;
 
                                FOUT[1] = 0;
 
                                FOUT[2] = parity;
 
                                FOUT[3] = ALU8DOUT[11];
 
                                FOUT[4] = 1;
 
                                FOUT[5] = ALU8DOUT[13];
 
                                FOUT[6] = zero;
 
                                FOUT[7] = ALU8DOUT[15];
 
                        end
 
                        5,6: begin              //XOR, OR
 
                                ALU8DOUT[15:8] = OP[0] ? (D0 ^ D1) : (D0 | D1);
 
                                FOUT[0] = 0;
 
                                FOUT[1] = 0;
 
                                FOUT[2] = parity;
 
                                FOUT[3] = ALU8DOUT[11];
 
                                FOUT[4] = 0;
 
                                FOUT[5] = ALU8DOUT[13];
 
                                FOUT[6] = zero;
 
                                FOUT[7] = ALU8DOUT[15];
 
                        end
 
                        9: begin                        // CPL
 
                                ALU8DOUT[15:8] = ~D0;
 
                                FOUT[0] = FIN[0];
 
                                FOUT[1] = 1;
 
                                FOUT[2] = FIN[2];
 
                                FOUT[3] = ALU8DOUT[11];
 
                                FOUT[4] = 1;
 
                                FOUT[5] = ALU8DOUT[13];
 
                                FOUT[7:6] = FIN[7:6];
 
                        end
 
                        11,12: begin                                    // RLD, RRD
 
                                if(OP[0]) ALU8DOUT = {D0[7:4], D1[3:0], D0[3:0], D1[7:4]};
 
                                else ALU8DOUT = {D0[7:4], D1[7:0], D0[3:0]};
 
                                FOUT[0] = FIN[0];
 
                                FOUT[1] = 0;
 
                                FOUT[2] = parity;
 
                                FOUT[3] = ALU8DOUT[11];
 
                                FOUT[4] = 0;
 
                                FOUT[5] = ALU8DOUT[13];
 
                                FOUT[6] = zero;
 
                                FOUT[7] = ALU8DOUT[15];
 
                        end
 
                        13: begin       // DAA
 
                                ALU8DOUT[15:8] = sum[7:0];
 
                                FOUT[0] = cdaa;
 
                                FOUT[1] = FIN[1];
 
                                FOUT[2] = parity;
 
                                FOUT[3] = ALU8DOUT[11];
 
                                FOUT[4] = hdaa;
 
                                FOUT[5] = ALU8DOUT[13];
 
                                FOUT[6] = zero;
 
                                FOUT[7] = ALU8DOUT[15];
 
                        end
 
                        14,15: begin    // inc/dec 16
 
                                ALU8DOUT = {D0, D1} + (OP[0] ? 16'hffff : 16'h0001);
 
                                FOUT[0] = FIN[0];
 
                                FOUT[1] = LDIFLAGS ? 1'b0 : FIN[1];
 
                                FOUT[2] = ALU8DOUT != 0;
 
                                FOUT[3] = FIN[3];
 
                                FOUT[4] = LDIFLAGS ? 1'b0 : FIN[4];
 
                                FOUT[5] = FIN[5];
 
                                FOUT[6] = FIN[6];
 
                                FOUT[7] = FIN[7];
 
                        end
 
                        20,21: begin            // CCF, SCF
 
                                ALU8DOUT[15:8] = D0;
 
                                FOUT[0] = OP[0] ? 1'b1 : !FIN[0];
 
                                FOUT[1] = 1'b0;
 
                                FOUT[2] = FIN[2];
 
                                FOUT[3] = ALU8DOUT[11];
 
                                FOUT[4] = OP[0] ? 1'b0 : FIN[0];
 
                                FOUT[5] = ALU8DOUT[13];
 
                                FOUT[6] = FIN[6];
 
                                FOUT[7] = FIN[7];
 
                        end
 
                        24,25,26,27, 28: begin                                                  // ROT, BIT, RES, SET
 
                                case({OP[2], EXOP[4:3]})
 
                                        0,1,2,3,4:       // rot - shift
 
                                                if(OP[2] ? EXOP[0] : OP[0]){ALU8DOUT[15:8], FOUT[0]} = {csin, D0};         // right
 
                                                else                                                            {FOUT[0], ALU8DOUT[15:8]} = {D0, csin};          // left
 
                                        5,6: begin      // BIT, RES 
 
                                                FOUT[0] = FIN[0];
 
                                                ALU8DOUT[15:8] = D0 & dbit;
 
                                        end
 
                                        7: begin        // SET
 
                                                FOUT[0] = FIN[0];
 
                                                ALU8DOUT[15:8] = D0 | dbit;
 
                                        end
 
                                endcase
 
                                ALU8DOUT[7:0] = ALU8DOUT[15:8];
 
                                FOUT[1] = 0;
 
                                FOUT[2] = OP[2] ? (EXOP[3] ? zero : parity) : FIN[2];
 
                                FOUT[3] = ALU8DOUT[11];
 
                                FOUT[4] = OP[2] & EXOP[3];
 
                                FOUT[5] = ALU8DOUT[13];
 
                                FOUT[6] = OP[2] ? zero : FIN[6];
 
                                FOUT[7] = OP[2] ? ALU8DOUT[15] : FIN[7];
 
                        end
 
                        29:     begin           // IN, pass D1
 
                                ALU8DOUT = {D1, D1};
 
                                FOUT[0] = FIN[0];
 
                                FOUT[1] = 0;
 
                                FOUT[2] = parity;
 
                                FOUT[3] = ALU8DOUT[11];
 
                                FOUT[4] = 0;
 
                                FOUT[5] = ALU8DOUT[13];
 
                                FOUT[6] = zero;
 
                                FOUT[7] = ALU8DOUT[15];
 
                        end
 
                        30: FOUT = D0;          // FLAGS <- D0
 
                        default:;
 
                endcase
 
        end
 
endmodule
 
 
 
module daa (
 
        input [7:0]flags,
 
        input [7:0]val,
 
 
 
        output [7:0]adjust,
 
        output reg cdaa,
 
        output reg hdaa
 
        );
 
 
 
        wire h08 = val[7:4] < 9;
 
        wire h09 = val[7:4] < 10;
 
        wire l05 = val[3:0] < 6;
 
        wire l09 = val[3:0] < 10;
 
        reg [1:0]aa;
 
        assign adjust = ({1'b0, aa[1], aa[1], 2'b0, aa[0], aa[0], 1'b0} ^ {8{flags[1]}}) + flags[1];
 
 
 
        always @* begin
 
                case({flags[0], h08, h09, flags[4], l09})
 
                        5'b00101, 5'b01101:     aa = 0;
 
                        5'b00111, 5'b01111, 5'b01000, 5'b01010, 5'b01100, 5'b01110:     aa = 1;
 
                        5'b00001, 5'b01001, 5'b10001, 5'b10101, 5'b11001, 5'b11101:     aa = 2;
 
                        default: aa = 3;
 
                endcase
 
                case({flags[0], h08, h09, l09})
 
                        4'b0011, 4'b0111, 4'b0100, 4'b0110:     cdaa = 0;
 
                        default: cdaa = 1;
 
                endcase
 
                case({flags[1], flags[4], l05, l09})
 
                        4'b0000, 4'b0010, 4'b0100, 4'b0110, 4'b1110, 4'b1111:   hdaa = 1;
 
                        default:        hdaa = 0;
 
                endcase
 
        end
 
endmodule
 
 
 
 
 
module ALU16(
 
    input [15:0]D0,
 
    input [7:0]D1,
 
    input [2:0]OP,       // 0-NOP, 1-INC, 2-INC2, 3-ADD, 4-NOP, 5-DEC, 6-DEC2
 
 
 
    output [15:0]DOUT
 
    );
 
 
 
        reg [7:0] mux;
 
        always @*
 
                case(OP)
 
                        0: mux = 8'h00;  // post inc
 
                        1: mux = 8'h01; // post inc
 
                        2: mux = 8'h02; // post inc
 
                        3: mux = D1;            // post inc
 
                        4: mux = 8'h00; // no post inc                  
 
                        5: mux = 8'hff; // no post inc
 
                        6: mux = 8'hfe; // no post inc
 
                        default: mux = 8'hxx;
 
                endcase
 
 
 
        assign DOUT = D0 + {{8{mux[7]}}, mux};
 
endmodule
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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