Arlet 65C02 WIP: Implement correct 65C02 BCD N/Z flags (optional, disabled)
Change-Id: Ib72bcc1a100ee3c642048ce195bf1424feb4bf50
This commit is contained in:
37
cpu_65c02.v
37
cpu_65c02.v
@@ -28,6 +28,16 @@
|
|||||||
|
|
||||||
`define IMPLEMENT_NOPS
|
`define IMPLEMENT_NOPS
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Two things were needed to correctly implement 65C02 BCD arithmentic
|
||||||
|
* 1. The Z flag needs calculating over the BCD adjusted ALU output
|
||||||
|
* 2. The N flag needs calculating over the BCD adjusted ALU output
|
||||||
|
*
|
||||||
|
* If IMPLEMENT_CORRECT_BCD_FLAGS is defined, this additional logic is added
|
||||||
|
*/
|
||||||
|
|
||||||
|
// `define IMPLEMENT_CORRECT_BCD_FLAGS
|
||||||
|
|
||||||
module cpu_65c02( clk, reset, AB, DI, DO, WE, IRQ, NMI, RDY );
|
module cpu_65c02( clk, reset, AB, DI, DO, WE, IRQ, NMI, RDY );
|
||||||
|
|
||||||
input clk; // CPU clock
|
input clk; // CPU clock
|
||||||
@@ -65,9 +75,11 @@ reg D = 0; // decimal flag
|
|||||||
reg V = 0; // overflow flag
|
reg V = 0; // overflow flag
|
||||||
reg N = 0; // negative flag
|
reg N = 0; // negative flag
|
||||||
wire AZ; // ALU Zero flag
|
wire AZ; // ALU Zero flag
|
||||||
|
wire AZ1; // ALU Zero flag (BCD adjusted)
|
||||||
reg AZ2; // ALU Second Zero flag, set using TSB/TRB semantics
|
reg AZ2; // ALU Second Zero flag, set using TSB/TRB semantics
|
||||||
wire AV; // ALU overflow flag
|
wire AV; // ALU overflow flag
|
||||||
wire AN; // ALU negative flag
|
wire AN; // ALU negative flag
|
||||||
|
wire AN1; // ALU negative flag (BCD adjusted)
|
||||||
wire HC; // ALU half carry
|
wire HC; // ALU half carry
|
||||||
|
|
||||||
reg [7:0] AI; // ALU Input A
|
reg [7:0] AI; // ALU Input A
|
||||||
@@ -75,6 +87,7 @@ reg [7:0] BI; // ALU Input B
|
|||||||
wire [7:0] DI; // Data In
|
wire [7:0] DI; // Data In
|
||||||
wire [7:0] IR; // Instruction register
|
wire [7:0] IR; // Instruction register
|
||||||
reg [7:0] DO; // Data Out
|
reg [7:0] DO; // Data Out
|
||||||
|
wire [7:0] AO; // ALU output after BCD adjustment
|
||||||
reg WE; // Write Enable
|
reg WE; // Write Enable
|
||||||
reg CI; // Carry In
|
reg CI; // Carry In
|
||||||
wire CO; // Carry Out
|
wire CO; // Carry Out
|
||||||
@@ -554,6 +567,20 @@ always @* begin
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assign AO = { ADD[7:4] + ADJH, ADD[3:0] + ADJL };
|
||||||
|
|
||||||
|
`ifdef IMPLEMENT_CORRECT_BCD_FLAGS
|
||||||
|
|
||||||
|
assign AN1 = AO[7];
|
||||||
|
assign AZ1 = ~|AO;
|
||||||
|
|
||||||
|
`else
|
||||||
|
|
||||||
|
assign AN1 = AN;
|
||||||
|
assign AZ1 = AZ;
|
||||||
|
|
||||||
|
`endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* write to a register. Usually this is the (BCD corrected) output of the
|
* write to a register. Usually this is the (BCD corrected) output of the
|
||||||
* ALU, but in case of the JSR0 we use the S register to temporarily store
|
* ALU, but in case of the JSR0 we use the S register to temporarily store
|
||||||
@@ -562,7 +589,7 @@ end
|
|||||||
*/
|
*/
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
if( write_register & RDY )
|
if( write_register & RDY )
|
||||||
AXYS[regsel] <= (state == JSR0) ? DIMUX : { ADD[7:4] + ADJH, ADD[3:0] + ADJL };
|
AXYS[regsel] <= (state == JSR0) ? DIMUX : AO;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* register select logic. This determines which of the A, X, Y or
|
* register select logic. This determines which of the A, X, Y or
|
||||||
@@ -805,26 +832,26 @@ always @(posedge clk)
|
|||||||
|
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
if( state == WRITE)
|
if( state == WRITE)
|
||||||
Z <= txb_ins ? AZ2 : AZ;
|
Z <= txb_ins ? AZ2 : AZ1;
|
||||||
else if( state == RTI2 )
|
else if( state == RTI2 )
|
||||||
Z <= DIMUX[1];
|
Z <= DIMUX[1];
|
||||||
else if( state == DECODE ) begin
|
else if( state == DECODE ) begin
|
||||||
if( plp )
|
if( plp )
|
||||||
Z <= ADD[1];
|
Z <= ADD[1];
|
||||||
else if( (load_reg & (regsel != SEL_S)) | compare | bit_ins )
|
else if( (load_reg & (regsel != SEL_S)) | compare | bit_ins )
|
||||||
Z <= AZ;
|
Z <= AZ1;
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
if( state == WRITE && ~txb_ins)
|
if( state == WRITE && ~txb_ins)
|
||||||
N <= AN;
|
N <= AN1;
|
||||||
else if( state == RTI2 )
|
else if( state == RTI2 )
|
||||||
N <= DIMUX[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 <= AN1;
|
||||||
end else if( state == FETCH && bit_ins_nv )
|
end else if( state == FETCH && bit_ins_nv )
|
||||||
N <= DIMUX[7];
|
N <= DIMUX[7];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user