FC2カウンター FPGAの部屋 2010年10月27日
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

2進数からBCDへの変換回路

必要があって10ビットの2進数から3桁のBCD(Binary-coded decimal)への変換回路を作りました。
私はビットごとに+6補正を入れながら、足していきました。変換するに11クロックです。
変換クロックに余裕があれば、BCDカウンタとバイナリカウンタ2つ作って、両方をカウントアップしていって、バイナリカウンタと10ビットの2進数が同じになったところの、BCDカウンタの値を使っても良いと思います。
武内さんから、10のn乗で割っていく方式を教えてくださいました。ありがとうございました。
自分のVHDLコードもブログに貼っておきます。

#使いものにならないよ。どうしてこんなコードを書いたの?とか、厳しい御指導があるかと思いますが、どうぞお手柔らかにお願いします。

-- Binary to Decimal Test

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.std_logic_arith.all;

entity binary_decimal_test is
    port(
        clk : in std_logic;
        reset : in std_logic;
        complete : in std_logic;
        latched_quotient : in std_logic_vector(9 downto 0);
        persent : out std_logic_vector(11 downto 0)
    );
end binary_decimal_test;

architecture RTL of binary_decimal_test is
signal persent_node : std_logic_vector(11 downto 0);
type binary_decimal_state is (idle_bds, state_0, state_1, state_2, state_3, state_4, state_5, state_6, state_7, state_8, state_9, state_10, val_valid);
signal cs_bds : binary_decimal_state;
type complete_state is (idle_comp, divide_complete);
signal cs_div : complete_state;
begin
    process(clk) begin
        if clk'event and clk='1' then
            if reset='1' then
                cs_div <= idle_comp;
            else
                case cs_div is
                    when idle_comp =>
                        if complete='1' then
                            cs_div <= divide_complete;
                        end if;
                    when divide_complete =>
                        cs_div <= idle_comp;
                end case;
            end if;
        end if;
    end process;
    
    -- 2進化10進用ステートマシン
    process(clk) begin
        if clk'event and clk='1' then
            if reset='1' then
                cs_bds <= idle_bds;
            else
                case cs_bds is
                    when idle_bds =>
                        if cs_div = divide_complete then
                            if unsigned(latched_quotient)>999 then -- 999以上は999と表示する
                                cs_bds <= state_9;
                            else
                                cs_bds <= state_0;
                            end if;
                        end if;
                    when state_0 =>
                        cs_bds <= state_1;
                    when state_1 =>
                        cs_bds <= state_2;
                    when state_2 =>
                        cs_bds <= state_3;
                    when state_3 =>
                        cs_bds <= state_4;
                    when state_4 =>
                        cs_bds <= state_5;
                    when state_5 =>
                        cs_bds <= state_6;
                    when state_6 =>
                        cs_bds <= state_7;
                    when state_7 =>
                        cs_bds <= state_8;
                    when state_8 =>
                        cs_bds <= state_9;
                    when state_9 =>
                        cs_bds <= state_10;
                    when state_10 =>
                        cs_bds <= val_valid;
                    when val_valid => -- present_nodeの値が有効
                        cs_bds <= idle_bds;
                end case;
            end if;
        end if;
    end process;
    
    -- 10進数変換用のテーブル
    
    -- 割り算で導き出したパーセンテージを10進にする
    process(clk) begin
        if clk'event and clk='1' then
            if reset='1' then
                persent_node <= (others => '0');
            else
                case cs_bds is
                    when state_0 =>
                        if latched_quotient(0)='1' then
                            persent_node <= "000000000001";
                        else
                            persent_node <= (others => '0');
                        end if;
                    when state_1 => 
                        if latched_quotient(1)='1' then
                            persent_node <= persent_node + 2;
                        else
                            persent_node <= persent_node;
                        end if;
                    when state_2 =>
                        if latched_quotient(2)='1' then
                            persent_node <= persent_node + 4;
                        else
                            persent_node <= persent_node;
                        end if;
                    when state_3 =>
                        if latched_quotient(3)='1' then
                            persent_node <= persent_node + 8;
                        else
                            persent_node <= persent_node;
                        end if;
                    when state_4 =>
                        if unsigned(persent_node(3 downto 0))>9 then -- 前までの総計15
                            if latched_quotient(4)='1' then
                                persent_node <= persent_node + x"01C"; -- +6+16
                            else
                                persent_node <= persent_node + x"006"; -- +6
                            end if;
                        else
                            if latched_quotient(4)='1' then 
                                persent_node <= persent_node + x"016";
                            else
                                persent_node <= persent_node;
                            end if;
                        end if;
                    when state_5 =>
                        if unsigned(persent_node(3 downto 0))>9 then -- 前までの総計は31
                            if latched_quotient(5)='1' then
                                persent_node <= persent_node + x"038"; -- +6+32
                            else
                                persent_node <= persent_node + x"006"; -- +6
                            end if;
                        else
                            if latched_quotient(5)='1' then 
                                persent_node <= persent_node + x"032";
                            else
                                persent_node <= persent_node;
                            end if;
                        end if;
                    when state_6 =>
                        if unsigned(persent_node(3 downto 0)) >9 then -- 前までの総計は63
                            if latched_quotient(6)='1' then
                                persent_node <= persent_node + x"06A"; -- +6+64
                            else
                                persent_node <= persent_node + x"006"; -- +6
                            end if;
                        else
                            if latched_quotient(6)='1' then 
                                persent_node <= persent_node + x"064";
                            else
                                persent_node <= persent_node;
                            end if;
                        end if;
                    when state_7 => -- 前までの総計は127
                        if unsigned(persent_node(3 downto 0)) >9 then
                            if unsigned(persent_node(7 downto 4)) >9 then
                                if latched_quotient(7)='1' then
                                    persent_node <= persent_node + x"18E"; -- +6+60+128=18E
                                else
                                    persent_node <= persent_node + x"066"; -- +6+60
                                end if;
                            else -- +6補正のみ
                                if latched_quotient(7)='1' then
                                    persent_node <= persent_node + x"12E"; -- +6+128
                                else
                                    persent_node <= persent_node + x"006"; -- +6
                                end if;
                            end if;
                        else
                            if unsigned(persent_node(7 downto 4)) >9 then
                                if latched_quotient(7)='1' then
                                    persent_node <= persent_node + x"188"; -- +60+128=18E
                                else
                                    persent_node <= persent_node + x"060"; -- +60
                                end if;
                            else
                                if latched_quotient(7)='1' then
                                    persent_node <= persent_node + x"128"; -- +128
                                else
                                    persent_node <= persent_node;
                                end if;
                            end if;
                        end if;
                    when state_8 => -- 前までの総計は255
                        if unsigned(persent_node(3 downto 0)) >9 then
                            if unsigned(persent_node(7 downto 4)) >9 then
                                if latched_quotient(8)='1' then
                                    persent_node <= persent_node + x"2BC"; -- +6+60+256=2BC
                                else
                                    persent_node <= persent_node + x"066"; -- +6+60
                                end if;
                            else -- +6補正のみ
                                if latched_quotient(8)='1' then
                                    persent_node <= persent_node + x"25C"; -- +6+256
                                else
                                    persent_node <= persent_node + x"006"; -- +6
                                end if;
                            end if;
                        else
                            if unsigned(persent_node(7 downto 4)) >9 then
                                if latched_quotient(8)='1' then
                                    persent_node <= persent_node + x"2B6"; -- +60+256=2B6
                                else
                                    persent_node <= persent_node + x"060"; -- +60
                                end if;
                            else
                                if latched_quotient(8)='1' then
                                    persent_node <= persent_node + x"256"; -- +256
                                else
                                    persent_node <= persent_node;
                                end if;
                            end if;
                        end if;
                    when state_9 => -- 前までの総計は511
                        if unsigned(latched_quotient)>999 then -- 999よりも大きい
                            persent_node <= "100110011001"; -- 999
                        else
                            if unsigned(persent_node(3 downto 0)) >9 then
                                if unsigned(persent_node(7 downto 4)) >9 then
                                    if latched_quotient(9)='1' then
                                        persent_node <= persent_node + x"578"; -- +6+60+512=578
                                    else
                                        persent_node <= persent_node + x"066"; -- +6+60
                                    end if;
                                else -- +6補正のみ
                                    if latched_quotient(9)='1' then
                                        persent_node <= persent_node + x"518"; -- +6+512
                                    else
                                        persent_node <= persent_node + x"006"; -- +6
                                    end if;
                                end if;
                            else
                                if unsigned(persent_node(7 downto 4)) >9 then
                                    if latched_quotient(9)='1' then
                                        persent_node <= persent_node + x"572"; -- +60+512=572
                                    else
                                        persent_node <= persent_node + x"060"; -- +60
                                    end if;
                                else
                                    if latched_quotient(9)='1' then
                                        persent_node <= persent_node + x"512"; -- +512
                                    else
                                        persent_node <= persent_node;
                                    end if;
                                end if;
                            end if;
                        end if;
                    when state_10 => -- 10進補正のみ
                            if unsigned(persent_node(3 downto 0)) >9 then
                                if unsigned(persent_node(7 downto 4)) >9 or (unsigned(persent_node(3 downto 0)) >9 and unsigned(persent_node(7 downto 4))=9) then -- 桁が上がって2桁目がAになる時も+66補正をする
                                    persent_node <= persent_node + x"066"; -- +6+60
                                else -- +6補正のみ
                                    persent_node <= persent_node + x"006"; -- +6
                                end if;
                            else
                                if unsigned(persent_node(7 downto 4)) >9 then
                                    persent_node <= persent_node + x"060"; -- +60
                                else
                                    persent_node <= persent_node;
                                end if;
                            end if;
                    when others =>
                        persent_node <= persent_node;
                end case;
            end if;
        end if;
    end process;
   
    process(clk) begin
        if clk'event and clk='1' then
            if reset='1' then
                persent <= (others => '0');
            else
                if cs_bds=val_valid then
                    persent <= persent_node;
                end if;
            end if;
        end if;
    end process;
            
end RTL;



テストベンチのVHDLコードも下に貼っておきます。

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use IEEE.std_logic_unsigned.all;
use IEEE.std_logic_arith.all;
 
ENTITY binary_decimal_test_tb IS
END binary_decimal_test_tb;
 
ARCHITECTURE behavior OF binary_decimal_test_tb IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT binary_decimal_test
    PORT(
         clk : IN  std_logic;
         reset : IN  std_logic;
         complete : IN  std_logic;
         latched_quotient : IN  std_logic_vector(9 downto 0);
         persent : OUT  std_logic_vector(11 downto 0)
        );
    END COMPONENT;
    

   --Inputs
   signal clk : std_logic := '0';
   signal reset : std_logic := '0';
   signal complete : std_logic := '0';
   signal latched_quotient : std_logic_vector(9 downto 0) := (others => '0');

     --Outputs
   signal persent : std_logic_vector(11 downto 0);

   -- Clock period definitions
   constant clk_period : time := 40 ns;
 
BEGIN
 
    -- Instantiate the Unit Under Test (UUT)
   uut: binary_decimal_test PORT MAP (
          clk => clk,
          reset => reset,
          complete => complete,
          latched_quotient => latched_quotient,
          persent => persent
        );

   -- Clock process definitions
   clk_process :process
   begin
        clk <= '0';
        wait for clk_period/2;
        clk <= '1';
        wait for clk_period/2;
   end process;
 

   -- Stimulus process
   stim_proc: process
   begin        
        -- hold reset state for 100 ns.
        reset <= '1';
        wait for 100 ns;    
        reset <= '0';
        wait for clk_period*10;

        -- insert stimulus here 
        STIMULUS_LOOP : for i in 0 to 1000 loop
            wait until clk'event and clk='1';
            wait for 1 ns;
            latched_quotient <= CONV_STD_LOGIC_VECTOR(i, 10);
            complete <= '1';
            wait until clk'event and clk='1';
            wait for 1 ns;
            complete <= '0';
            TRANS_WAIT_LOOP : for j in 0 to 10 loop -- 11クロックwait
                wait until clk'event and clk='1';
                wait for 1 ns;
            end loop TRANS_WAIT_LOOP;
        end loop STIMULUS_LOOP;    
        
        wait for clk_period*10;
        assert (false) report "Simulation End!" severity failure;
   end process;

END;


このVHDLコードをISE12.3、Spartan3E-500でインプリメントしたところ、60スライス、91LUTでした。
binary_decimal_101027.png
  1. 2010年10月27日 10:59 |
  2. IP
  3. | トラックバック:0
  4. | コメント:4

AlteraのFPGAでのクロック出力とデータ出力3(Assignment Editorを使ってみる2)

AlteraのFPGAでのクロック出力とデータ出力2(Assignment Editorを使ってみる1)”では、Assignment Editorを使用してFAST_OUTPUT_REGISTER属性を入れてみた。今回は、FAST_INPUT_REGISTER属性を試してみることにする。(Quartus II 10.0 SP1を使用)

前回同様に、Assignment Editorで、今度はdinにFast input Registerを設定する。下が設定している途中。
CLK_DATA_test_21_101026.png

Createボタンをクリックすると、8ビットのdinにFast input Register属性が指定された。
CLK_DATA_test_22_101026.png

これでコンパイルして、din[0]を見てみると、I/Oセル内のレジスタが使われていなかった。
CLK_DATA_test_23_101026.png

実際にdin[0]がd0[0]にどうつながっているかと言うと下の図の用に普通の配線でつながっている。
CLK_DATA_test_24_101026.png

Fast input Registerを設定したのになぜ?というところだが、”HardCopy シリーズ・ハンドブック Volume 1”(なぜか?HardCopyだが)この20ページによると、fast_input_registerは、”I/O セルまたは隣接LAB に、高速入力レジスタを実装。”だそうだ。必ずしもI/Oセルに実装されるものではないらしい?

CLK_DATA_test.qsfを貼っておく。

set_global_assignment -name FAMILY "Cyclone III"
set_global_assignment -name DEVICE EP3C16F484C6
set_global_assignment -name TOP_LEVEL_ENTITY CLK_DATA_test
set_global_assignment -name ORIGINAL_QUARTUS_VERSION "10.0 SP1"
set_global_assignment -name PROJECT_CREATION_TIME_DATE "05:20:24 OCTOBER 21, 2010"
set_global_assignment -name LAST_QUARTUS_VERSION "10.0 SP1"
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1
set_global_assignment -name NOMINAL_CORE_SUPPLY_VOLTAGE 1.2V
set_global_assignment -name VERILOG_FILE CLK_DATA_test.v
set_global_assignment -name QIP_FILE clk_data_test_pll.qip
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
set_global_assignment -name LL_ROOT_REGION ON -section_id "Root Region"
set_global_assignment -name LL_MEMBER_STATE LOCKED -section_id "Root Region"
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "2.5 V"
set_global_assignment -name MISC_FILE "H:/HDL/Altera/qdesigns/DE0/Test/CLK_DATA_test/CLK_DATA_test.dpf"
set_location_assignment PIN_AA3 -to clk_out
set_location_assignment PIN_Y2 -to dout[0]
set_location_assignment PIN_Y1 -to dout[1]
set_location_assignment PIN_M8 -to dout[2]
set_location_assignment PIN_N8 -to dout[3]
set_location_assignment PIN_T3 -to dout[4]
set_location_assignment PIN_M7 -to dout[5]
set_location_assignment PIN_P3 -to dout[6]
set_location_assignment PIN_M5 -to dout[7]
set_location_assignment PIN_G1 -to reset
set_location_assignment PIN_G2 -to clk
set_location_assignment PIN_V1 -to din[0]
set_location_assignment PIN_N2 -to din[1]
set_location_assignment PIN_V4 -to din[2]
set_location_assignment PIN_T4 -to din[3]
set_location_assignment PIN_W1 -to din[4]
set_location_assignment PIN_U2 -to din[5]
set_location_assignment PIN_U1 -to din[6]
set_location_assignment PIN_V2 -to din[7]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dout[0]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dout[1]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dout[2]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dout[3]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dout[4]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dout[5]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dout[6]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to dout[7]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to din[0]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to din[1]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to din[2]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to din[3]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to din[4]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to din[5]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to din[6]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to din[7]
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

  1. 2010年10月27日 04:36 |
  2. QuartusⅡ
  3. | トラックバック:0
  4. | コメント:0