Saturday, February 1, 2014

write a counter with vhdl

--Design purpose
--when selector is b"00", counter(7 downto 0) output 0
--when selector is b"01", counter(7 downto 0) output 0~255, increase one per 0.5 second
--when selector is b"10", counter(7 downto 0) output 255~0, decrease one per 0.5 second
--when selector is b"11", counter(7 downto 0) output 0~255 and then 255~1, when 0~255 increase one per 0.5 second, when 255~1 decrease two per 0.5 second
--
--In the design, for each bit of counter when converted to bcd, use clock to shift each bit
--
-----------------------------------------------------------------
--clk dividor
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;

entity clk_div is
generic (
    N: integer := 12499999
);
port (
    clk     : in  std_logic;
    rst_n   : in  std_logic;
    clk_out : out std_logic
);
end entity clk_div;

architecture behavioral of clk_div is
signal clk_cnt     : integer range 0 to N;
signal clk_out_tmp : std_logic;
begin
--counter for half second
process(clk, rst_n)
begin
    if(rst_n = '0')then
        clk_cnt <= 0;
        clk_out_tmp <= '0';
    elsif(clk'event and clk = '1')  then
        --when counter reaches to half second,
        --need to reset the counter to 0
        if(clk_cnt = N) then
            clk_cnt <= 0;
            clk_out_tmp <= not (clk_out_tmp);
        else
            clk_cnt <= clk_cnt + 1;
            clk_out_tmp <= clk_out_tmp;
        end if;
    end if;
end process;

clk_out <= clk_out_tmp;

end behavioral;

-----------------------------------------------------------------
--counter
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity counter is
port (
    clk_in   : in  std_logic;
    rst_n    : in  std_logic;
    selector : in  std_logic_vector(1 downto 0);
    data     : out std_logic_vector(7 downto 0)
);
end entity counter;

architecture behavioral of counter is
--signal declaration in architecture
signal cnt             : integer range 0 to 255;
signal cnt_nxt         : integer range 0 to 255;
signal selector_ff1    : std_logic_vector(1 downto 0);
signal selector_ff2    : std_logic_vector(1 downto 0);
signal selector_ff3    : std_logic_vector(1 downto 0);
signal selector_trig   : std_logic_vector(3 downto 0);
signal selector_status : std_logic_vector(3 downto 0);
signal reverse         : std_logic;
signal reverse_nxt     : std_logic;

--function to convert boolean to std_logic
function to_stdulogic(V: Boolean) return std_ulogic is
begin
    if V then
        return '1';
    else
        return '0';
    end if;
end to_stdulogic;

--begin of architecture
begin

--solve metastability issue, so 2 flip-flops are needed
--sample the change of selector, so 3 flip-flops are needed
--so add 3 flip-flops
process(clk_in, rst_n)
begin
    if(rst_n = '0') then
        selector_ff1 <= b"00";
        selector_ff2 <= b"00";
        selector_ff3 <= b"00";
    elsif(clk_in'event and clk_in = '1') then
        selector_ff1 <= selector;
        selector_ff2 <= selector_ff1;
        selector_ff3 <= selector_ff2;
    end if;
end process;

--sample the change of selector
--use each bit to represent one selector
selector_trig(0)   <= to_stdulogic((selector_ff2 = b"00") and (selector_ff3 /= b"00"));
selector_trig(1)   <= to_stdulogic((selector_ff2 = b"01") and (selector_ff3 /= b"01"));
selector_trig(2)   <= to_stdulogic((selector_ff2 = b"10") and (selector_ff3 /= b"10"));
selector_trig(3)   <= to_stdulogic((selector_ff2 = b"11") and (selector_ff3 /= b"11"));
selector_status(0) <= to_stdulogic(selector_ff2 = b"00");
selector_status(1) <= to_stdulogic(selector_ff2 = b"01");
selector_status(2) <= to_stdulogic(selector_ff2 = b"10");
selector_status(3) <= to_stdulogic(selector_ff2 = b"11");

--counter state machine
--counter to count how many half seconds
process(selector_trig, selector_status, cnt, reverse)
begin
    --when selector change, this counter need to reset
    --set counter data to 0 when in selector 1 and selector 3
    --set coutner to 1 when in selector 2
    if(selector_trig(1) = '1' or selector_trig(3) = '1') then
        cnt_nxt <= 0;
    elsif(selector_trig(2) = '1') then
        cnt_nxt <= 255;
    else
        case selector_status is
            --when in selector 0, counter should be 0
            when b"0001" =>
                cnt_nxt <= 0;
            --when in selector 1, counter should add 1 after each half second
            when b"0010" =>
                if(cnt = 255) then
                    --if need to repeat from 0 to 255
                    --set cnt_nxt to 0
                    --else keep it as 255
                    --cnt_nxt <= 0;
                    cnt_nxt <= cnt;
                else
                    cnt_nxt <= cnt + 1;
                end if;
            --when in selector 2, counter should decrease 1 after each half second
            when b"0100" =>
                if(cnt = 0) then
                    --if need to repeat from 255 to 0
                    --set cnt_nxt to 255
                    --else keep it as 0
                    --cnt_nxt <= 255;
                    cnt_nxt <= cnt;
                else
                    cnt_nxt <= cnt - 1;
                end if;
            --when in selector 3, counter should add 1 after each half second
            --and after reaches 255, counter will decrease 2 after each half second
            when b"1000" =>
                if(reverse = '0') then
                    if(cnt = 255) then
                        cnt_nxt <= cnt - 2;
                    else
                        cnt_nxt <= cnt + 1;
                    end if;
                else
                    if(cnt = 1) then
                        --if need to repeat from 0 to 255 and then 255 to 1
                        --set cnt_nxt to 0
                        --else keep it as 1
                        --cnt_nxt <= 0;
                        cnt_nxt <= cnt;
                    else
                        cnt_nxt <= cnt - 2;
                    end if;
                end if;
            --for other unknown selectors, set counter to 0
            when others =>
                cnt_nxt <= 0;
        end case;
    end if;
end process;

process(selector_trig, selector_status, cnt, reverse)
begin
    --when selector change, this counter need to reset
    --set counter data to 0 when in selector 1 and selector 3
    --set coutner to 1 when in selector 2
    if(selector_trig(3) = '1') then
        reverse_nxt <= '0';
    elsif(selector_status = b"1000") then
        if(reverse = '0') then
            if(cnt = 255) then
                reverse_nxt <= '1';
            else
                reverse_nxt <= reverse;
            end if;
        else
            if(cnt = 1) then
                --if need to repeat from 0 to 255 and then 255 to 1
                --set reverse_nxt to 0
                --else keep it as 1
                --reverse_nxt <= '0';
                reverse_nxt <= reverse;
            else
                reverse_nxt <= reverse;
            end if;
        end if;
    else
        reverse_nxt <= '0';
    end if;
end process;

--in selector 3, check if counter reaches 255
process(clk_in, rst_n)
begin
    if(rst_n = '0') then
        reverse <= '0';
    elsif(clk_in'event and clk_in = '1') then
        reverse <= reverse_nxt;
    end if;
end process;

--flip-flop the counter
process(clk_in, rst_n)
begin
    if(rst_n = '0') then
        cnt <= 0;
    elsif(clk_in'event and clk_in = '1') then
        cnt <= cnt_nxt;
    end if;
end process;

--send the counter data out
data <= std_logic_vector(to_unsigned(cnt, 8));

end behavioral;
--end of architecture

-----------------------------------------------------------------
--process one bcd
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity one_bcd is
port (
    clk             : in std_logic;
    rst_n           : in std_logic;
    calc_en         : in std_logic;
    bin_change_trig : in std_logic;
    bcd_in          : in std_logic_vector(3 downto 0);
    bcd_out         : out std_logic_vector(3 downto 0)
);
end entity one_bcd;

architecture behavioral of one_bcd is

begin

--add 3 when bcd is greater than 4
process(clk, rst_n)
begin
    if(rst_n = '0') then
        bcd_out(3 downto 0) <= x"0";
    elsif(clk'event and clk = '1') then
        if(bin_change_trig = '1') then
            bcd_out <= x"0";
        elsif(calc_en = '1') then
            if(bcd_in > "0100") then
                bcd_out <= bcd_in + "0011";
            else
                bcd_out <= bcd_in;
            end if;
        end if;
    end if;
end process;

end behavioral;

-----------------------------------------------------------------
--bin to bcd
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity bin2bcd is
port (
    clk   : in std_logic;
    rst_n : in std_logic;
    bin   : in std_logic_vector(7 downto 0);
    bcd   : out std_logic_vector(11 downto 0)
);
end entity bin2bcd;

architecture behavioral of bin2bcd is
signal bin_ff1            : std_logic_vector(7 downto 0);
signal bin_ff2            : std_logic_vector(7 downto 0);
signal bin_ff3            : std_logic_vector(7 downto 0);
signal calc_en            : std_logic;
signal calc_done          : std_logic;
signal bin_change_trig    : std_logic;
signal bcd_nxt            : std_logic_vector(11 downto 0);
signal bcd_tmp            : std_logic_vector(11 downto 0);
signal bin_tmp            : std_logic_vector(7 downto 0);
signal cnt                : integer range 0 to 15;

--function to convert boolean to std_logic
function to_stdulogic(V: Boolean) return std_ulogic is
begin
    if V then
        return '1';
    else
        return '0';
    end if;
end to_stdulogic;

component one_bcd is
port (
    clk             : in std_logic;
    rst_n           : in std_logic;
    calc_en         : in std_logic;
    bin_change_trig : in std_logic;
    bcd_in          : in std_logic_vector(3 downto 0);
    bcd_out         : out std_logic_vector(3 downto 0)
);
end component;

begin

--solve metastability issue
--sample the change of bin, so 3 flip-flops are needed
--so add 3 flip-flops
process(clk, rst_n)
begin
    if(rst_n = '0') then
        bin_ff1 <= x"00";
        bin_ff2 <= x"00";
        bin_ff3 <= x"00";
    elsif(clk'event and clk = '1') then
        bin_ff1 <= bin;
        bin_ff2 <= bin_ff1;
        bin_ff3 <= bin_ff2;
    end if;
end process;
--data bin is changed
bin_change_trig <= to_stdulogic(bin_ff2 /= bin_ff3);

--cnt to control how many loop is needed
process(clk, rst_n)
begin
    if(rst_n = '0') then
        cnt <= 0;
    elsif(clk'event and clk = '1') then
        if(bin_change_trig = '1') then
            cnt <= 1;
        elsif(cnt > 0 and cnt < 15) then
            cnt <= cnt + 1;
        else
            cnt <= 0;
        end if;
    end if;
end process;

--enable loop to get bcd
process(clk, rst_n)
begin
    if(rst_n = '0') then
        calc_en <= '0';
    elsif(clk'event and clk = '1') then
        if(bin_change_trig = '1') then
            calc_en <= '1';
        elsif(cnt <= 6) then
            calc_en <= '1';
        else
            calc_en <= '0';
        end if;
    end if;
end process;

--bcd loop is done
process(clk, rst_n)
begin
    if(rst_n = '0') then
        calc_done <= '0';
    elsif(clk'event and clk = '1') then
        if(cnt = 7) then
            calc_done <= '1';
        else
            calc_done <= '0';
        end if;
    end if;
end process;

--get bin_tmp data from bin
--and shift bin_tmp
process(clk, rst_n)
begin
    if(rst_n = '0') then
        bin_tmp <= x"00";
    elsif(clk'event and clk = '1') then
        if(bin_change_trig = '1') then
            bin_tmp <= bin;
        elsif(calc_en = '1') then
            bin_tmp(7 downto 1) <= bin_tmp(6 downto 0);
            bin_tmp(0) <= '0';
        end if;
    end if;
end process;

--shift bcd_tmp
bcd_nxt(11 downto 1) <= bcd_tmp(10 downto 0);
bcd_nxt(0) <= bin_tmp(7);

--change bin to bcd for data 0
u_one_bcd_0: one_bcd PORT MAP (
    clk             => clk,
    rst_n           => rst_n,
    calc_en         => calc_en,
    bin_change_trig => bin_change_trig,
    bcd_in          => bcd_nxt(3 downto 0),
    bcd_out         => bcd_tmp(3 downto 0)
);

--change bin to bcd for data 1
u_one_bcd_1: one_bcd PORT MAP (
    clk             => clk,
    rst_n           => rst_n,
    calc_en         => calc_en,
    bin_change_trig => bin_change_trig,
    bcd_in          => bcd_nxt(7 downto 4),
    bcd_out         => bcd_tmp(7 downto 4)
);

--change bin to bcd for data 2
u_one_bcd_2: one_bcd PORT MAP (
    clk             => clk,
    rst_n           => rst_n,
    calc_en         => calc_en,
    bin_change_trig => bin_change_trig,
    bcd_in          => bcd_nxt(11 downto 8),
    bcd_out         => bcd_tmp(11 downto 8)
);

--send bcd out
process(clk, rst_n)
begin
    if(rst_n = '0') then
        bcd <= x"000";
    elsif(clk'event and clk = '1') then
        if(calc_done = '1') then
            bcd <= bcd_nxt;
        end if;
    end if;
end process;

end behavioral;

-----------------------------------------------------------------
--bcd to segment
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;

entity bcd2segment is
generic (
    M: integer := 7
);
port (
    bcd     : in std_logic_vector(3 downto 0);
    segment : out std_logic_vector(M-1 downto 0)
);
end entity bcd2segment;

architecture behavioral of bcd2segment is

begin

SEGMENT_WITHOUT_DP: if M=7 generate
process(bcd)
begin
    case bcd is
        --decode from bcd to segment
        when x"0" => segment <= b"1111111";
        when x"1" => segment <= b"1111001";
        when x"2" => segment <= b"0100100";
        when x"3" => segment <= b"0110000";
        when x"4" => segment <= b"0011001";
        when x"5" => segment <= b"0010010";
        when x"6" => segment <= b"0000010";
        when x"7" => segment <= b"1111000";
        when x"8" => segment <= b"0000000";
        when x"9" => segment <= b"0010000";
        --when in selector 1, counter should add 1 after each half second
        --for other unknown selectors, set counter to 0
        when others => segment <= b"1111111";
    end case;
end process;

end generate SEGMENT_WITHOUT_DP;

SEGMENT_WITH_DP: if M=8 generate
process(bcd)
begin
    case bcd is
        --decode from bcd to segment
        when x"0" => segment <= b"11111111";
        when x"1" => segment <= b"11111001";
        when x"2" => segment <= b"10100100";
        when x"3" => segment <= b"10110000";
        when x"4" => segment <= b"10011001";
        when x"5" => segment <= b"10010010";
        when x"6" => segment <= b"10000010";
        when x"7" => segment <= b"11111000";
        when x"8" => segment <= b"10000000";
        when x"9" => segment <= b"10010000";
        --when in selector 1, counter should add 1 after each half second
        --for other unknown selectors, set counter to 0
        when others => segment <= b"11111111";
    end case;
end process;

end generate SEGMENT_WITH_DP;

end behavioral;

-----------------------------------------------------------------
--top
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;

entity top is
generic (
    M: integer := 7
);
port (
    clk      : in  std_logic;
    rst_n    : in  std_logic;
    selector : in  std_logic_vector(1 downto 0);
    data     : out std_logic_vector(7 downto 0);
    segment0 : out std_logic_vector(M-1 downto 0);
    segment1 : out std_logic_vector(M-1 downto 0);
    segment2 : out std_logic_vector(M-1 downto 0)
);
end entity top;

architecture behavioral of top is
--signal declaration in architecture
signal clk_out  : std_logic;
signal data_tmp : std_logic_vector(7 downto 0);
signal bcd      : std_logic_vector(11 downto 0);

component clk_div is
generic (
    N: integer := 12499999
);
port (
    clk     : in  std_logic;
    rst_n   : in  std_logic;
    clk_out : out std_logic
);
end component;

component counter is
port (
    clk_in   : in  std_logic;
    rst_n    : in  std_logic;
    selector : in  std_logic_vector(1 downto 0);
    data     : out std_logic_vector(7 downto 0)
);
end component;

component bin2bcd is
port (
    clk   : in std_logic;
    rst_n : in std_logic;
    bin   : in std_logic_vector(7 downto 0);
    bcd   : out std_logic_vector(11 downto 0)
);
end component;

component bcd2segment is
generic (
    M: integer := 7
);
port (
    bcd     : in std_logic_vector(3 downto 0);
    segment : out std_logic_vector(M-1 downto 0)
);
end component;

--begin of architecture
begin

--instance clock dividor
u_clk_div: clk_div generic map (
    N => 12499999
 --N => 20
) PORT MAP (
    clk     => clk     ,
    rst_n   => rst_n   ,
    clk_out => clk_out
);

--instance counter
u_counter: counter PORT MAP (
    clk_in   => clk_out  ,
    rst_n    => rst_n    ,
    selector => selector ,
    data     => data_tmp  
);

data <= data_tmp;

--instance bin2bcd
u_bin2bcd: bin2bcd PORT MAP (
    clk   => clk,
    rst_n => rst_n,
    bin   => data_tmp,
    bcd   => bcd
);

--instance segment0
u_bcd2segment_0: bcd2segment generic map (
    M => M
) PORT MAP (
    bcd     => bcd(3 downto 0),
    segment => segment0
);

--instance segment1
u_bcd2segment_1: bcd2segment generic map (
    M => M
) PORT MAP (
    bcd     => bcd(7 downto 4),
    segment => segment1
);

--instance segment2
u_bcd2segment_2: bcd2segment generic map (
    M => M
) PORT MAP (
    bcd     => bcd(11 downto 8),
    segment => segment2
);

end behavioral;
--end of architecture


---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
If calculating std_logic_vector to bcd can be done in one cycle, update the module bin2bcd that convert std_logic_vector to bcd as following:
-----------------------------------------------------------------
--process one bit of bin to convert to bcd
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity process_one_bit is
port (
    shift_in  : in std_logic;
    bcd_in    : in std_logic_vector(3 downto 0);
    bcd_out   : out std_logic_vector(3 downto 0);
    shift_out : out std_logic
);
end entity process_one_bit;

architecture behavioral of process_one_bit is
signal bcd_tmp: std_logic_vector(3 downto 0);

begin

bcd_tmp(3 downto 1) <= bcd_in(2 downto 0);
bcd_tmp(0) <= shift_in;
shift_out <= bcd_in(3);

--add 3 when bcd is greater than 4
process(bcd_tmp, shift_in)
begin
    if(bcd_tmp > "0100") then
        bcd_out <= bcd_tmp + "0011";
    else
        bcd_out <= bcd_tmp;
    end if;
end process;

end behavioral;

-----------------------------------------------------------------
--process one bcd
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity one_bcd is
port (
    shift_in  : in std_logic_vector(7 downto 0);
    bcd_in    : in std_logic_vector(3 downto 0);
    bcd_out   : out std_logic_vector(3 downto 0);
    shift_out : out std_logic_vector(7 downto 0)
);
end entity one_bcd;

architecture behavioral of one_bcd is
component process_one_bit is
    port (
        shift_in  : in std_logic;
        bcd_in    : in std_logic_vector(3 downto 0);
        bcd_out   : out std_logic_vector(3 downto 0);
        shift_out : out std_logic
    );
end component;


signal bcd_out1: std_logic_vector(3 downto 0);
signal bcd_out2: std_logic_vector(3 downto 0);
signal bcd_out3: std_logic_vector(3 downto 0);
signal bcd_out4: std_logic_vector(3 downto 0);
signal bcd_out5: std_logic_vector(3 downto 0);
signal bcd_out6: std_logic_vector(3 downto 0);
signal bcd_out7: std_logic_vector(3 downto 0);

begin

u_process_one_bit_7: process_one_bit port map (
    shift_in  => shift_in(7),
    bcd_in    => bcd_in,
    bcd_out   => bcd_out7,
    shift_out => shift_out(7)
);

u_process_one_bit_6: process_one_bit port map (
    shift_in  => shift_in(6),
    bcd_in    => bcd_out7,
    bcd_out   => bcd_out6,
    shift_out => shift_out(6)
);

u_process_one_bit_5: process_one_bit port map (
    shift_in  => shift_in(5),
    bcd_in    => bcd_out6,
    bcd_out   => bcd_out5,
    shift_out => shift_out(5)
);

u_process_one_bit_4: process_one_bit port map (
    shift_in  => shift_in(4),
    bcd_in    => bcd_out5,
    bcd_out   => bcd_out4,
    shift_out => shift_out(4)
);

u_process_one_bit_3: process_one_bit port map (
    shift_in  => shift_in(3),
    bcd_in    => bcd_out4,
    bcd_out   => bcd_out3,
    shift_out => shift_out(3)
);

u_process_one_bit_2: process_one_bit port map (
    shift_in  => shift_in(2),
    bcd_in    => bcd_out3,
    bcd_out   => bcd_out2,
    shift_out => shift_out(2)
);

u_process_one_bit_1: process_one_bit port map (
    shift_in  => shift_in(1),
    bcd_in    => bcd_out2,
    bcd_out   => bcd_out1,
    shift_out => shift_out(1)
);

bcd_out(3 downto 1) <= bcd_out1(2 downto 0);
bcd_out(0) <= shift_in(0);
shift_out(0) <= bcd_out1(3);

end behavioral;

-----------------------------------------------------------------
--bin to bcd
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity bin2bcd is
port (
    clk   : in std_logic;
    rst_n : in std_logic;
    bin   : in std_logic_vector(7 downto 0);
    bcd   : out std_logic_vector(11 downto 0)
);
end entity bin2bcd;

architecture behavioral of bin2bcd is
signal bin_ff1    : std_logic_vector(7 downto 0);
signal bin_ff2    : std_logic_vector(7 downto 0);
signal bcd_tmp    : std_logic_vector(11 downto 0);
signal shift_out0 : std_logic_vector(7 downto 0);
signal shift_out1 : std_logic_vector(7 downto 0);

component one_bcd is
port (
    shift_in  : in std_logic_vector(7 downto 0);
    bcd_in    : in std_logic_vector(3 downto 0);
    bcd_out   : out std_logic_vector(3 downto 0);
    shift_out : out std_logic_vector(7 downto 0)
);
end component;

begin

--solve metastability issue
--sample the change of bin, so 3 flip-flops are needed
--so add 3 flip-flops
process(clk, rst_n)
begin
    if(rst_n = '0') then
        bin_ff1 <= x"00";
        bin_ff2 <= x"00";
    elsif(clk'event and clk = '1') then
        bin_ff1 <= bin;
        bin_ff2 <= bin_ff1;
    end if;
end process;

--change bin to bcd for data 0
u_one_bcd_0: one_bcd PORT MAP (
    shift_in  => bin_ff2,
    bcd_in    => b"0000",
    bcd_out   => bcd_tmp(3 downto 0),
    shift_out => shift_out0
);

--change bin to bcd for data 1
u_one_bcd_1: one_bcd PORT MAP (
    shift_in  => shift_out0,
    bcd_in    => b"0000",
    bcd_out   => bcd_tmp(7 downto 4),
    shift_out => shift_out1
);

--change bin to bcd for data 2
u_one_bcd_2: one_bcd PORT MAP (
    shift_in  => shift_out1,
    bcd_in    => b"0000",
    bcd_out   => bcd_tmp(11 downto 8)
);

--send bcd out
bcd <= bcd_tmp;

end behavioral;

---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
If don't care for how the logic will be and let synthesis tool determine the logic, we can update the module bin2bcd that convert std_logic_vector to bcd as following:
-----------------------------------------------------------------
--bin to bcd
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity bin2bcd is
port (
    clk   : in std_logic;
    rst_n : in std_logic;
    bin   : in std_logic_vector(7 downto 0);
    bcd   : out std_logic_vector(11 downto 0)
);
end entity bin2bcd;

architecture behavioral of bin2bcd is
signal bin_ff1    : std_logic_vector(7 downto 0);
signal bin_ff2    : std_logic_vector(7 downto 0);

function to_bcd (bin: std_logic_vector(7 downto 0)) return std_logic_vector is
variable i       : integer := 0;
variable bcd     : std_logic_vector(11 downto 0) := (others => '0');
variable bin_tmp : std_logic_vector(7 downto 0)  := bin;

begin

    -- repeating 8 times.
    for i in 0 to 6 loop
        --shifting the bits.
        bcd(11 downto 1)    := bcd(10 downto 0);
        bcd(0)              := bin_tmp(7);
        bin_tmp(7 downto 1) := bin_tmp(6 downto 0);
        bin_tmp(0)          := '0';
     
        --add 3 if BCD digit is greater than 4.
        if(bcd(3 downto 0) > "0100") then
            bcd(3 downto 0) := bcd(3 downto 0) + "0011";
        end if;
     
        --add 3 if BCD digit is greater than 4.
        if(bcd(7 downto 4) > "0100") then
            bcd(7 downto 4) := bcd(7 downto 4) + "0011";
        end if;
     
        --add 3 if BCD digit is greater than 4.
        if(bcd(11 downto 8) > "0100") then
            bcd(11 downto 8) := bcd(11 downto 8) + "0011";
        end if;
 
    end loop;

    bcd(11 downto 1) := bcd(10 downto 0);
    bcd(0)           := bin_tmp(7);

    return bcd;
end to_bcd;

begin
process(clk, rst_n)
begin
    if(rst_n = '0') then
        bin_ff1 <= x"00";
        bin_ff2 <= x"00";
    elsif(clk'event and clk = '1') then
        bin_ff1 <= bin;
        bin_ff2 <= bin_ff1;
    end if;
end process;

bcd <= to_bcd(bin_ff2);

end behavioral;

No comments:

Post a Comment