Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: перевод 2 связанных сигналов с частоты на частоту
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Работаем с ПЛИС, области применения, выбор
GAYVER
в голове уже каша, поэтому обращаюсь к коллективному бессознательному.

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


зы
я мог не точно выразиться - под стробом понимается сигнал валидности данных. грубо говоря WDATA+WVALID с акси
new123
в fifo асинхронный записывать клок и данные не решит проблему? вроде бы я так делаю у себя.. с частоты 250 перехожу на 125, записываю и клок и данные
Lmx2315
Я не понимаю как можно перевести тактирующий строб на "меньшую частоту" , я понимаю как данные можно перевести из одного клокового домена в другой, но чтоб строб?
https://www.fpga4fun.com/CrossClockDomain.html
blackfin
Цитата(Lmx2315 @ Aug 3 2018, 10:57) *
Я не понимаю как можно перевести тактирующий строб на "меньшую частоту" , я понимаю как данные можно перевести из одного клокового домена в другой, но чтоб строб?

См.: Figure 5-6.

PS. Кроме того, вы всегда можете представить себе "тактирующий строб" в виде "данных" с разрядностью в один бит и передавать эти однобитные "данные" через FIFO с двумя клоками.. wink.gif
RobFPGA
Приветствую!
Цитата(blackfin @ Aug 3 2018, 11:06) *
...
PS. Кроме того, вы всегда можете представить себе "тактирующий строб" в виде "данных" с разрядностью в один бит и передавать эти однобитные "данные" через FIFO с двумя клоками.. wink.gif
А смысл этого ? Строб на высокой частоте просто показывает когда данные валидны для записи - бессмысленно его явно тащить через FIFO для этого случая. Не явно это и так делается через сигнал valid на выходе FIFO.
Удачи! Rob.
quato_a
синхронизатор шин данных между частотными регионами

Код
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;
RobFPGA
Приветствую!

bb-offtopic.gif Лучше использовать codebox тег для длинных блоков кода.
Цитата(quato_a @ Aug 3 2018, 11:42) *
синхронизатор шин данных между частотными регионами

CODE
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;[/code]

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

[code]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.
blackfin
Цитата(RobFPGA @ Aug 3 2018, 11:41) *
А смысл этого?

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

Понятно, что если через FIFO тащат данные, то строб уже не нужен. Но для понимания логики CDC мой намек вопрошающему не повредит. biggrin.gif
quato_a
Цитата(RobFPGA @ Aug 3 2018, 11:48) *
Приветствую!

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

Удачи! Rob.


Учту в дальнейшем sm.gif
GAYVER
фифо, конечно, круто, но в 6 спартане его нет... или я что то путаю ))
RobFPGA
Приветствую!
Цитата(GAYVER @ Aug 3 2018, 14:10) *
фифо, конечно, круто, но в 6 спартане его нет... или я что то путаю ))
Зато там есть немного Block RAM поболее distributed RAM кучка регистров и тучка логики.
Так что можно и не обращать внимание на IP core FIFO. sm.gif
Удачи! Rob.
GAYVER
Цитата(RobFPGA @ Aug 3 2018, 14:32) *
Приветствую!
Зато там есть немного Block RAM поболее distributed RAM кучка регистров и тучка логики.
Так что можно и не обращать внимание на IP core FIFO. sm.gif
Удачи! Rob.



если вопрос стоит в том чтобы самому что то городить, то мне будет проще переписать входной блок под одинаковую частоту sm.gif. это если нет решения на пару строк кода или использование чего-то стандартного...
RobFPGA
Приветствую!
Цитата(GAYVER @ Aug 3 2018, 14:45) *
если вопрос стоит в том чтобы самому что то городить, то мне будет проще переписать входной блок под одинаковую частоту sm.gif. это если нет решения на пару строк кода или использование чего-то стандартного...
Ну это Вам виднее что проще. По мне так в асинхронном FIFO нет никакой сложности кроме понимания принципов работы.
Удачи! Rob.

Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.