`include "utils.svh" module ntoa #( BITS = 8 , BASE = 10 , BASE_BITS = $clog2(BASE) , DIGITS = 3 // should be ceil[log(2**BITS) base BASE] which is hard to do in Verilog :-( ) ( input bit clk , input bit reset , output bit n_ready , input bit n_valid `define n_valid `past(n_valid) , input bit [BITS-1:0] n_data `define n_data `past(n_data) , input bit a_ready `define a_ready `past(a_ready) , output bit a_valid , output bit [7:0] a_data ); bit bcd_ready; bit bcd_valid; bit [DIGITS-1:0][BASE_BITS-1:0] bcd_data; bin2bcd #( .BITS(BITS) , .BASE(BASE) , .BASE_BITS(BASE_BITS) , .DIGITS(DIGITS) ) b2b ( .clk(clk) , .reset(reset) , .bin_ready(n_ready) , .bin_valid(n_valid) , .bin_data(n_data) , .bcd_ready(bcd_ready) , .bcd_valid(bcd_valid) `define bcd_valid `past(bcd_valid) , .bcd_data(bcd_data) `define bcd_data `past(bcd_data) ); bit bcd_b_valid; bit [DIGITS-1:0][BASE_BITS-1:0] bcd_b_data; bit [$clog2(DIGITS):0] work; always_ff @(posedge clk) begin if (reset) begin a_valid = 0; bcd_ready = 0; bcd_b_valid = 0; end else begin if (bcd_ready && `bcd_valid) begin bcd_b_valid = 1; bcd_b_data = `bcd_data; // verilator lint_off WIDTH work = DIGITS; // verilator lint_on WIDTH for (int i = 0; i < DIGITS - 1; ++i) begin if (bcd_b_data[DIGITS-1] != 0) break; bcd_b_data = { bcd_b_data[DIGITS-2:0], {BASE_BITS{1'b0}} }; --work; end end if (`a_ready) a_valid = 0; if (!a_valid && bcd_b_valid) begin if (work != 0) begin a_valid = 1; // verilator lint_off WIDTH if (bcd_b_data[DIGITS-1] < 10) a_data = "0" + bcd_b_data[DIGITS-1]; else a_data = "a" + bcd_b_data[DIGITS-1] - 10; // verilator lint_off WIDTH bcd_b_data = { bcd_b_data[DIGITS-2:0], {BASE_BITS{1'b0}} }; --work; end else begin a_valid = 1; a_data = ","; bcd_b_valid = 0; end end bcd_ready = !bcd_b_valid; end end endmodule