Skip to content

Commit b112c80

Browse files
committed
improved wide serial Binary -> BCD based on Xilinx App Note XAPP 029
1 parent 169d312 commit b112c80

File tree

7 files changed

+224
-247
lines changed

7 files changed

+224
-247
lines changed

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
iverilog -o $@ $^
88

99
# tagets
10-
default: bin/pcap.lxt bin/pcap10gb.lxt bin/obin2bcd8.lxt bin/obin2bcdN.lxt bin/ohash.lxt bin/ohashmap.lxt bin/olittletoe.lxt \
10+
default: bin/pcap.lxt bin/pcap10gb.lxt bin/obin2bcd8.lxt bin/obin2bcd_serial.lxt bin/ohash.lxt bin/ohashmap.lxt bin/olittletoe.lxt \
1111
bin/oxml.lxt
1212
clean:
1313
RM bin/*
@@ -27,8 +27,8 @@ bin/obin2bcd8.lxt: bin/obin2bcd8.bin
2727
bin/obin2bcd8.bin: bcd/bin2bcd8*.v bcd/add3.v
2828
iverilog -o $@ $^
2929

30-
bin/obin2bcdN.lxt: bin/obin2bcdN.bin
31-
bin/obin2bcdN.bin: bcd/bin2bcdN*.v
30+
bin/obin2bcd_serial.lxt: bin/obin2bcd_serial.bin
31+
bin/obin2bcd_serial.bin: bcd/bin2bcd_serial*.v
3232
iverilog -o $@ $^
3333

3434
bin/ohash.lxt: bin/ohash.bin

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Basic 1G line-speed, read-only MAC/IP/TCP stack to follow a specific TCP session
1414

1515
bcd (synth)
1616
-----------
17-
Convertors to and from binary to numerical ascii/bcd
17+
Convertor from binary to binary coded decimal (BCD). `bin2bcd_serial.v` can be sythesised to any required width and takes one cycle per input binary bit.
1818

1919
xml (synth)
2020
-----------

bcd/bin2bcdN.v

Lines changed: 0 additions & 175 deletions
This file was deleted.

bcd/bin2bcdN_test.v

Lines changed: 0 additions & 68 deletions
This file was deleted.

bcd/bin2bcd_serial.v

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//
2+
// Convert a binary input to binary-coded-decimal (BCD) output.
3+
// Each binary coded decimal digit occupies 4-bits of the ouput bus.
4+
// The number of output digits and input binary width are configurable. It
5+
// is possible to choose binary input widths that will cause the BCD output to overflow,
6+
// so care must be exercised by the invokee.
7+
//
8+
// The implementation follows Xlinx App Note "XAPP 029". There is a block instantiated for
9+
// each BCD digit, which recieves the binary data serially. It takes n cycles to convert an
10+
// n-bit binary input. Each BCD digit has a registered carry output to the next digit.
11+
//
12+
// There is no explicit reset, each new conversion request clears all previous state whether
13+
// a conversion was in progress or not.
14+
`timescale 1ns / 1ps
15+
16+
module bin2bcd_serial #(
17+
parameter BINARY_BITS = 16, // # of bits of binary input
18+
parameter BCD_DIGITS = 5 // # of digits of BCD output
19+
) (
20+
input wire clock,
21+
input wire start,
22+
input wire [BINARY_BITS-1:0] binary_in,
23+
24+
output wire [4*BCD_DIGITS-1:0] bcd_out, // output bus
25+
output wire done // indicate conversion done
26+
);
27+
28+
// binary input shift register and counter
29+
reg [BINARY_BITS-1:0] binary_shift = 0;
30+
reg [$clog2(BINARY_BITS):0] binary_count = 0;
31+
assign done = binary_count == 0;
32+
33+
always @(posedge clock) begin
34+
if(start) begin
35+
binary_shift <= binary_in;
36+
binary_count <= BINARY_BITS;
37+
end else if (binary_count != 0) begin
38+
binary_shift <= { binary_shift[BINARY_BITS-2:0], 1'b0 };
39+
binary_count <= binary_count - 1'b1;
40+
end
41+
end
42+
43+
wire [BCD_DIGITS:0] bcd_carry;
44+
assign bcd_carry[0] = binary_shift[BINARY_BITS-1]; // MSB
45+
wire clock_enable = start | ~done;
46+
47+
genvar j;
48+
generate
49+
for (j = 0; j < BCD_DIGITS; j=j+1) begin: DIGITS
50+
bcd_digit digit (
51+
.clock( clock ),
52+
.init( start ),
53+
.mod_in( bcd_carry[j] ),
54+
.mod_out( bcd_carry[j+1] ),
55+
.digit( bcd_out[4*j +: 4] ),
56+
.ce( clock_enable )
57+
);
58+
end
59+
endgenerate
60+
61+
endmodule
62+
63+
// Regarding the init signal: At first it seems that digit[0] should have an explicit clear ("& ~init")
64+
// like the rest. However digit[0] loads mod_in unconditionaly, and since mod_out is masked
65+
// by & ~init this ensures digit[0] of higher digits is cleared during the init cycle whilst not loosing
66+
// a cycle in the conversion for synchronous clearing.
67+
module bcd_digit (
68+
input wire clock,
69+
input wire ce,
70+
input wire init,
71+
input wire mod_in,
72+
output wire mod_out,
73+
output reg [3:0] digit
74+
);
75+
76+
wire fiveOrMore = digit >= 5;
77+
assign mod_out = fiveOrMore & ~init;
78+
79+
always @(posedge clock) begin
80+
if (ce) begin
81+
digit[0] <= mod_in;
82+
digit[1] <= ~init & (~mod_out ? digit[0] : ~digit[0]);
83+
digit[2] <= ~init & (~mod_out ? digit[1] : digit[1] == digit[0]);
84+
digit[3] <= ~init & (~mod_out ? digit[2] : digit[0] & digit[3]);
85+
end
86+
end
87+
88+
endmodule

0 commit comments

Comments
 (0)