VHDL ile Clock Domain Crossing İşlemi

Aşağıda A saat darbesi frekansında mevcut bir sinyalin B saat darbesi frekansında oluşturulmasını sağlayan VHDL kodları aşağıda verilmiştir.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
 
 
entity clk_bridge is
  Generic(
    CLK_COMPARE : integer range 0 to 1 := 0;
--if in_clk_A > in_clk_B; 0 else 1;
    DATA_WIDTH : integer := 8
   
  );
  Port (
    in_rst : in std_logic;
    in_clk_A : in std_logic;
    in_clk_B : in std_logic;
    in_data_A_vld : in std_logic;
    in_data_A : in std_logic_vector(DATA_WIDTH - 1 downto 0);
    out_data_B : out std_logic_vector(DATA_WIDTH - 1 downto 0);
    out_data_B_vld : out std_logic  
   
  );
end clk_bridge;
 
architecture Behavioral of clk_bridge is
 
    component cdc_down
        generic(
            DATA_WIDTH : integer := 8
        );
        Port (
            in_rst : in std_logic;
            in_clk_A : in std_logic;
            in_clk_B : in std_logic;
            in_data_A_vld : in std_logic;
            in_data_A : in std_logic_vector(DATA_WIDTH - 1 downto 0);
            out_data_B : out std_logic_vector(DATA_WIDTH - 1 downto 0);
            out_data_B_vld : out std_logic
                   
        );    
    end component;
   
    component cdc_up
        generic(
            DATA_WIDTH : integer := 8
        );
        Port (
            in_rst : in std_logic;
            in_clk_A : in std_logic;
            in_clk_B : in std_logic;
            in_data_A_vld : in std_logic;
            in_data_A : in std_logic_vector(DATA_WIDTH - 1 downto 0);
            out_data_B : out std_logic_vector(DATA_WIDTH - 1 downto 0);
            out_data_B_vld : out std_logic            
        );    
    end component;
begin
 
    cdc_down_if : if CLK_COMPARE = 0 generate
        cdc_down_map : cdc_down
        generic map(
            DATA_WIDTH => DATA_WIDTH
        )
        Port map(
            in_rst => in_rst,
            in_clk_A => in_clk_A,
            in_clk_B => in_clk_B,
            in_data_A_vld => in_data_A_vld,
            in_data_A => in_data_A,
            out_data_B => out_data_B,
            out_data_B_vld =>  out_data_B_vld                    
        );          
    end generate cdc_down_if;
    cdc_up_if : if CLK_COMPARE = 1 generate
        cdc_up_map : cdc_up
        generic map(
            DATA_WIDTH => DATA_WIDTH
        )
        Port map(
            in_rst => in_rst,
            in_clk_A => in_clk_A,
            in_clk_B => in_clk_B,
            in_data_A_vld => in_data_A_vld,
            in_data_A => in_data_A,
            out_data_B => out_data_B,
            out_data_B_vld =>  out_data_B_vld                    
        );
    end generate cdc_up_if;
 
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
 
entity cdc_down is
    generic(
        DATA_WIDTH : integer := 8
    );
    Port (
        in_rst : in std_logic;
        in_clk_A : in std_logic;
        in_clk_B : in std_logic;
        in_data_A_vld : in std_logic;
        in_data_A : in std_logic_vector(DATA_WIDTH - 1 downto 0);
        out_data_B : out std_logic_vector(DATA_WIDTH - 1 downto 0);
        out_data_B_vld : out std_logic
               
    );
end cdc_down;
 
architecture Behavioral of cdc_down is
   
    signal r_data_A : std_logic_vector(DATA_WIDTH - 1 downto 0)
     := (others => '0');
    signal r_data_B : std_logic_vector(DATA_WIDTH - 1 downto 0)
     := (others => '0');
    signal r_handshake_A : std_logic := '0';
    signal r_handshake_B : std_logic := '0';
 
begin
 
    out_data_B <= r_data_B;
    out_data_B_vld <= r_handshake_B;
 
    process(in_clk_A, in_rst)
    begin
        if in_rst = '1' then
            r_handshake_A <= '0';  
            r_data_A <= (others => '0');
 
        elsif rising_edge(in_clk_A) then
            if in_data_A_vld = '1' and r_handshake_A = '0' then
                r_data_A <= in_data_A;
                r_handshake_A <= '1';
            else
                if r_handshake_B = '1' then
                    r_handshake_A <= '0';
                 end if;
            end if;
        end if;
    end process;
 
    process(in_clk_B, in_rst)
    begin
        if in_rst = '1' then
            r_handshake_B <= '0';
            r_data_B <= (others => '0');
        elsif rising_edge(in_clk_B) then
            if r_handshake_B = '0' and r_handshake_A = '1'  then
                r_handshake_B <= '1';
                r_data_B <= r_data_A;          
            elsif r_handshake_A = '0' then
                r_handshake_B <= '0';      
            end if;
        end if;    
    end process;
 
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
 
entity cdc_up is
    generic(
        DATA_WIDTH : integer := 8
    );
    Port (
        in_rst : in std_logic;
        in_clk_A : in std_logic;
        in_clk_B : in std_logic;
        in_data_A_vld : in std_logic;
        in_data_A : in std_logic_vector(DATA_WIDTH - 1 downto 0);
        out_data_B : out std_logic_vector(DATA_WIDTH - 1 downto 0);
        out_data_B_vld : out std_logic            
    );
end cdc_up;
 
architecture Behavioral of cdc_up is
    signal r_data_cnt : std_logic_vector(3 downto 0) := (others => '0');
begin
   
    out_data_B <= in_data_A when r_data_cnt(3 downto 2) = "01"
     else (others => '0');
    out_data_B_vld <= '1' when r_data_cnt(3 downto 2) = "01"
     else '0';
   
    process(in_clk_B, in_rst)
    begin
        if in_rst = '1' then
            r_data_cnt <= (others => '0');
        elsif rising_edge(in_clk_B) then
            r_data_cnt <= r_data_cnt(2 downto 0) & in_data_A_vld;
        end if;
    end process;
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
entity tb_clk_bridge is
end tb_clk_bridge;
 
architecture Behavioral of tb_clk_bridge is
 
    component clk_bridge 
    Generic(
        CLK_COMPARE : integer range 0 to 1 := 0; 
        DATA_WIDTH : integer := 8
 
    );
    Port ( 
        in_rst : in std_logic;
        in_clk_A : in std_logic;
        in_clk_B : in std_logic;
        in_data_A_vld : in std_logic;
        in_data_A : in std_logic_vector(DATA_WIDTH - 1 downto 0);
        out_data_B : out std_logic_vector(DATA_WIDTH - 1 downto 0);
        out_data_B_vld : out std_logic       
    );
    end component;
 
    constant DATA_WIDTH : integer := 8;
    constant PERIOD_CLK_A :time := 10 us;
    constant PERIOD_CLK_B :time := 1 us; 
    signal in_clk_A : std_logic := '0';
    signal in_clk_B : std_logic := '0';
    signal in_data_A_vld : std_logic := '0';
    signal in_data_A : std_logic_vector(DATA_WIDTH - 1 downto 0) 
     := (others => '0');
    signal out_data_B : std_logic_vector(DATA_WIDTH - 1 downto 0)
     := (others => '0');
    signal out_data_B_vld : std_logic := '0';
 
begin
    process
    begin
        in_clk_A <= '1';
        wait for PERIOD_CLK_A / 2;
        in_clk_A <= '0';
        wait for PERIOD_CLK_A / 2;
    end process;
 
    process
    begin
        in_clk_B <= '1';
        wait for PERIOD_CLK_B / 2;
        in_clk_B <= '0';
        wait for PERIOD_CLK_B / 2;
    end process;
 
    process
    begin
        in_data_A_vld <= '0';
        wait for PERIOD_CLK_A * 19;
        in_data_A_vld <= '1';
        wait for PERIOD_CLK_A;
    end process;
 
    process(in_data_A_vld)
    begin
        if in_data_A_vld = '1' then
            in_data_A <= in_data_A + 1;
        end if;
    end process;
 
 
    clk_bridge_map : clk_bridge
    Generic map(
        CLK_COMPARE => 1, --f_clk_a <= f_clk_b
        DATA_WIDTH => DATA_WIDTH   
    )
    Port map( 
        in_rst => '0',
        in_clk_A => in_clk_A,
        in_clk_B => in_clk_B,
        in_data_A_vld => in_data_A_vld,
        in_data_A => in_data_A,
        out_data_B => out_data_B,
        out_data_B_vld => out_data_B_vld
    );
 
end Behavioral;

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir