コメントが長くなりすぎました。
次のブロック図を検討してください。

これは展開されたループ ( for i in 0 to 7 loop
) を表し、LS BCD 桁の i = 2 の前に +3 の追加が発生せず、中央の BCD 桁の i = 5 の前に +3 の追加が発生せず、MS BCD 桁で調整が発生しないことを示しています。これは、静的な「0」値の一部を構成します。
これにより、合計 7 つの add3 モジュールが得られます (if ステートメントと条件付き add +3 で表されます)。
これは VHDL で示されます。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity bin8bcd is
port (
bin: in std_logic_vector (7 downto 0);
bcd: out std_logic_vector (11 downto 0)
);
end entity;
architecture struct of bin8bcd is
procedure add3 (signal bin: in std_logic_vector (3 downto 0);
signal bcd: out std_logic_vector (3 downto 0)) is
variable is_gt_4: std_logic;
begin
is_gt_4 := bin(3) or (bin(2) and (bin(1) or bin(0)));
if is_gt_4 = '1' then
-- if to_integer(unsigned (bin)) > 4 then
bcd <= std_logic_vector(unsigned(bin) + "0011");
else
bcd <= bin;
end if;
end procedure;
signal U0bin,U1bin,U2bin,U3bin,U4bin,U5bin,U6bin:
std_logic_vector (3 downto 0);
signal U0bcd,U1bcd,U2bcd,U3bcd,U4bcd,U5bcd,U6bcd:
std_logic_vector (3 downto 0);
begin
U0bin <= '0' & bin (7 downto 5);
U1bin <= U0bcd(2 downto 0) & bin(4);
U2bin <= U1bcd(2 downto 0) & bin(3);
U3bin <= U2bcd(2 downto 0) & bin(2);
U4bin <= U3bcd(2 downto 0) & bin(1);
U5bin <= '0' & U0bcd(3) & U1bcd(3) & U2bcd(3);
U6bin <= U5bcd(2 downto 0) & U3bcd(3);
U0: add3(U0bin,U0bcd);
U1: add3(U1bin,U1bcd);
U2: add3(U2bin,U2bcd);
U3: add3(U3bin,U3bcd);
U4: add3(U4bin,U4bcd);
U5: add3(U5bin,U5bcd);
U6: add3(U6bin,U6bcd);
OUTP:
bcd <= '0' & '0' & U5bcd(3) & U6bcd & U4bcd & bin(0);
end architecture;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity bin8bcd_tb is
end entity;
architecture foo of bin8bcd_tb is
signal bin: std_logic_vector (7 downto 0) := (others => '0');
-- (initialized to prevent those annoying metavalue reports)
signal bcd: std_logic_vector (11 downto 0);
begin
DUT:
entity work.bin8bcd
port map (
bin => bin,
bcd => bcd
);
STIMULUS:
process
begin
for i in 0 to 255 loop
bin <= std_logic_vector(to_unsigned(i,8));
wait for 1 ns;
end loop;
wait for 1 ns;
wait;
end process;
end architecture;
付属のテスト ベンチを実行すると、次の結果が得られます。

波形全体をスクロールすると、001 から 255 までのすべての bcd 出力が存在し、説明されている (穴がない) ことがわかります。「X」や「U」はどこにもありません。
i = 7 を示すブロック線図の表現から、最終シフト後に加算 +3 が発生しないことがわかります。
また、bcd の LSB は常に bin の LSB であり、bcd(11) と bcd(10) は常に「0」であることに注意してください。
add3 は手動で最適化して、論理演算子を使用して 3 ずつインクリメントを作成し、bin から派生したメタ値を報告する可能性を取り除くことができます (そして、それらはたくさんあります)。
私が知る限り、これは 8 ビット バイナリから 12 ビット BCD への変換の最も最適化された表現を表しています。
以前、私は espresso に入力を提供する C プログラムを作成しました (用語最小化ツール)。
/*
* binbcd.c - generates input to espresso for 8 bit binary
* to 12 bit bcd.
*
*/
#include <stdlib.h>
#include <stdio.h>
int main (argc, argv)
int argc;
char **argv;
{
int binary;
int bit;
char bcd_buff[4];
int digit;
int bcd;
printf(".i 8\n");
printf(".o 12\n");
for (binary = 0; binary < 256; binary++) {
for ( bit = 7; bit >= 0; bit--) {
if ((1 << bit) & binary)
printf("1");
else
printf("0");
}
digit = snprintf(bcd_buff,4,"%03d",binary); /* leading zeros */
if (digit != 3) {
fprintf(stderr,"%s: binary to string conversion failure, digit = %d\n",
argv[0],digit);
exit (-1);
}
printf (" "); /* input to output space */
for ( digit = 0; digit <= 2; digit++) {
bcd = bcd_buff[digit] - 0x30;
for (bit = 3; bit >= 0; bit--) {
if ((1 << bit) & bcd)
printf("1");
else
printf("0");
}
}
/* printf(" %03d",binary); */
printf("\n");
}
printf (".e\n");
exit (0);
次に、中間の用語を調べ始めると、上のブロック図に示されているものに直接たどり着きます。
もちろん、実際のコンポーネント add3 を使用したり、ネストされた generate ステートメントを使用してすべてを接続したりすることもできます。
if ステートメントを制約せずにループ ステートメント表現から同じ最小化されたハードウェアを取得することはできません (LS BCD 桁の場合は 2 < i < 7、中央の BCD 桁の場合は 5 < i < 7)。
下位のネストされた generate ステートメントで、短縮された構造表現に対して同じ制約を提供する必要があります。
add3 の論理演算子バージョンは、ダブル ダブルを使用したバイナリから BCD への変換に関する大学の講義スライドの PDF ページ 5 に示されています。前方ティックは否定表記に使用され、「+」は OR を表し、Adjacency は AND を表します。
add3 は次のようになります。
procedure add3 (signal bin: in std_logic_vector (3 downto 0);
signal bcd: out std_logic_vector (3 downto 0)) is
begin
bcd(3) <= bin(3) or
(bin(2) and bin(0)) or
(bin(2) and bin(1));
bcd(2) <= (bin(3) and bin(0)) or
(bin(2) and not bin(1) and not bin(0));
bcd(1) <= (bin(3) and not bin(0)) or
(not bin(2) and bin(1)) or
(bin(1) and bin(0));
bcd(0) <= (bin(3) and not bin(0)) or
(not bin(3) and not bin(2) and bin(0)) or
(bin(2) and bin(1) and not bin(0));
end procedure;
これにより、パッケージ numeric_std (または同等のもの) を context 句から削除できることに注意してください。
AND 条件で信号を同じ順序 (この場合は左から右) で記述すると、エスプレッソを使用する場合と同様に、複製された AND 条件が適切に表示されます。FPGA インプリメンテーションで中間の AND 項を使用する価値はありません。これらはすべてそのまま LUT に適合します。
add3 のエスプレッソ入力:
.i 4
.o 4
0000 0000
0001 0001
0010 0010
0011 0011
0100 0100
0101 1000
0110 1001
0111 1010
1000 1011
1001 1100
1010 ----
1011 ----
1100 ----
1101 ----
1110 ----
1111 ----
.e
そしてエスプレッソの出力 (espresso -eonset):
.i 4
.o 4
.p 8
-100 0100
00-1 0001
--11 0010
-01- 0010
-110 1001
-1-1 1000
1--1 1100
1--0 1011
.e
バイナリから BCD への変換の組み合わせの「深さ」を考慮すると、FPGA の場合、6 つの LUT (6 番目は次の何かへの入力) です。これにより、変換が 1 クロックで発生する場合、クロック速度が 100 MHz 程度に制限される可能性があります。
パイプライン処理またはシーケンシャル ロジック (クロック ループ) を使用することで、FPGA を 6 クロックで実行しながら最速で実行できます。