Перейти к содержанию

    

перевод 2 связанных сигналов с частоты на частоту

в голове уже каша, поэтому обращаюсь к коллективному бессознательному.

 

имеется 2 связанных сигнала (данные-строб). их надо перевести с бОльшей частоты на мЕньшую (кратность примерно 2,6). сначала взял старую проверенную заготовку и вкорячил ее на обе линии. а потом задумался - из-за того что переход в точке 0 затиган - рано или поздно вылезет ситуация, когда произойдет рассинхрон фронтов данных и строба, и на меньшей частоте по стробу защелкнется не то данное. и, собствено, вопрос - как этого избежать?

 

 

зы

я мог не точно выразиться - под стробом понимается сигнал валидности данных. грубо говоря WDATA+WVALID с акси

post-76333-1533279346_thumb.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

в fifo асинхронный записывать клок и данные не решит проблему? вроде бы я так делаю у себя.. с частоты 250 перехожу на 125, записываю и клок и данные

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я не понимаю как можно перевести тактирующий строб на "меньшую частоту" , я понимаю как данные можно перевести из одного клокового домена в другой, но чтоб строб?

https://www.fpga4fun.com/CrossClockDomain.html

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Я не понимаю как можно перевести тактирующий строб на "меньшую частоту" , я понимаю как данные можно перевести из одного клокового домена в другой, но чтоб строб?

См.: Figure 5-6.

 

PS. Кроме того, вы всегда можете представить себе "тактирующий строб" в виде "данных" с разрядностью в один бит и передавать эти однобитные "данные" через FIFO с двумя клоками.. ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

...

PS. Кроме того, вы всегда можете представить себе "тактирующий строб" в виде "данных" с разрядностью в один бит и передавать эти однобитные "данные" через FIFO с двумя клоками.. ;)

А смысл этого ? Строб на высокой частоте просто показывает когда данные валидны для записи - бессмысленно его явно тащить через FIFO для этого случая. Не явно это и так делается через сигнал valid на выходе FIFO.

Удачи! Rob.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

синхронизатор шин данных между частотными регионами

 

library ieee;
use ieee.std_logic_1164.all;

entity indpClkDataBufferStd is
    generic(
        DW : natural := 32;
        RST_ACTIVE_SRC : std_logic := '1';
        RST_ACTIVE_DEST : std_logic := '1'
    );
    port(
        clk_src     : in  std_logic;
        clk_dest    : in  std_logic;
        rst_src     : in  std_logic;
        rst_dest    : in  std_logic;
        src_rdy_i   : in  std_logic;
        src_data_i  : in  std_logic_vector(DW - 1 downto 0);
        dest_rdy_o  : out std_logic;
        src_rdy_o   : out std_logic;
        dest_data_o : out std_logic_vector(DW - 1 downto 0)
    );
end indpClkDataBufferStd;

architecture rtl of indpClkDataBufferStd is

    type state_src_t is (IDLE, WAIT_ACK, ACK);
    signal state_src : state_src_t;
    signal ack_b     : std_logic;       -- trigger for latching signal from dest_ctrl
    signal ack_b2    : std_logic;       -- trigger for latching signal from dest_ctrl

    type state_dest_t is (IDLE, ACK);
    signal state_dest : state_dest_t;
    signal req_b : std_logic;           -- trigger for latch signal from src_ctrl
    signal req_b2 : std_logic;          -- trigger for latch signal from src_ctrl

    signal ack_dest_src  : std_logic;
    signal req_src_dest  : std_logic;
    signal data_src_dest : std_logic_vector(DW - 1 downto 0);

begin

    src_ctrl_proc : process(clk_src, rst_src)
    begin
        if rst_src = RST_ACTIVE_SRC then
            data_src_dest <= (others => '0');
            req_src_dest  <= '0';
            src_rdy_o     <= '0';

            state_src <= IDLE;
            ack_b     <= '0';

        elsif rising_edge(clk_src) then

            ack_b  <= ack_dest_src;     -- base synchronize
            ack_b2 <= ack_b;

            case state_src is
                when IDLE =>
                    src_rdy_o <= '0';
                    if (src_rdy_i = '1') then
                        state_src     <= WAIT_ACK;
                        data_src_dest <= src_data_i; -- latching data bus from source to dest_ctrl
                        req_src_dest  <= '1';
                    end if;
                when WAIT_ACK =>
                    if (ack_b2 = '1') then -- when dest_ctrl get data, req_o = '0'
                        req_src_dest <= '0';
                        state_src    <= ACK;
                    end if;
                when ACK =>
                    if (ack_b2 = '0') then -- when dest_ctrl ack='0' go to IDLE
                        state_src <= IDLE;
                        src_rdy_o <= '1';
                    end if;
            end case;
        end if;
    end process;

    dest_ctrl_proc : process(clk_dest, rst_dest)
    begin
        if rst_dest = RST_ACTIVE_DEST then
            ack_dest_src <= '0';
            dest_data_o  <= (others => '0');

            state_dest <= IDLE;
            req_b      <= '0';
            req_b2     <= '0';
            dest_rdy_o <= '0';

        elsif rising_edge(clk_dest) then

            req_b  <= req_src_dest;
            req_b2 <= req_b;

            case state_dest is
                when IDLE =>
                    if (req_b2 = '1') then -- when request from src_cotrol, latch data bus, form acknowledge
                        dest_data_o  <= data_src_dest;
                        dest_rdy_o   <= '1';
                        ack_dest_src <= '1';
                        state_dest   <= ACK;
                    end if;
                when ACK =>
                    dest_rdy_o <= '0';
                    if (req_b2 = '0') then -- when req from src_ctrl is '0', ack_0 = '0', go to IDLE
                        ack_dest_src <= '0';
                        state_dest   <= IDLE;
                    end if;
            end case;
        end if;
    end process;

end rtl;

 

синхронизатор стробов между частотными регионами

 

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;


entity IndpClkStb is
    generic(
        RST_ACTIVE_SRC : std_logic := '1';
        RST_ACTIVE_DEST : std_logic := '1'
    );
    port(
        clk_src  : in  std_logic;
        rst_src  : in  std_logic;
        data_i   : in  std_logic;
        clk_dest : in  std_logic;
        rst_dest : in  std_logic;
        data_o   : out std_logic
    );
end entity IndpClkStb;

architecture RTL of IndpClkStb is

    type state_src_t is (IDLE, WAIT_ACK, ACK);
    signal state_src : state_src_t;

    type state_dest_t is (IDLE, ACK);
    signal state_dest : state_dest_t;

    signal hardshake_req : std_logic;
    signal req_z         : std_logic;
    signal req_z2        : std_logic;

    signal handshake_ack : std_logic;
    signal ack_z         : std_logic;
    signal ack_z2        : std_logic;

begin

    --================================================================================
====================================
    --=========== автомат состояний входа
    --================================================================================
====================================
    proc_scr_ctrl : process(clk_src, rst_src)
    begin
        if (rst_src = RST_ACTIVE_SRC) then
            hardshake_req <= '0';
            state_src     <= IDLE;

        elsif rising_edge(clk_src) then

            ack_z  <= handshake_ack;
            ack_z2 <= ack_z;

            case state_src is
                when IDLE =>
                    if (data_i = '1') then
                        state_src     <= WAIT_ACK;
                        hardshake_req <= '1';
                    end if;

                when WAIT_ACK =>
                    if (ack_z2 = '1') then
                        hardshake_req <= '0';
                        state_src     <= ACK;
                    end if;

                when ACK =>
                    if (ack_z2 = '0') then
                        state_src <= IDLE;
                    end if;
            end case;

        end if;
    end process;

    --================================================================================
====================================
    --=========== автомат состояний выхода
    --================================================================================
====================================
    proc_dest_ctrl : process(clk_dest, rst_dest)
    begin
        if (rst_dest = RST_ACTIVE_DEST) then
            handshake_ack <= '0';
            state_dest    <= IDLE;

            data_o <= '0';

        elsif rising_edge(clk_dest) then

            req_z  <= hardshake_req;
            req_z2 <= req_z;

            case state_dest is
                when IDLE =>
                    if (req_z2 = '1') then
                        data_o        <= '1';
                        handshake_ack <= '1';
                        state_dest    <= ACK;
                    end if;
                when ACK =>
                    data_o <= '0';
                    if (req_z2 = '0') then
                        handshake_ack <= '0';
                        state_dest    <= IDLE;
                    end if;
            end case;

        end if;
    end process;

end architecture RTL;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

 

:bb-offtopic: Лучше использовать codebox тег для длинных блоков кода.

синхронизатор шин данных между частотными регионами

 

library ieee;
use ieee.std_logic_1164.all;

entity indpClkDataBufferStd is
generic(
	DW : natural := 32;
	RST_ACTIVE_SRC : std_logic := '1';
	RST_ACTIVE_DEST : std_logic := '1'
);
port(
	clk_src	 : in  std_logic;
	clk_dest	: in  std_logic;
	rst_src	 : in  std_logic;
	rst_dest	: in  std_logic;
	src_rdy_i   : in  std_logic;
	src_data_i  : in  std_logic_vector(DW - 1 downto 0);
	dest_rdy_o  : out std_logic;
	src_rdy_o   : out std_logic;
	dest_data_o : out std_logic_vector(DW - 1 downto 0)
);
end indpClkDataBufferStd;

architecture rtl of indpClkDataBufferStd is

type state_src_t is (IDLE, WAIT_ACK, ACK);
signal state_src : state_src_t;
signal ack_b	 : std_logic;	   -- trigger for latching signal from dest_ctrl
signal ack_b2	: std_logic;	   -- trigger for latching signal from dest_ctrl

type state_dest_t is (IDLE, ACK);
signal state_dest : state_dest_t;
signal req_b : std_logic;		   -- trigger for latch signal from src_ctrl
signal req_b2 : std_logic;		  -- trigger for latch signal from src_ctrl

signal ack_dest_src  : std_logic;
signal req_src_dest  : std_logic;
signal data_src_dest : std_logic_vector(DW - 1 downto 0);

begin

src_ctrl_proc : process(clk_src, rst_src)
begin
	if rst_src = RST_ACTIVE_SRC then
		data_src_dest <= (others => '0');
		req_src_dest  <= '0';
		src_rdy_o	 <= '0';

		state_src <= IDLE;
		ack_b	 <= '0';

	elsif rising_edge(clk_src) then

		ack_b  <= ack_dest_src;	 -- base synchronize
		ack_b2 <= ack_b;

		case state_src is
			when IDLE =>
				src_rdy_o <= '0';
				if (src_rdy_i = '1') then
					state_src	 <= WAIT_ACK;
					data_src_dest <= src_data_i; -- latching data bus from source to dest_ctrl
					req_src_dest  <= '1';
				end if;
			when WAIT_ACK =>
				if (ack_b2 = '1') then -- when dest_ctrl get data, req_o = '0'
					req_src_dest <= '0';
					state_src	<= ACK;
				end if;
			when ACK =>
				if (ack_b2 = '0') then -- when dest_ctrl ack='0' go to IDLE
					state_src <= IDLE;
					src_rdy_o <= '1';
				end if;
		end case;
	end if;
end process;

dest_ctrl_proc : process(clk_dest, rst_dest)
begin
	if rst_dest = RST_ACTIVE_DEST then
		ack_dest_src <= '0';
		dest_data_o  <= (others => '0');

		state_dest <= IDLE;
		req_b	  <= '0';
		req_b2	 <= '0';
		dest_rdy_o <= '0';

	elsif rising_edge(clk_dest) then

		req_b  <= req_src_dest;
		req_b2 <= req_b;

		case state_dest is
			when IDLE =>
				if (req_b2 = '1') then -- when request from src_cotrol, latch data bus, form acknowledge
					dest_data_o  <= data_src_dest;
					dest_rdy_o   <= '1';
					ack_dest_src <= '1';
					state_dest   <= ACK;
				end if;
			when ACK =>
				dest_rdy_o <= '0';
				if (req_b2 = '0') then -- when req from src_ctrl is '0', ack_0 = '0', go to IDLE
					ack_dest_src <= '0';
					state_dest   <= IDLE;
				end if;
		end case;
	end if;
end process;

end rtl;

 

синхронизатор стробов между частотными регионами

 

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;


entity IndpClkStb is
generic(
	RST_ACTIVE_SRC : std_logic := '1';
	RST_ACTIVE_DEST : std_logic := '1'
);
port(
	clk_src  : in  std_logic;
	rst_src  : in  std_logic;
	data_i   : in  std_logic;
	clk_dest : in  std_logic;
	rst_dest : in  std_logic;
	data_o   : out std_logic
);
end entity IndpClkStb;

architecture RTL of IndpClkStb is

type state_src_t is (IDLE, WAIT_ACK, ACK);
signal state_src : state_src_t;

type state_dest_t is (IDLE, ACK);
signal state_dest : state_dest_t;

signal hardshake_req : std_logic;
signal req_z		 : std_logic;
signal req_z2		: std_logic;

signal handshake_ack : std_logic;
signal ack_z		 : std_logic;
signal ack_z2		: std_logic;

begin

--================================================================================
====================================
--=========== автомат состояний входа
--================================================================================
====================================
proc_scr_ctrl : process(clk_src, rst_src)
begin
	if (rst_src = RST_ACTIVE_SRC) then
		hardshake_req <= '0';
		state_src	 <= IDLE;

	elsif rising_edge(clk_src) then

		ack_z  <= handshake_ack;
		ack_z2 <= ack_z;

		case state_src is
			when IDLE =>
				if (data_i = '1') then
					state_src	 <= WAIT_ACK;
					hardshake_req <= '1';
				end if;

			when WAIT_ACK =>
				if (ack_z2 = '1') then
					hardshake_req <= '0';
					state_src	 <= ACK;
				end if;

			when ACK =>
				if (ack_z2 = '0') then
					state_src <= IDLE;
				end if;
		end case;

	end if;
end process;

--================================================================================
====================================
--=========== автомат состояний выхода
--================================================================================
====================================
proc_dest_ctrl : process(clk_dest, rst_dest)
begin
	if (rst_dest = RST_ACTIVE_DEST) then
		handshake_ack <= '0';
		state_dest	<= IDLE;

		data_o <= '0';

	elsif rising_edge(clk_dest) then

		req_z  <= hardshake_req;
		req_z2 <= req_z;

		case state_dest is
			when IDLE =>
				if (req_z2 = '1') then
					data_o		<= '1';
					handshake_ack <= '1';
					state_dest	<= ACK;
				end if;
			when ACK =>
				data_o <= '0';
				if (req_z2 = '0') then
					handshake_ack <= '0';
					state_dest	<= IDLE;
				end if;
		end case;

	end if;
end process;

end architecture RTL;

Удачи! Rob.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
А смысл этого?

А я где-то утверждал, что в этом есть смысл?

 

Понятно, что если через FIFO тащат данные, то строб уже не нужен. Но для понимания логики CDC мой намек вопрошающему не повредит. :biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Приветствую!

 

:bb-offtopic: Лучше использовать codebox тег для длинных блоков кода.

 

Удачи! Rob.

 

Учту в дальнейшем :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

фифо, конечно, круто, но в 6 спартане его нет... или я что то путаю ))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

фифо, конечно, круто, но в 6 спартане его нет... или я что то путаю ))
Зато там есть немного Block RAM поболее distributed RAM кучка регистров и тучка логики.

Так что можно и не обращать внимание на IP core FIFO. :)

Удачи! Rob.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Приветствую!

Зато там есть немного Block RAM поболее distributed RAM кучка регистров и тучка логики.

Так что можно и не обращать внимание на IP core FIFO. :)

Удачи! Rob.

 

 

если вопрос стоит в том чтобы самому что то городить, то мне будет проще переписать входной блок под одинаковую частоту :). это если нет решения на пару строк кода или использование чего-то стандартного...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

если вопрос стоит в том чтобы самому что то городить, то мне будет проще переписать входной блок под одинаковую частоту :). это если нет решения на пару строк кода или использование чего-то стандартного...
Ну это Вам виднее что проще. По мне так в асинхронном FIFO нет никакой сложности кроме понимания принципов работы.

Удачи! Rob.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти