fixed verilog 6502 CPU

This commit is contained in:
Steven Hugg 2019-08-29 09:36:18 -04:00
parent 912123ea64
commit 187bcfc2e2
1 changed files with 95 additions and 95 deletions

View File

@ -1,16 +1,20 @@
/* verilator lint_off CASEX */
/* verilator lint_off CASEINCOMPLETE */
/* verilator lint_off CASEOVERLAP */
/* verilator lint_off SYNCASYNCNET */
/*
* verilog model of 6502 CPU.
*
* (C) Arlet Ottens, <arlet@c-scape.nl>
*
* https://github.com/Arlet/verilog-6502/
*
* Feel free to use this code in any project (commercial or not), as long as you
* keep this message, and the copyright notice. This code is provided "as is",
* without any warranties of any kind.
*
*/
/*
* Note that not all 6502 interface signals are supported (yet). The goal
* is to create an Acorn Atom model, and the Atom didn't use all signals on
* the main board.
@ -500,8 +504,8 @@ reg [3:0] ADJH;
// adc_bcd: '1' if doing ADC with D=1
// HC : half carry bit from ALU
always @* begin
casez( {adj_bcd, adc_bcd, HC} )
3'b0??: ADJL = 4'd0; // no BCD instruction
casex( {adj_bcd, adc_bcd, HC} )
3'b0xx: ADJL = 4'd0; // no BCD instruction
3'b100: ADJL = 4'd10; // SBC, and digital borrow
3'b101: ADJL = 4'd0; // SBC, but no borrow
3'b110: ADJL = 4'd0; // ADC, but no carry
@ -514,8 +518,8 @@ end
// adc_bcd: '1' if doing ADC with D=1
// CO : carry out bit from ALU
always @* begin
casez( {adj_bcd, adc_bcd, CO} )
3'b0??: ADJH = 4'd0; // no BCD instruction
casex( {adj_bcd, adc_bcd, CO} )
3'b0xx: ADJH = 4'd0; // no BCD instruction
3'b100: ADJH = 4'd10; // SBC, and digital borrow
3'b101: ADJH = 4'd0; // SBC, but no borrow
3'b110: ADJH = 4'd0; // ADC, but no carry
@ -857,15 +861,16 @@ always @(posedge clk )
assign DIMUX = ~RDY ? DIHOLD : DI;
/*
* Microcode state machine
*/
always @(posedge clk)
always @(posedge clk or posedge reset)
if( reset )
state <= BRK0;
else if( RDY ) case( state )
DECODE :
casez ( IR )
casex ( IR )
8'b0000_0000: state <= BRK0;
8'b0010_0000: state <= JSR0;
8'b0010_1100: state <= ABS0; // BIT abs
@ -873,24 +878,23 @@ always @(posedge clk)
8'b0100_1100: state <= JMP0;
8'b0110_0000: state <= RTS0;
8'b0110_1100: state <= JMPI0;
8'b0?00_1000: state <= PUSH0;
8'b0?10_1000: state <= PULL0;
8'b0??1_1000: state <= REG; // CLC, SEC, CLI, SEI
8'b1??0_00?0: state <= FETCH; // IMM
8'b1??0_1100: state <= ABS0; // X/Y abs
8'b1???_1000: state <= REG; // DEY, TYA, ...
8'b???0_0001: state <= INDX0;
8'b???0_01??: state <= ZP0;
8'b???0_1001: state <= FETCH; // IMM
8'b???0_1101: state <= ABS0; // even E column
8'b???0_1110: state <= ABS0; // even E column
8'b???1_0000: state <= BRA0; // odd 0 column
8'b???1_0001: state <= INDY0; // odd 1 column
8'b???1_01??: state <= ZPX0; // odd 4,5,6,7 columns
8'b???1_1001: state <= ABSX0; // odd 9 column
8'b???1_11??: state <= ABSX0; // odd C, D, E, F columns
8'b????_1010: state <= REG; // <shift> A, TXA, ... NOP
default: state <= BRK0; // TODO
8'b0x00_1000: state <= PUSH0;
8'b0x10_1000: state <= PULL0;
8'b0xx1_1000: state <= REG; // CLC, SEC, CLI, SEI
8'b1xx0_00x0: state <= FETCH; // IMM
8'b1xx0_1100: state <= ABS0; // X/Y abs
8'b1xxx_1000: state <= REG; // DEY, TYA, ...
8'bxxx0_0001: state <= INDX0;
8'bxxx0_01xx: state <= ZP0;
8'bxxx0_1001: state <= FETCH; // IMM
8'bxxx0_1101: state <= ABS0; // even E column
8'bxxx0_1110: state <= ABS0; // even E column
8'bxxx1_0000: state <= BRA0; // odd 0 column
8'bxxx1_0001: state <= INDY0; // odd 1 column
8'bxxx1_01xx: state <= ZPX0; // odd 4,5,6,7 columns
8'bxxx1_1001: state <= ABSX0; // odd 9 column
8'bxxx1_11xx: state <= ABSX0; // odd C, D, E, F columns
8'bxxxx_1010: state <= REG; // <shift> A, TXA, ... NOP
endcase
ZP0 : state <= write_back ? READ : FETCH;
@ -958,7 +962,6 @@ always @(posedge clk)
BRK1 : state <= BRK2;
BRK2 : state <= BRK3;
BRK3 : state <= JMP0;
default : state <= BRK0;
endcase
@ -974,16 +977,16 @@ always @(posedge clk)
always @(posedge clk)
if( state == DECODE && RDY )
casez( IR )
8'b0??01010, // ASLA, ROLA, LSRA, RORA
8'b0?????01, // ORA, AND, EOR, ADC
8'b100?10?0, // DEY, TYA, TXA, TXS
8'b1010???0, // LDA/LDX/LDY
casex( IR )
8'b0xx01010, // ASLA, ROLA, LSRA, RORA
8'b0xxxxx01, // ORA, AND, EOR, ADC
8'b100x10x0, // DEY, TYA, TXA, TXS
8'b1010xxx0, // LDA/LDX/LDY
8'b10111010, // TSX
8'b1011?1?0, // LDX/LDY
8'b1011x1x0, // LDX/LDY
8'b11001010, // DEX
8'b1?1???01, // LDA, SBC
8'b11?01000: // DEY, TAY, INY, INX (88,a8,c8,e8)
8'b1x1xxx01, // LDA, SBC
8'bxxx01000: // DEY, TAY, INY, INX
load_reg <= 1;
default: load_reg <= 0;
@ -991,19 +994,19 @@ always @(posedge clk)
always @(posedge clk)
if( state == DECODE && RDY )
casez( IR )
casex( IR )
8'b1110_1000, // INX
8'b1100_1010, // DEX
8'b101?_??10: // LDX, TAX, TSX
8'b101x_xx10: // LDX, TAX, TSX
dst_reg <= SEL_X;
8'b0?00_1000, // PHP, PHA
8'b0x00_1000, // PHP, PHA
8'b1001_1010: // TXS
dst_reg <= SEL_S;
8'b1?00_1000, // DEY, DEX
8'b101?_?100, // LDY
8'b1010_?000: // LDY #imm, TAY
8'b1x00_1000, // DEY, DEX
8'b101x_x100, // LDY
8'b1010_x000: // LDY #imm, TAY
dst_reg <= SEL_Y;
default: dst_reg <= SEL_A;
@ -1011,22 +1014,20 @@ always @(posedge clk)
always @(posedge clk)
if( state == DECODE && RDY )
casez( IR )
casex( IR )
8'b1011_1010: // TSX
src_reg <= SEL_S;
8'b100?_?110, // STX
8'b100?_1010, // TXA, TXS
8'b1110_??00, // INX, CPX
8'b100x_x110, // STX
8'b100x_1x10, // TXA, TXS
8'b1110_xx00, // INX, CPX
8'b1100_1010: // DEX
src_reg <= SEL_X;
8'b100?_?100, // STY
8'b100x_x100, // STY
8'b1001_1000, // TYA
8'b1100_0000, // CPY
8'b1100_0010, // CPY
8'b1100_1110, // CPY
8'b1?00_1000: // DEY, INY
8'b1100_xx00, // CPY
8'b1x00_1000: // DEY, INY
src_reg <= SEL_Y;
default: src_reg <= SEL_A;
@ -1034,10 +1035,10 @@ always @(posedge clk)
always @(posedge clk)
if( state == DECODE && RDY )
casez( IR )
8'b???1_0001, // INDY
8'b10?1_?110, // LDX/STX zpg/abs, Y
8'b????_1001: // abs, Y
casex( IR )
8'bxxx1_0001, // INDY
8'b10x1_x110, // LDX/STX zpg/abs, Y
8'bxxxx_1001: // abs, Y
index_y <= 1;
default: index_y <= 0;
@ -1046,9 +1047,9 @@ always @(posedge clk)
always @(posedge clk)
if( state == DECODE && RDY )
casez( IR )
8'b100?_?1?0, // STX, STY
8'b100?_??01: // STA
casex( IR )
8'b100x_x1x0, // STX, STY
8'b100x_xx01: // STA
store <= 1;
default: store <= 0;
@ -1057,9 +1058,9 @@ always @(posedge clk)
always @(posedge clk )
if( state == DECODE && RDY )
casez( IR )
8'b0???_?110, // ASL, ROL, LSR, ROR
8'b11??_?110: // DEC/INC
casex( IR )
8'b0xxx_x110, // ASL, ROL, LSR, ROR
8'b11xx_x110: // DEC/INC
write_back <= 1;
default: write_back <= 0;
@ -1068,17 +1069,17 @@ always @(posedge clk )
always @(posedge clk )
if( state == DECODE && RDY )
casez( IR )
8'b101?_????: // LDA, LDX, LDY
casex( IR )
8'b101x_xxxx: // LDA, LDX, LDY
load_only <= 1;
default: load_only <= 0;
endcase
always @(posedge clk )
if( state == DECODE && RDY )
casez( IR )
8'b111?_?110, // INC
8'b11?0_1000: // INX, INY
casex( IR )
8'b111x_x110, // INC
8'b11x0_1000: // INX, INY
inc <= 1;
default: inc <= 0;
@ -1086,8 +1087,8 @@ always @(posedge clk )
always @(posedge clk )
if( (state == DECODE || state == BRK0) && RDY )
casez( IR )
8'b?11?_??01: // SBC, ADC
casex( IR )
8'bx11x_xx01: // SBC, ADC
adc_sbc <= 1;
default: adc_sbc <= 0;
@ -1095,8 +1096,8 @@ always @(posedge clk )
always @(posedge clk )
if( (state == DECODE || state == BRK0) && RDY )
casez( IR )
8'b011?_??01: // ADC
casex( IR )
8'b011x_xx01: // ADC
adc_bcd <= D;
default: adc_bcd <= 0;
@ -1104,9 +1105,9 @@ always @(posedge clk )
always @(posedge clk )
if( state == DECODE && RDY )
casez( IR )
8'b0???_?110, // ASL, ROL, LSR, ROR (abs, abs?, zpg, zpg?)
8'b0???_1010: // ASL, ROL, LSR, ROR (acc)
casex( IR )
8'b0xxx_x110, // ASL, ROL, LSR, ROR (abs, absx, zpg, zpgx)
8'b0xxx_1010: // ASL, ROL, LSR, ROR (acc)
shift <= 1;
default: shift <= 0;
@ -1114,10 +1115,10 @@ always @(posedge clk )
always @(posedge clk )
if( state == DECODE && RDY )
casez( IR )
8'b11?0_0?00, // CPX, CPY (imm/zp)
8'b11?0_1100, // CPX, CPY (abs)
8'b110?_??01: // CMP
casex( IR )
8'b11x0_0x00, // CPX, CPY (imm/zp)
8'b11x0_1100, // CPX, CPY (abs)
8'b110x_xx01: // CMP
compare <= 1;
default: compare <= 0;
@ -1125,8 +1126,8 @@ always @(posedge clk )
always @(posedge clk )
if( state == DECODE && RDY )
casez( IR )
8'b01??_??10: // ROR, LSR
casex( IR )
8'b01xx_xx10: // ROR, LSR
shift_right <= 1;
default: shift_right <= 0;
@ -1134,9 +1135,9 @@ always @(posedge clk )
always @(posedge clk )
if( state == DECODE && RDY )
casez( IR )
8'b0?1?_1010, // ROL A, ROR A
8'b0?1?_?110: // ROR, ROL
casex( IR )
8'b0x1x_1010, // ROL A, ROR A
8'b0x1x_x110: // ROR, ROL
rotate <= 1;
default: rotate <= 0;
@ -1144,25 +1145,25 @@ always @(posedge clk )
always @(posedge clk )
if( state == DECODE && RDY )
casez( IR )
8'b00??_??10: // ROL, ASL
casex( IR )
8'b00xx_xx10: // ROL, ASL
op <= OP_ROL;
8'b0010_?100: // BIT zp/abs
8'b0010_x100: // BIT zp/abs
op <= OP_AND;
8'b01??_??10: // ROR, LSR
8'b01xx_xx10: // ROR, LSR
op <= OP_A;
8'b1000_1000, // DEY
8'b1100_1010, // DEX
8'b110?_?110, // DEC
8'b11??_??01, // CMP, SBC
8'b11?0_0?00, // CPX, CPY (imm, zpg)
8'b11?0_1100: op <= OP_SUB;
8'b110x_x110, // DEC
8'b11xx_xx01, // CMP, SBC
8'b11x0_0x00, // CPX, CPY (imm, zpg)
8'b11x0_1100: op <= OP_SUB;
8'b010?_??01, // EOR
8'b00??_??01: // ORA, AND
8'b010x_xx01, // EOR
8'b00xx_xx01: // ORA, AND
op <= { 2'b11, IR[6:5] };
default: op <= OP_ADD;
@ -1170,13 +1171,12 @@ always @(posedge clk )
always @(posedge clk )
if( state == DECODE && RDY )
casez( IR )
8'b0010_?100: // BIT zp/abs
casex( IR )
8'b0010_x100: // BIT zp/abs
bit_ins <= 1;
default: bit_ins <= 0;
endcase
/*
* special instructions
*/