2010年10月29日金曜日

神のBIN2BCD

BIN2BCDについてネットで検索していたら凄いのを見つけてしまった。
このサイトだ。  (※. リンク先のサイトが存在しなくなっていたのでリンクを削除しました。 2016.09.19)
ここに引用しておく。

~~ 引用ここから ~~
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 件のコメント:

コメントを投稿

自作CPUで遊ぶ 22

今使用しているモータードライバはDM556Dというものだが、このドライバはMicro Stepが 800 [pulse/rev] 〜 40000 [pulse/rev]の範囲で設定できる。 Mi...