diff --git a/ALU.v b/ALU.v index aae6a2a..f3678d6 100755 --- a/ALU.v +++ b/ALU.v @@ -17,7 +17,7 @@ * */ -module ALU( clk, op, right, AI, BI, CI, CO, BCD, OUT, V, Z, N, HC ); +module ALU( clk, op, right, AI, BI, CI, CO, BCD, OUT, V, Z, N, HC, RDY ); input clk; input right; input [3:0] op; // operation @@ -31,6 +31,7 @@ module ALU( clk, op, right, AI, BI, CI, CO, BCD, OUT, V, Z, N, HC ); output Z; output N; output HC; + input RDY; reg [7:0] OUT; reg CO; @@ -89,13 +90,14 @@ always @* begin end // calculate the flags -always @(posedge clk) begin +always @(posedge clk) + if( RDY ) begin OUT <= temp[7:0]; CO <= temp[8] | CO9; Z <= ~|temp[7:0]; N <= temp[7]; V <= AI[7] ^ BI[7] ^ temp[7] ^ temp[8]; HC <= temp_HC; -end + end endmodule diff --git a/cpu.v b/cpu.v index 1a57a50..23cc3f9 100644 --- a/cpu.v +++ b/cpu.v @@ -18,7 +18,7 @@ * on the output pads if external memory is required. */ -module cpu( clk, reset, AB, DI, DO, WE, IRQ, NMI ); +module cpu( clk, reset, AB, DI, DO, WE, IRQ, NMI, RDY ); input clk; // CPU clock input reset; // reset signal @@ -28,6 +28,7 @@ output [7:0] DO; // data out, write bus output WE; // write enable input IRQ; // interrupt request input NMI; // non-maskable interrupt request +input RDY; // Ready signal. Pauses CPU when RDY=0 /* * internal signals @@ -38,6 +39,10 @@ reg [7:0] ABL; // Address Bus Register LSB reg [7:0] ABH; // Address Bus Register MSB wire [7:0] ADD; // Adder Hold Register (registered in ALU) +reg [7:0] DIHOLD; // Hold for Data In +reg DIHOLD_valid; // +wire [7:0] DIMUX; // + reg [7:0] IRHOLD; // Hold for Instruction register reg IRHOLD_valid; // Valid instruction in IRHOLD @@ -88,9 +93,7 @@ wire [7:0] Y = AXYS[SEL_Y]; // Y register wire [7:0] S = AXYS[SEL_S]; // Stack pointer `endif -wire B = ~(IRQ | NMI_edge); - -wire [7:0] P = { N, V, 1'b1, B, D, I, Z, C }; +wire [7:0] P = { N, V, 2'b0, D, I, Z, C }; /* * instruction decoder/sequencer @@ -279,8 +282,8 @@ always @* JMPI1: statename <= "JMPI1"; endcase -always @( PC ) - $display( "PC:%04x A:%02x X:%02x Y:%02x S:%02x C:%d Z:%d V:%d N:%d", PC, A, X, Y, S, C, Z, V, N ); +//always @( PC ) + //$display( "%t, PC:%04x A:%02x X:%02x Y:%02x S:%02x C:%d Z:%d V:%d N:%d", $time, PC, A, X, Y, S, C, Z, V, N ); `endif @@ -302,7 +305,7 @@ always @* JMPI1, JSR3, RTS3, - RTI4: PC_temp = { DI, ADD }; + RTI4: PC_temp = { DIMUX, ADD }; BRA1: PC_temp = { ABH, ADD }; @@ -344,7 +347,8 @@ always @* * Set new PC */ always @(posedge clk) - PC <= PC_temp + PC_inc; + if( RDY ) + PC <= PC_temp + PC_inc; /* * Address Generator @@ -362,7 +366,7 @@ always @* JMP1, JMPI1, RTI4, - ABS1: AB <= { DI, ADD }; + ABS1: AB <= { DIMUX, ADD }; BRA2, INDY3, @@ -392,7 +396,7 @@ always @* INDX2: AB <= { ZEROPAGE, ADD }; ZP0, - INDY0: AB <= { ZEROPAGE, DI }; + INDY0: AB <= { ZEROPAGE, DIMUX }; REG, READ, @@ -426,7 +430,7 @@ always @* PUSH1: DO <= php ? P : ADD; - BRK2: DO <= P; + BRK2: DO <= (IRQ | NMI_edge) ? P : P | 8'b0001_0000; default: DO <= regfile; endcase @@ -522,8 +526,8 @@ end * the ALU during those cycles. */ always @(posedge clk) - if( write_register ) - AXYS[regsel] <= (state == JSR0) ? DI : { ADD[7:4] + ADJH, ADD[3:0] + ADJL }; + if( write_register & RDY ) + AXYS[regsel] <= (state == JSR0) ? DIMUX : { ADD[7:4] + ADJH, ADD[3:0] + ADJL }; /* * register select logic. This determines which of the A, X, Y or @@ -571,7 +575,8 @@ ALU ALU( .clk(clk), .V(AV), .Z(AZ), .N(AN), - .HC(HC) ); + .HC(HC), + .RDY(RDY) ); /* * Select current ALU operation @@ -586,6 +591,9 @@ always @* FETCH, REG : alu_op <= op; + DECODE, + ABS1: alu_op <= 1'bx; + PUSH1, BRK0, BRK1, @@ -611,7 +619,8 @@ always @* */ always @(posedge clk) - backwards <= DI[7]; + if( RDY ) + backwards <= DIMUX[7]; /* * ALU A Input MUX @@ -642,12 +651,15 @@ always @* PUSH1: AI <= regfile; BRA0, - READ: AI <= DI; + READ: AI <= DIMUX; BRA1: AI <= ABH; // don't use PCH in case we're FETCH: AI <= load_only ? 0 : regfile; + DECODE, + ABS1: AI <= 8'hxx; // don't care + default: AI <= 0; endcase @@ -679,7 +691,10 @@ always @* BRA0: BI <= PCL; - default: BI <= DI; + DECODE, + ABS1: BI <= 8'hxx; + + default: BI <= DIMUX; endcase /* @@ -690,9 +705,11 @@ always @* case( state ) INDY2, BRA1, - ABS1, ABSX1: CI <= CO; + DECODE, + ABS1: CI <= 1'bx; + READ, REG: CI <= rotate ? C : shift ? 0 : inc; @@ -725,7 +742,7 @@ always @(posedge clk ) if( shift && state == WRITE ) C <= CO; else if( state == RTI2 ) - C <= DI[0]; + C <= DIMUX[0]; else if( ~write_back && state == DECODE ) begin if( adc_sbc | shift | compare ) C <= CO; @@ -745,7 +762,7 @@ always @(posedge clk) if( state == WRITE ) Z <= AZ; else if( state == RTI2 ) - Z <= DI[1]; + Z <= DIMUX[1]; else if( state == DECODE ) begin if( plp ) Z <= ADD[1]; @@ -757,14 +774,14 @@ always @(posedge clk) if( state == WRITE ) N <= AN; else if( state == RTI2 ) - N <= DI[7]; + N <= DIMUX[7]; else if( state == DECODE ) begin if( plp ) N <= ADD[7]; else if( (load_reg & (regsel != SEL_S)) | compare ) N <= AN; end else if( state == FETCH && bit ) - N <= DI[7]; + N <= DIMUX[7]; /* * Update I flag @@ -774,7 +791,7 @@ always @(posedge clk) if( state == BRK3 ) I <= 1; else if( state == RTI2 ) - I <= DI[2]; + I <= DIMUX[2]; else if( state == DECODE ) begin if( sei ) I <= 1; if( cli ) I <= 0; @@ -786,7 +803,7 @@ always @(posedge clk) */ always @(posedge clk ) if( state == RTI2 ) - D <= DI[3]; + D <= DIMUX[3]; else if( state == DECODE ) begin if( sed ) D <= 1; if( cld ) D <= 0; @@ -798,13 +815,13 @@ always @(posedge clk ) */ always @(posedge clk ) if( state == RTI2 ) - V <= DI[6]; + V <= DIMUX[6]; else if( state == DECODE ) begin if( adc_sbc ) V <= AV; if( clv ) V <= 0; if( plp ) V <= ADD[6]; end else if( state == FETCH && bit ) - V <= DI[6]; + V <= DIMUX[6]; /* * Instruction decoder @@ -816,17 +833,30 @@ always @(posedge clk ) * time to read the IR again before the next decode. */ +reg RDY1 = 1; + +always @(posedge clk ) + RDY1 <= RDY; + +always @(posedge clk ) + if( ~RDY && RDY1 ) + DIHOLD <= DI; + always @(posedge clk ) if( reset ) IRHOLD_valid <= 0; - else if( state == PULL0 || state == PUSH0 ) begin - IRHOLD <= DI; - IRHOLD_valid <= 1; - end else if( state == DECODE ) - IRHOLD_valid <= 0; + else if( RDY ) begin + if( state == PULL0 || state == PUSH0 ) begin + IRHOLD <= DIMUX; + IRHOLD_valid <= 1; + end else if( state == DECODE ) + IRHOLD_valid <= 0; + end assign IR = (IRQ & ~I) | NMI_edge ? 8'h00 : - IRHOLD_valid ? IRHOLD : DI; + IRHOLD_valid ? IRHOLD : DIMUX; + +assign DIMUX = ~RDY1 ? DIHOLD : DI; /* * Microcode state machine @@ -834,7 +864,7 @@ assign IR = (IRQ & ~I) | NMI_edge ? 8'h00 : always @(posedge clk or posedge reset) if( reset ) state <= BRK0; - else case( state ) + else if( RDY ) case( state ) DECODE : casex ( IR ) 8'b0000_0000: state <= BRK0; @@ -942,7 +972,7 @@ always @(posedge clk) res <= 0; always @(posedge clk) - if( state == DECODE ) + if( state == DECODE && RDY ) casex( IR ) 8'b0xxx_xx01, // ORA, AND, EOR, ADC 8'b1x1x_xx01, // LDA, SBC @@ -955,7 +985,7 @@ always @(posedge clk) endcase always @(posedge clk) - if( state == DECODE ) + if( state == DECODE && RDY ) casex( IR ) 8'b1110_1000, // INX 8'b1100_1010, // DEX @@ -975,7 +1005,7 @@ always @(posedge clk) endcase always @(posedge clk) - if( state == DECODE ) + if( state == DECODE && RDY ) casex( IR ) 8'b1011_1010: // TSX src_reg <= SEL_S; @@ -996,7 +1026,7 @@ always @(posedge clk) endcase always @(posedge clk) - if( state == DECODE ) + if( state == DECODE && RDY ) casex( IR ) 8'bxxx1_0001, // INDY 8'b10x1_x110, // LDX/STX zpg/abs, Y @@ -1008,7 +1038,7 @@ always @(posedge clk) always @(posedge clk) - if( state == DECODE ) + if( state == DECODE && RDY ) casex( IR ) 8'b100x_x1x0, // STX, STY 8'b100x_xx01: // STA @@ -1019,7 +1049,7 @@ always @(posedge clk) endcase always @(posedge clk ) - if( state == DECODE ) + if( state == DECODE && RDY ) casex( IR ) 8'b0xxx_x110, // ASL, ROL, LSR, ROR 8'b11xx_x110: // DEC/INC @@ -1030,7 +1060,7 @@ always @(posedge clk ) always @(posedge clk ) - if( state == DECODE ) + if( state == DECODE && RDY ) casex( IR ) 8'b101x_xxxx: // LDA, LDX, LDY load_only <= 1; @@ -1038,7 +1068,7 @@ always @(posedge clk ) endcase always @(posedge clk ) - if( state == DECODE ) + if( state == DECODE && RDY ) casex( IR ) 8'b111x_x110, // INC 8'b11x0_1000: // INX, INY @@ -1048,7 +1078,7 @@ always @(posedge clk ) endcase always @(posedge clk ) - if( state == DECODE || state == BRK0 ) + if( (state == DECODE || state == BRK0) && RDY ) casex( IR ) 8'bx11x_xx01: // SBC, ADC adc_sbc <= 1; @@ -1057,7 +1087,7 @@ always @(posedge clk ) endcase always @(posedge clk ) - if( state == DECODE || state == BRK0 ) + if( (state == DECODE || state == BRK0) && RDY ) casex( IR ) 8'b011x_xx01: // ADC adc_bcd <= D; @@ -1066,7 +1096,7 @@ always @(posedge clk ) endcase always @(posedge clk ) - if( state == DECODE ) + if( state == DECODE && RDY ) casex( IR ) 8'b0xxx_x110, // ASL, ROL, LSR, ROR (abs, absx, zpg, zpgx) 8'b0xxx_1010: // ASL, ROL, LSR, ROR (acc) @@ -1076,7 +1106,7 @@ always @(posedge clk ) endcase always @(posedge clk ) - if( state == DECODE ) + if( state == DECODE && RDY ) casex( IR ) 8'b11x0_0x00, // CPX, CPY (imm/zp) 8'b11x0_1100, // CPX, CPY (abs) @@ -1087,7 +1117,7 @@ always @(posedge clk ) endcase always @(posedge clk ) - if( state == DECODE ) + if( state == DECODE && RDY ) casex( IR ) 8'b01xx_xx10: // ROR, LSR shift_right <= 1; @@ -1096,7 +1126,7 @@ always @(posedge clk ) endcase always @(posedge clk ) - if( state == DECODE ) + if( state == DECODE && RDY ) casex( IR ) 8'b0x1x_1010, // ROL A, ROR A 8'b0x1x_x110: // ROR, ROL @@ -1106,7 +1136,7 @@ always @(posedge clk ) endcase always @(posedge clk ) - if( state == DECODE ) + if( state == DECODE && RDY ) casex( IR ) 8'b00xx_xx10: // ROL, ASL op <= OP_ROL; @@ -1132,7 +1162,7 @@ always @(posedge clk ) endcase always @(posedge clk ) - if( state == DECODE ) + if( state == DECODE && RDY ) casex( IR ) 8'b0010_x100: // BIT zp/abs bit <= 1; @@ -1144,7 +1174,7 @@ always @(posedge clk ) * special instructions */ always @(posedge clk ) - if( state == DECODE ) begin + if( state == DECODE && RDY ) begin php <= (IR == 8'h08); clc <= (IR == 8'h18); plp <= (IR == 8'h28); @@ -1158,19 +1188,20 @@ always @(posedge clk ) end always @(posedge clk) + if( RDY ) cond_code <= IR[7:5]; always @* - case( cond_code ) - 3'b000: cond_true <= ~N; - 3'b001: cond_true <= N; - 3'b010: cond_true <= ~V; - 3'b011: cond_true <= V; - 3'b100: cond_true <= ~C; - 3'b101: cond_true <= C; - 3'b110: cond_true <= ~Z; - 3'b111: cond_true <= Z; - endcase + case( cond_code ) + 3'b000: cond_true <= ~N; + 3'b001: cond_true <= N; + 3'b010: cond_true <= ~V; + 3'b011: cond_true <= V; + 3'b100: cond_true <= ~C; + 3'b101: cond_true <= C; + 3'b110: cond_true <= ~Z; + 3'b111: cond_true <= Z; + endcase reg NMI_1 = 0; // delayed NMI signal