Added support for RDY

This commit is contained in:
Arlet
2011-05-16 14:31:22 +02:00
parent 5fe44f4b7f
commit c305e6d3ef
2 changed files with 96 additions and 63 deletions

6
ALU.v
View File

@@ -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 clk;
input right; input right;
input [3:0] op; // operation 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 Z;
output N; output N;
output HC; output HC;
input RDY;
reg [7:0] OUT; reg [7:0] OUT;
reg CO; reg CO;
@@ -89,7 +90,8 @@ always @* begin
end end
// calculate the flags // calculate the flags
always @(posedge clk) begin always @(posedge clk)
if( RDY ) begin
OUT <= temp[7:0]; OUT <= temp[7:0];
CO <= temp[8] | CO9; CO <= temp[8] | CO9;
Z <= ~|temp[7:0]; Z <= ~|temp[7:0];

123
cpu.v
View File

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