Add 32 bit BRK

This commit is contained in:
2026-04-26 08:53:59 -07:00
parent 06f933fa56
commit 9476c6a0dd
3 changed files with 75 additions and 31 deletions

View File

@@ -0,0 +1,9 @@
tests:
- name: "cpu_65c02"
toplevel: "cpu_65c02"
modules:
- "verilog6502_32bit_test"
sources: "sources.list"
waves: True
defines:
SIM: "hi"

View File

@@ -0,0 +1,20 @@
import cocotb
from cocotb.handle import Immediate
from cocotb.clock import Clock
from cocotb.triggers import Timer, RisingEdge
CLK_PERIOD = 5
@cocotb.test
async def test_absolute(dut):
cocotb.start_soon(Clock(dut.clk, CLK_PERIOD, unit="ns").start())
dut.RDY.value = Immediate(1)
dut.reset.value = Immediate(1)
for _ in range(10):
await RisingEdge(dut.clk)
dut.reset.value = 0
await Timer(1, "us")

View File

@@ -52,7 +52,7 @@ module cpu_65c02( clk, reset, AB, DI, DO, WE, IRQ, NMI, RDY, RDY_O, SYNC );
input clk; // CPU clock input clk; // CPU clock
input reset; // reset signal input reset; // reset signal
output reg [15:0] AB; // address bus output reg [31:0] AB; // address bus
input [7:0] DI; // data in, read bus input [7:0] DI; // data in, read bus
output [7:0] DO; // data out, write bus output [7:0] DO; // data out, write bus
output WE; // write enable output WE; // write enable
@@ -66,9 +66,8 @@ output reg SYNC; // AB is first cycle of the intruction
* internal signals * internal signals
*/ */
reg [15:0] PC; // Program Counter reg [31:0] PC; // Program Counter
reg [7:0] ABL; // Address Bus Register LSB reg [31:0] ABR; // Address Bus Register
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 [7:0] DIHOLD; // Hold for Data In
@@ -103,8 +102,6 @@ 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
wire [7:0] PCH = PC[15:8];
wire [7:0] PCL = PC[7:0];
reg NMI_edge = 0; // captured NMI edge reg NMI_edge = 0; // captured NMI edge
@@ -142,7 +139,7 @@ reg [5:0] state;
*/ */
reg PC_inc; // Increment PC reg PC_inc; // Increment PC
reg [15:0] PC_temp; // intermediate value of PC reg [31:0] PC_temp; // intermediate value of PC
reg [1:0] src_reg; // source register index reg [1:0] src_reg; // source register index
reg [1:0] dst_reg; // destination register index reg [1:0] dst_reg; // destination register index
@@ -263,7 +260,9 @@ parameter
JMPIX0 = 6'd51, // JMP (,X)- fetch LSB and send to ALU (+X) JMPIX0 = 6'd51, // JMP (,X)- fetch LSB and send to ALU (+X)
JMPIX1 = 6'd52, // JMP (,X)- fetch MSB and send to ALU (+Carry) JMPIX1 = 6'd52, // JMP (,X)- fetch MSB and send to ALU (+Carry)
JMPIX2 = 6'd53, // JMP (,X)- Wait for ALU (only if needed) JMPIX2 = 6'd53, // JMP (,X)- Wait for ALU (only if needed)
WAI = 6'd54; // WAI - Wait for interrupt, then go to decode WAI = 6'd54, // WAI - Wait for interrupt, then go to decode
BRK4 = 6'd55, // TODO
BRK5 = 6'd56; // TODO
`ifdef SIM `ifdef SIM
@@ -318,6 +317,8 @@ always @*
BRK1: statename = "BRK1"; BRK1: statename = "BRK1";
BRK2: statename = "BRK2"; BRK2: statename = "BRK2";
BRK3: statename = "BRK3"; BRK3: statename = "BRK3";
BRK4: statename = "BRK4";
BRK5: statename = "BRK5";
BRA0: statename = "BRA0"; BRA0: statename = "BRA0";
BRA1: statename = "BRA1"; BRA1: statename = "BRA1";
BRA2: statename = "BRA2"; BRA2: statename = "BRA2";
@@ -346,7 +347,7 @@ always @*
always @* always @*
case( state ) case( state )
DECODE: if( (~I & IRQ) | NMI_edge ) DECODE: if( (~I & IRQ) | NMI_edge )
PC_temp = { ABH, ABL }; PC_temp = ABR;
else else
PC_temp = PC; PC_temp = PC;
@@ -358,13 +359,13 @@ always @*
RTS3, RTS3,
RTI4: PC_temp = { DIMUX, ADD }; RTI4: PC_temp = { DIMUX, ADD };
BRA1: PC_temp = { ABH, ADD }; BRA1: PC_temp = { ABR[15:8], ADD };
JMPIX2, JMPIX2,
BRA2: PC_temp = { ADD, PCL }; BRA2: PC_temp = { ADD, PC[7:0] }; // TODO
BRK2: PC_temp = res ? 16'hfffc : BRK2: PC_temp = res ? 32'hFFFFFFF4 :
NMI_edge ? 16'hfffa : 16'hfffe; NMI_edge ? 32'hFFFFFFF8 : 32'hFFFFFFFC;
default: PC_temp = PC; default: PC_temp = PC;
endcase endcase
@@ -386,7 +387,7 @@ always @*
FETCH, FETCH,
BRA0, BRA0,
BRA2, BRA2,
BRK3, BRK5,
JMPI1, JMPI1,
JMP1, JMP1,
RTI4, RTI4,
@@ -428,15 +429,15 @@ always @*
BRA2, BRA2,
INDY3, INDY3,
JMPIX2, JMPIX2,
ABSX2: AB = { ADD, ABL }; ABSX2: AB = { ADD, ABR[7:0] }; // TODO
BRA1: AB = { ABH, ADD }; BRA1: AB = { ABR[15:8], ADD }; // TODO
JSR0, JSR0,
PUSH1, PUSH1,
RTS0, RTS0,
RTI0, RTI0,
BRK0: AB = { STACKPAGE, regfile }; BRK0: AB = { 16'h0, STACKPAGE, regfile };
BRK1, BRK1,
JSR1, JSR1,
@@ -446,7 +447,9 @@ always @*
RTI1, RTI1,
RTI2, RTI2,
RTI3, RTI3,
BRK2: AB = { STACKPAGE, ADD }; BRK2,
BRK3,
BRK4: AB = { 16'h0, STACKPAGE, ADD };
INDY1, INDY1,
INDX1, INDX1,
@@ -458,7 +461,7 @@ always @*
REG, REG,
READ, READ,
WRITE: AB = { ABH, ABL }; WRITE: AB = ABR;
default: AB = PC; default: AB = PC;
endcase endcase
@@ -472,8 +475,7 @@ always @(posedge clk)
if( state != PUSH0 && state != PUSH1 && RDY && if( state != PUSH0 && state != PUSH1 && RDY &&
state != PULL0 && state != PULL1 && state != PULL2 ) state != PULL0 && state != PULL1 && state != PULL2 )
begin begin
ABL <= AB[7:0]; ABR <= AB;
ABH <= AB[15:8];
end end
/* /*
@@ -484,14 +486,20 @@ always @*
WRITE: DO = ADD; WRITE: DO = ADD;
JSR0, JSR0,
BRK0: DO = PCH; BRK0: DO = PC[31:24];
JSR1, JSR1,
BRK1: DO = PCL; BRK1: DO = PC[23:16];
JSR2,
BRK2: DO = PC[15:8];
JSR3,
BRK3: DO = PC[7:0];
PUSH1: DO = php ? P : ADD; PUSH1: DO = php ? P : ADD;
BRK2: DO = (IRQ | NMI_edge) ? (P & 8'b1110_1111) : P; BRK4: DO = (IRQ | NMI_edge) ? (P & 8'b1110_1111) : P;
default: DO = store_zero ? 8'b0 : regfile; default: DO = store_zero ? 8'b0 : regfile;
endcase endcase
@@ -505,8 +513,13 @@ always @*
BRK0, // writing to stack or memory BRK0, // writing to stack or memory
BRK1, BRK1,
BRK2, BRK2,
BRK2,
BRK3,
BRK4,
JSR0, JSR0,
JSR1, JSR1,
JSR2,
JSR3,
PUSH1, PUSH1,
WRITE: WE = 1; WRITE: WE = 1;
@@ -535,7 +548,7 @@ always @*
PULL1, PULL1,
RTS2, RTS2,
RTI3, RTI3,
BRK3, BRK5,
JSR0, JSR0,
JSR2 : write_register = 1; JSR2 : write_register = 1;
@@ -621,7 +634,7 @@ always @*
DECODE : regsel = dst_reg; DECODE : regsel = dst_reg;
BRK0, BRK0,
BRK3, BRK5,
JSR0, JSR0,
JSR2, JSR2,
PULL0, PULL0,
@@ -730,7 +743,7 @@ always @*
BRA0, BRA0,
READ: AI = DIMUX; READ: AI = DIMUX;
BRA1: AI = ABH; // don't use PCH in case we're BRA1: AI = ABR[15:8]; // don't use PCH in case we're TODO
FETCH: AI = load_only ? 8'b0 : regfile; FETCH: AI = load_only ? 8'b0 : regfile;
@@ -767,7 +780,7 @@ always @*
READ: BI = txb_ins ? (trb_ins ? ~regfile : regfile) : 8'h00; READ: BI = txb_ins ? (trb_ins ? ~regfile : regfile) : 8'h00;
BRA0: BI = PCL; BRA0: BI = PC[7:0]; // TODO
DECODE, DECODE,
ABS1: BI = 8'hxx; ABS1: BI = 8'hxx;
@@ -880,7 +893,7 @@ always @(posedge clk)
*/ */
always @(posedge clk) always @(posedge clk)
if( state == BRK3 ) if( state == BRK5 )
I <= 1; I <= 1;
else if( state == RTI2 ) else if( state == RTI2 )
I <= DIMUX[2]; I <= DIMUX[2];
@@ -1069,7 +1082,9 @@ always @(posedge clk or posedge reset)
BRK0 : state <= BRK1; BRK0 : state <= BRK1;
BRK1 : state <= BRK2; BRK1 : state <= BRK2;
BRK2 : state <= BRK3; BRK2 : state <= BRK3;
BRK3 : state <= JMP0; BRK3 : state <= BRK4;
BRK4 : state <= BRK5;
BRK5 : state <= JMP0;
WAI : state <= ( (~I & IRQ) | NMI_edge ) ? DECODE : WAI; WAI : state <= ( (~I & IRQ) | NMI_edge ) ? DECODE : WAI;
@@ -1415,7 +1430,7 @@ always @(posedge clk)
NMI_1 <= NMI; NMI_1 <= NMI;
always @(posedge clk ) always @(posedge clk )
if( NMI_edge && state == BRK3 ) if( NMI_edge && state == BRK5 )
NMI_edge <= 0; NMI_edge <= 0;
else if( NMI & ~NMI_1 ) else if( NMI & ~NMI_1 )
NMI_edge <= 1; NMI_edge <= 1;