Implementation of the decimal mode.

Let's talk about anything related to the 6502 microprocessor.
User avatar
Windfall
Posts: 229
Joined: 27 Nov 2011
Location: Amsterdam, Netherlands
Contact:

Re: Implementation of the decimal mode.

Post by Windfall »

Since no core I tried is consistent with the real 65C02 when it comes to 'decimal mode' results for non-BCD operands, here is a piece of Verilog that I created for my own 65C02 core, that actually is consistent with the real thing.

Note that C is valid as well, and N and Z are 'result[7]' and 'result == 8'h00' as usual. Make up your very own V flag (personally, I find the notion that BCD numbers can be negative and specifically, then, 0x80 and up, ludicrous and completely arbitrary).

Enjoy (if this is useful to you).

Code: Select all


module BCD_ADD
(
   a_in,
   data_in,
   carry_in,
   fixup_in,
   sbc_else_adc,
   data_out,
   carry_out,
   fixup_out
);

   input  [3:0] a_in;
   input  [3:0] data_in;
   input        carry_in;
   input        fixup_in;
   input        sbc_else_adc;
   output [3:0] data_out;
   output       carry_out;
   output       fixup_out;

   wire [3:0] adder_data;
   wire [4:0] adder_result;
   wire       adder_carry;
   wire       digit_not_bcd;
   reg  [3:0] digit_add_data;
   reg        digit_add_carry;
   wire [4:0] digit_result;

   assign adder_data = sbc_else_adc ? ~data_in : data_in;

   assign adder_result = a_in + adder_data + carry_in;

   assign adder_carry = adder_result[4];

   assign digit_not_bcd = (adder_result[3:0] > 4'd9);

   always @(*)
     casex ({ sbc_else_adc, adder_carry, digit_not_bcd })
       3'b000 : { digit_add_data, digit_add_carry } = { 4'h0, 1'b0     };
       3'b0xx : { digit_add_data, digit_add_carry } = { 4'h6, 1'b0     };
       3'b10x : { digit_add_data, digit_add_carry } = { 4'h9, fixup_in };
       3'b11x : { digit_add_data, digit_add_carry } = { 4'hF, fixup_in };
     endcase

   assign digit_result = adder_result[3:0] + digit_add_data + digit_add_carry;

   assign data_out = digit_result[3:0];

   assign carry_out = adder_carry | (~sbc_else_adc & digit_not_bcd);

   assign fixup_out = digit_result[4];

endmodule

BCD_ADD nibble_0
(
  .a_in(a_in[3:0]),
  .data_in(data_in[3:0]),
  .carry_in(carry_in),
  .fixup_in(1'b1),
  .sbc_else_adc(operation[2]),
  .data_out(d_adder_result[3:0]),
  .carry_out(d_nibble_carry),
  .fixup_out(d_nibble_fixup)
);

BCD_ADD nibble_1
(
  .a_in(a_in[7:4]),
  .data_in(data_in[7:4]),
  .carry_in(d_nibble_carry),
  .fixup_in(d_nibble_fixup),
  .sbc_else_adc(operation[2]),
  .data_out(d_adder_result[7:4]),
  .carry_out(d_adder_result[8]),
  .fixup_out()
);

Chromatix
Posts: 1462
Joined: 21 May 2018

Re: Implementation of the decimal mode.

Post by Chromatix »

I think I would take the convention that V represents an overflow from bit 6 to bit 7. It's not very useful, but it's consistent with the binary operation.
Post Reply