ここに引用しておく。
~~ 引用ここから ~~
module bin2bcd_m16
(
input wire [15:0] bin_in, // binary number in
output wire [15:0] bcd_out // BCD digits out
);
reg [3:0] ones, tens, huns, thous;
integer i;
assign bcd_out[3:0] = ones;
assign bcd_out[7:4] = tens;
assign bcd_out[11:8] = huns;
assign bcd_out[15:12] = thous;
always @(*) begin
thous = 0;
huns = 0;
tens = 0;
ones = 0;
for(i=15; i>=0; i=i-1) begin
{thous, huns, tens, ones} = {thous[2:0],huns,tens,ones,bin_in[i]};
if(ones >= 5 && i > 0) ones = ones + 3;
if(tens >= 5 && i > 0) tens = tens + 3;
if(huns >= 5 && i > 0) huns = huns + 3;
if(thous >= 5 && i > 0) thous = thous + 3;
end
end
endmodule
~~ 引用ここまで ~~
なんと、これでBinaryからBCDへの変換が出来るようだ。
コーディングの仕方は教科書では決して推奨されないスタイルだけれども凄い。
こんなんでちゃんと合成できるんだろうか?
ISEで合成してみた。。
ちゃんと合成できた。
シミュレーションをしてみた。
テストベンチは以下のようにした。
RTLとP&R後のネットリストの両方に同じ値を入力して、テストベンチ内部で生成した期待値と両者の出力が一致するかを見ている。
`timescale 1ns/1ps
module tb;
reg clk;
reg [15:0] bin_in;
wire [15:0] bcd_rtl,bcd_map;
reg [3:0] d3,d2,d1,d0;
integer r,err;
bin2bcd_m16 i_rtl ( .bin_in (bin_in), .bcd_out(bcd_rtl));
bin2bcd_m16_map i_map ( .bin_in (bin_in), .bcd_out(bcd_map));
initial begin
clk = 0;
forever clk = #5 ~clk;
end
initial begin
bin_in = 0;
err = 0;
wait (!glbl.GSR);
@(posedge clk); #1;
@(posedge clk); #1;
for (bin_in = 0; bin_in < 10000; bin_in = bin_in + 1)
begin
@(posedge clk); #1;
d3 = bin_in / 1000;
r = bin_in % 1000;
d2 = r / 100;
r = r % 100;
d1 = r / 10;
d0 = r % 10;
if ((bcd_rtl !== {d3,d2,d1,d0}) ||
(bcd_map !== {d3,d2,d1,d0}) ||
(bcd_map !== bcd_rtl)) begin
$display("ERROR!!! in=%d,exp=%x->rtl=%x,map=%x",
bin_in,{d3,d2,d1,d0}, bcd_rtl, bcd_map);
err = err+1;
end else begin
$display("O K !!! in=%d,exp=%x->rtl=%x,map=%x",
bin_in,{d3,d2,d1,d0}, bcd_rtl, bcd_map);
end
end
if (err == 0)
$display("END OF SIMULATION WITH NO ERROR");
else
$display("END OF SIMULATION WITH %d ERROR(S)", err);
$finish;
end
endmodule
icarus verilogでsimulationした。

エラーなし!! 凄い!!
こういうアルゴリズムをサクッと創造できるようになりたいもんだ。
私にとってみると正に神のBIN2BCDだ。
すげ~、凄い、凄すぎます。きゃ~~興奮しちゃう。
私もDRAMCの作成を頑張ろう。
0 件のコメント:
コメントを投稿