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

перевод 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 спартане его нет... или я что то путаю ))
Зато там есть немного Block RAM поболее distributed RAM кучка регистров и тучка логики.

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

Удачи! Rob.

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


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

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

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

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

Удачи! Rob.

 

 

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

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


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

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

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

Удачи! Rob.

 

 

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


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

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...