From 0f95f3efbe4879bcf8b24aafda1c10dd95e9dd40 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Tue, 23 Mar 2021 19:01:29 -0700 Subject: Replace dibble dabble algorithm with variant that tests after the add. This makes it really easy to support odd bases. --- Makefile | 4 +++- bin2bcd.sv | 52 ++++++++++++++-------------------------------------- ntoa.sv | 9 +++++---- top.sv | 6 ++++-- 4 files changed, 26 insertions(+), 45 deletions(-) diff --git a/Makefile b/Makefile index d270ffb..9eff3ef 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,8 @@ HEADERS := $(wildcard **.svh) CPPSRCS := $(wildcard **.cpp) COLLATERAL := $(wildcard **.hex) +OPTS ?= + QUARTUS ?= /opt/quartus-lite/20.1.1.720/ QUARTUS_SH := $(QUARTUS)/quartus/bin/quartus_sh @@ -23,7 +25,7 @@ pof: build/toycpu.pof build/Vtop: $(VERILOG) $(HEADERS) $(CPPSRCS) $(COLLATERAL) @mkdir -p build - verilator +1800-2017ext+sv -Wall -Wno-BLKSEQ -O3 --Mdir build --trace --cc --build --exe --top-module top $(VERILOG) $(CPPSRCS) + verilator +1800-2017ext+sv -Wall -Wno-BLKSEQ -O3 $(OPTS) --Mdir build --trace --cc --build --exe --top-module top $(VERILOG) $(CPPSRCS) build/toycpu.pof: build/toycpu.qpf $(VERILOG) $(COLLATERAL) cd build; $(QUARTUS_SH) --flow compile toycpu diff --git a/bin2bcd.sv b/bin2bcd.sv index 266860c..8e618c6 100644 --- a/bin2bcd.sv +++ b/bin2bcd.sv @@ -15,37 +15,8 @@ module bin2bcd , output bit [DIGITS-1:0][BASE_BITS-1:0] bcd_data ); -// FIXME I don't think this works for odd bases - localparam BASE_BITS = $clog2(BASE); -localparam SLACK = (1 << BASE_BITS) - BASE; localparam DIGITS = $rtoi($ceil($ln(1 << BITS) / $ln(BASE))); -localparam CARRY_TEST = $rtoi($ceil($itor(BASE) / 2)); -localparam CARRY_ADD = $rtoi($ceil($itor(SLACK) / 2)); - -`ifdef DEBUG_BIN2BCD - -initial $display("%d BITS", BITS); -initial $display("%d BASE", BASE); -initial $display("%d BASE_BITS", BASE_BITS); -initial $display("%d SLACK", SLACK); -initial $display("%d DIGITS", DIGITS); -initial $display("%d CARRY_TEST", CARRY_TEST); -initial $display("%d CARRY_ADD", CARRY_ADD); - -initial for(int i = 0; i < BASE; i = i + 1) begin - // verilator lint_off WIDTH - automatic bit [BASE_BITS-1:0] n = i; - automatic bit [BASE_BITS-1:0] a = n >= CARRY_TEST ? CARRY_ADD : 0; - automatic bit [BASE_BITS-1:0] s = n + a; - // verilator lint_on WIDTH - automatic bit c; - automatic bit [BASE_BITS-1:0] d; - {c, d} = {s, 1'b0}; - $display("\t\t(%x + %x => %x) * 2 => %x:%x", n, a, s, c, d); -end - -`endif bit bin_b_valid; bit [BITS-1:0] bin_b_data; @@ -65,7 +36,7 @@ always_ff @(posedge clk) begin bin_b_data = `bin_data; bcd = 0; work = BITS; - for (int i = 0; i < BITS && i < MAX_SKIP; i = i + 1) begin + for (int i = 0; i < BITS && i < MAX_SKIP; ++i) begin if (bin_b_data[BITS-1]) break; bin_b_data = { bin_b_data[BITS-2:0], 1'b0 }; work = work - 1; @@ -73,14 +44,19 @@ always_ff @(posedge clk) begin end if (bin_b_valid && work != 0) begin - for (int i = 0; i < DIGITS; i = i + 1) - // verilator lint_off WIDTH - if (bcd[i] >= CARRY_TEST) bcd[i] = bcd[i] + CARRY_ADD; - // verilator lint_on WIDTH - for (int i = DIGITS - 1; i > 0; i = i - 1) - bcd[i] = { bcd[i][BASE_BITS-2:0], bcd[i-1][BASE_BITS-1] }; - bcd[0] = { bcd[0][BASE_BITS-2:0], bin_b_data[BITS-1] }; - bin_b_data = { bin_b_data[BITS-2:0], 1'b0 }; + automatic bit carry = bin_b_data[BITS-1]; + for (int i = 0; i < DIGITS; ++i) begin + {carry, bcd[i]} = {bcd[i], carry}; + if ({carry, bcd[i]} >= BASE) begin + // verilator lint_off WIDTH + bcd[i] = {carry, bcd[i]} - BASE; + // verilator lint_on WIDTH + carry = 1; + end + end + assert(!carry); + + bin_b_data = bin_b_data << 1; work = work - 1; end diff --git a/ntoa.sv b/ntoa.sv index 2a5c1ef..f8e9f43 100644 --- a/ntoa.sv +++ b/ntoa.sv @@ -1,5 +1,6 @@ module ntoa #( BITS = 8 + , BASE = 10 ) ( input bit clk , input bit reset @@ -19,7 +20,7 @@ bit [b2b.DIGITS-1:0][b2b.BASE_BITS-1:0] bcd_data; bin2bcd #( .BITS(BITS) - , .BASE(10) + , .BASE(BASE) ) b2b ( .clk(clk) , .reset(reset) @@ -50,10 +51,10 @@ always_ff @(posedge clk) begin // verilator lint_off WIDTH work = b2b.DIGITS; // verilator lint_on WIDTH - for (int i = 0; i < b2b.DIGITS - 1; i = i + 1) begin + for (int i = 0; i < b2b.DIGITS - 1; ++i) begin if (bcd_b_data[b2b.DIGITS-1] != 0) break; bcd_b_data = { bcd_b_data[b2b.DIGITS-2:0], {b2b.BASE_BITS{1'b0}} }; - work = work - 1; + --work; end end @@ -68,7 +69,7 @@ always_ff @(posedge clk) begin a_data = "a" + bcd_b_data[b2b.DIGITS-1] - 10; // verilator lint_off WIDTH bcd_b_data = { bcd_b_data[b2b.DIGITS-2:0], {b2b.BASE_BITS{1'b0}} }; - work = work - 1; + --work; end else begin a_valid = 1; a_data = ","; diff --git a/top.sv b/top.sv index 4acfdeb..cbb5b55 100644 --- a/top.sv +++ b/top.sv @@ -1,5 +1,6 @@ module top #( FIB_BITS = 16 + , FIB_BASE = 10 , ROM_BITS = 8 ) ( input bit clk // verilator public @@ -58,6 +59,7 @@ bit [7:0] fib_a_data; ntoa #( .BITS(FIB_BITS) + , .BASE(FIB_BASE) ) fib_ntoa ( .clk(clk) , .reset(reset) @@ -97,9 +99,9 @@ always_ff @(posedge clk) begin if (!tx_valid && (data != 0)) begin tx_valid = 1; tx_data = data; - addr = addr + 1; + ++addr; end else if (data == 0) begin - addr = addr + 1; + ++addr; state = state.next; end end -- cgit v1.2.3