Skip to content

Commit

Permalink
Reimplement BCD using bit shifts
Browse files Browse the repository at this point in the history
  • Loading branch information
pwmarcz committed Dec 8, 2018
1 parent 7bf8270 commit d89da34
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 29 deletions.
27 changes: 27 additions & 0 deletions bcd.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
`default_nettype none

module bcd(input wire [7:0] abc,
output wire [1:0] a,
output reg [3:0] b,
output reg [3:0] c);
assign a = abc >= 200 ? 2 : abc >= 100 ? 1 : 0;
wire [6:0] bc = abc - 100 * a;

// See Hacker's Delight, Integer division by constants:
// https://www.hackersdelight.org/divcMore.pdf
reg [6:0] q;
reg [3:0] r;
always @(*) begin
q = (bc >> 1) + (bc >> 2);
q = q + (q >> 4);
q = q >> 3;
r = bc - q * 10;
if (r < 10) begin
b = q;
c = r;
end else begin
b = q + 1;
c = r - 10;
end
end
endmodule
26 changes: 26 additions & 0 deletions bcd_tb.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
`include "bcd.v"

module top;
reg [7:0] abc = 0;
wire [1:0] a;
wire [3:0] b, c;

bcd bcd0(abc, a, b, c);

initial begin
$monitor($time, " %d -> %d %d %d", abc, a, b, c);
$dumpfile(`VCD_FILE);
$dumpvars;

repeat (256) begin
#1;
if (!(a < 10 && b < 10 && c < 10))
$fatal(1, "bad result");
if (!(abc == a * 100 + b * 10 + c))
$fatal(2, "bad result");

abc += 1;
end
#1 $finish;
end
endmodule
43 changes: 14 additions & 29 deletions cpu.v
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
`include "bcd.v"

module cpu(input wire clk, output wire [11:0] debug_pc);
assign debug_pc = pc;

Expand Down Expand Up @@ -50,17 +52,9 @@ module cpu(input wire clk, output wire [11:0] debug_pc);

reg[4:0] state = STATE_FETCH_HI;

/*
BCD algorithm:
1. STATE_BCD_1: Store hundreds digit, remove it from vx
2. STATE_BCD_2: Keep removing 10 from vx to calculate tens digit, store it
3. STATE_BCD_3: Store rest of vx as ones digit
*/
// BCD first digit
wire [1:0] bcd_vx_1 = vx >= 200 ? 2 : vx >= 100 ? 1 : 0;
// BCD second digit
reg [3:0] bcd_vx_2;
wire bcd_vx_2_ready = vx < 10;
wire [1:0] bcd_1;
wire [3:0] bcd_2, bcd_3;
bcd bcd0(vx, bcd_1, bcd_2, bcd_3);

// Memory loads and stores
always @(*) begin
Expand Down Expand Up @@ -134,18 +128,17 @@ module cpu(input wire clk, output wire [11:0] debug_pc);
STATE_BCD_1: begin
mem_write = 1;
mem_write_idx = addr;
mem_write_byte = {6'b0, bcd_vx_1};
mem_write_byte = {6'b0, bcd_1};
end
STATE_BCD_2: begin
mem_write = 1;
mem_write_idx = addr + 1;
mem_write_byte = {4'b0, bcd_2};
end
STATE_BCD_2:
if (bcd_vx_2_ready) begin
mem_write = 1;
mem_write_idx = addr + 1;
mem_write_byte = {4'b0, bcd_vx_2};
end
STATE_BCD_3: begin
mem_write = 1;
mem_write_idx = addr + 2;
mem_write_byte = vx;
mem_write_byte = {4'b0, bcd_3};
end
endcase
end
Expand Down Expand Up @@ -238,18 +231,10 @@ module cpu(input wire clk, output wire [11:0] debug_pc);
else begin
transfer_counter <= transfer_counter - 1;
end
STATE_BCD_1: begin
STATE_BCD_1:
state <= STATE_BCD_2;
vx <= vx - bcd_vx_1 * 100;
bcd_vx_2 <= 0;
end
STATE_BCD_2:
if (bcd_vx_2_ready)
state <= STATE_BCD_3;
else begin
bcd_vx_2 <= bcd_vx_2 + 1;
vx <= vx - 10;
end
state <= STATE_BCD_3;
STATE_BCD_3:
state <= STATE_FETCH_HI;
STATE_DECODE: begin
Expand Down

0 comments on commit d89da34

Please sign in to comment.