diff options
Diffstat (limited to '')
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | bin2bcd.sv | 52 | ||||
| -rw-r--r-- | ntoa.sv | 9 | ||||
| -rw-r--r-- | top.sv | 6 |
4 files changed, 26 insertions, 45 deletions
| @@ -3,6 +3,8 @@ HEADERS := $(wildcard **.svh) | |||
| 3 | CPPSRCS := $(wildcard **.cpp) | 3 | CPPSRCS := $(wildcard **.cpp) |
| 4 | COLLATERAL := $(wildcard **.hex) | 4 | COLLATERAL := $(wildcard **.hex) |
| 5 | 5 | ||
| 6 | OPTS ?= | ||
| 7 | |||
| 6 | QUARTUS ?= /opt/quartus-lite/20.1.1.720/ | 8 | QUARTUS ?= /opt/quartus-lite/20.1.1.720/ |
| 7 | 9 | ||
| 8 | QUARTUS_SH := $(QUARTUS)/quartus/bin/quartus_sh | 10 | QUARTUS_SH := $(QUARTUS)/quartus/bin/quartus_sh |
| @@ -23,7 +25,7 @@ pof: build/toycpu.pof | |||
| 23 | 25 | ||
| 24 | build/Vtop: $(VERILOG) $(HEADERS) $(CPPSRCS) $(COLLATERAL) | 26 | build/Vtop: $(VERILOG) $(HEADERS) $(CPPSRCS) $(COLLATERAL) |
| 25 | @mkdir -p build | 27 | @mkdir -p build |
| 26 | verilator +1800-2017ext+sv -Wall -Wno-BLKSEQ -O3 --Mdir build --trace --cc --build --exe --top-module top $(VERILOG) $(CPPSRCS) | 28 | verilator +1800-2017ext+sv -Wall -Wno-BLKSEQ -O3 $(OPTS) --Mdir build --trace --cc --build --exe --top-module top $(VERILOG) $(CPPSRCS) |
| 27 | 29 | ||
| 28 | build/toycpu.pof: build/toycpu.qpf $(VERILOG) $(COLLATERAL) | 30 | build/toycpu.pof: build/toycpu.qpf $(VERILOG) $(COLLATERAL) |
| 29 | cd build; $(QUARTUS_SH) --flow compile toycpu | 31 | cd build; $(QUARTUS_SH) --flow compile toycpu |
| @@ -15,37 +15,8 @@ module bin2bcd | |||
| 15 | , output bit [DIGITS-1:0][BASE_BITS-1:0] bcd_data | 15 | , output bit [DIGITS-1:0][BASE_BITS-1:0] bcd_data |
| 16 | ); | 16 | ); |
| 17 | 17 | ||
| 18 | // FIXME I don't think this works for odd bases | ||
| 19 | |||
| 20 | localparam BASE_BITS = $clog2(BASE); | 18 | localparam BASE_BITS = $clog2(BASE); |
| 21 | localparam SLACK = (1 << BASE_BITS) - BASE; | ||
| 22 | localparam DIGITS = $rtoi($ceil($ln(1 << BITS) / $ln(BASE))); | 19 | localparam DIGITS = $rtoi($ceil($ln(1 << BITS) / $ln(BASE))); |
| 23 | localparam CARRY_TEST = $rtoi($ceil($itor(BASE) / 2)); | ||
| 24 | localparam CARRY_ADD = $rtoi($ceil($itor(SLACK) / 2)); | ||
| 25 | |||
| 26 | `ifdef DEBUG_BIN2BCD | ||
| 27 | |||
| 28 | initial $display("%d BITS", BITS); | ||
| 29 | initial $display("%d BASE", BASE); | ||
| 30 | initial $display("%d BASE_BITS", BASE_BITS); | ||
| 31 | initial $display("%d SLACK", SLACK); | ||
| 32 | initial $display("%d DIGITS", DIGITS); | ||
| 33 | initial $display("%d CARRY_TEST", CARRY_TEST); | ||
| 34 | initial $display("%d CARRY_ADD", CARRY_ADD); | ||
| 35 | |||
| 36 | initial for(int i = 0; i < BASE; i = i + 1) begin | ||
| 37 | // verilator lint_off WIDTH | ||
| 38 | automatic bit [BASE_BITS-1:0] n = i; | ||
| 39 | automatic bit [BASE_BITS-1:0] a = n >= CARRY_TEST ? CARRY_ADD : 0; | ||
| 40 | automatic bit [BASE_BITS-1:0] s = n + a; | ||
| 41 | // verilator lint_on WIDTH | ||
| 42 | automatic bit c; | ||
| 43 | automatic bit [BASE_BITS-1:0] d; | ||
| 44 | {c, d} = {s, 1'b0}; | ||
| 45 | $display("\t\t(%x + %x => %x) * 2 => %x:%x", n, a, s, c, d); | ||
| 46 | end | ||
| 47 | |||
| 48 | `endif | ||
| 49 | 20 | ||
| 50 | bit bin_b_valid; | 21 | bit bin_b_valid; |
| 51 | bit [BITS-1:0] bin_b_data; | 22 | bit [BITS-1:0] bin_b_data; |
| @@ -65,7 +36,7 @@ always_ff @(posedge clk) begin | |||
| 65 | bin_b_data = `bin_data; | 36 | bin_b_data = `bin_data; |
| 66 | bcd = 0; | 37 | bcd = 0; |
| 67 | work = BITS; | 38 | work = BITS; |
| 68 | for (int i = 0; i < BITS && i < MAX_SKIP; i = i + 1) begin | 39 | for (int i = 0; i < BITS && i < MAX_SKIP; ++i) begin |
| 69 | if (bin_b_data[BITS-1]) break; | 40 | if (bin_b_data[BITS-1]) break; |
| 70 | bin_b_data = { bin_b_data[BITS-2:0], 1'b0 }; | 41 | bin_b_data = { bin_b_data[BITS-2:0], 1'b0 }; |
| 71 | work = work - 1; | 42 | work = work - 1; |
| @@ -73,14 +44,19 @@ always_ff @(posedge clk) begin | |||
| 73 | end | 44 | end |
| 74 | 45 | ||
| 75 | if (bin_b_valid && work != 0) begin | 46 | if (bin_b_valid && work != 0) begin |
| 76 | for (int i = 0; i < DIGITS; i = i + 1) | 47 | automatic bit carry = bin_b_data[BITS-1]; |
| 77 | // verilator lint_off WIDTH | 48 | for (int i = 0; i < DIGITS; ++i) begin |
| 78 | if (bcd[i] >= CARRY_TEST) bcd[i] = bcd[i] + CARRY_ADD; | 49 | {carry, bcd[i]} = {bcd[i], carry}; |
| 79 | // verilator lint_on WIDTH | 50 | if ({carry, bcd[i]} >= BASE) begin |
| 80 | for (int i = DIGITS - 1; i > 0; i = i - 1) | 51 | // verilator lint_off WIDTH |
| 81 | bcd[i] = { bcd[i][BASE_BITS-2:0], bcd[i-1][BASE_BITS-1] }; | 52 | bcd[i] = {carry, bcd[i]} - BASE; |
| 82 | bcd[0] = { bcd[0][BASE_BITS-2:0], bin_b_data[BITS-1] }; | 53 | // verilator lint_on WIDTH |
| 83 | bin_b_data = { bin_b_data[BITS-2:0], 1'b0 }; | 54 | carry = 1; |
| 55 | end | ||
| 56 | end | ||
| 57 | assert(!carry); | ||
| 58 | |||
| 59 | bin_b_data = bin_b_data << 1; | ||
| 84 | 60 | ||
| 85 | work = work - 1; | 61 | work = work - 1; |
| 86 | end | 62 | end |
| @@ -1,5 +1,6 @@ | |||
| 1 | module ntoa | 1 | module ntoa |
| 2 | #( BITS = 8 | 2 | #( BITS = 8 |
| 3 | , BASE = 10 | ||
| 3 | ) | 4 | ) |
| 4 | ( input bit clk | 5 | ( input bit clk |
| 5 | , input bit reset | 6 | , input bit reset |
| @@ -19,7 +20,7 @@ bit [b2b.DIGITS-1:0][b2b.BASE_BITS-1:0] bcd_data; | |||
| 19 | 20 | ||
| 20 | bin2bcd | 21 | bin2bcd |
| 21 | #( .BITS(BITS) | 22 | #( .BITS(BITS) |
| 22 | , .BASE(10) | 23 | , .BASE(BASE) |
| 23 | ) b2b | 24 | ) b2b |
| 24 | ( .clk(clk) | 25 | ( .clk(clk) |
| 25 | , .reset(reset) | 26 | , .reset(reset) |
| @@ -50,10 +51,10 @@ always_ff @(posedge clk) begin | |||
| 50 | // verilator lint_off WIDTH | 51 | // verilator lint_off WIDTH |
| 51 | work = b2b.DIGITS; | 52 | work = b2b.DIGITS; |
| 52 | // verilator lint_on WIDTH | 53 | // verilator lint_on WIDTH |
| 53 | for (int i = 0; i < b2b.DIGITS - 1; i = i + 1) begin | 54 | for (int i = 0; i < b2b.DIGITS - 1; ++i) begin |
| 54 | if (bcd_b_data[b2b.DIGITS-1] != 0) break; | 55 | if (bcd_b_data[b2b.DIGITS-1] != 0) break; |
| 55 | bcd_b_data = { bcd_b_data[b2b.DIGITS-2:0], {b2b.BASE_BITS{1'b0}} }; | 56 | bcd_b_data = { bcd_b_data[b2b.DIGITS-2:0], {b2b.BASE_BITS{1'b0}} }; |
| 56 | work = work - 1; | 57 | --work; |
| 57 | end | 58 | end |
| 58 | end | 59 | end |
| 59 | 60 | ||
| @@ -68,7 +69,7 @@ always_ff @(posedge clk) begin | |||
| 68 | a_data = "a" + bcd_b_data[b2b.DIGITS-1] - 10; | 69 | a_data = "a" + bcd_b_data[b2b.DIGITS-1] - 10; |
| 69 | // verilator lint_off WIDTH | 70 | // verilator lint_off WIDTH |
| 70 | bcd_b_data = { bcd_b_data[b2b.DIGITS-2:0], {b2b.BASE_BITS{1'b0}} }; | 71 | bcd_b_data = { bcd_b_data[b2b.DIGITS-2:0], {b2b.BASE_BITS{1'b0}} }; |
| 71 | work = work - 1; | 72 | --work; |
| 72 | end else begin | 73 | end else begin |
| 73 | a_valid = 1; | 74 | a_valid = 1; |
| 74 | a_data = ","; | 75 | a_data = ","; |
| @@ -1,5 +1,6 @@ | |||
| 1 | module top | 1 | module top |
| 2 | #( FIB_BITS = 16 | 2 | #( FIB_BITS = 16 |
| 3 | , FIB_BASE = 10 | ||
| 3 | , ROM_BITS = 8 | 4 | , ROM_BITS = 8 |
| 4 | ) | 5 | ) |
| 5 | ( input bit clk // verilator public | 6 | ( input bit clk // verilator public |
| @@ -58,6 +59,7 @@ bit [7:0] fib_a_data; | |||
| 58 | 59 | ||
| 59 | ntoa | 60 | ntoa |
| 60 | #( .BITS(FIB_BITS) | 61 | #( .BITS(FIB_BITS) |
| 62 | , .BASE(FIB_BASE) | ||
| 61 | ) fib_ntoa | 63 | ) fib_ntoa |
| 62 | ( .clk(clk) | 64 | ( .clk(clk) |
| 63 | , .reset(reset) | 65 | , .reset(reset) |
| @@ -97,9 +99,9 @@ always_ff @(posedge clk) begin | |||
| 97 | if (!tx_valid && (data != 0)) begin | 99 | if (!tx_valid && (data != 0)) begin |
| 98 | tx_valid = 1; | 100 | tx_valid = 1; |
| 99 | tx_data = data; | 101 | tx_data = data; |
| 100 | addr = addr + 1; | 102 | ++addr; |
| 101 | end else if (data == 0) begin | 103 | end else if (data == 0) begin |
| 102 | addr = addr + 1; | 104 | ++addr; |
| 103 | state = state.next; | 105 | state = state.next; |
| 104 | end | 106 | end |
| 105 | end | 107 | end |
