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

Всем привет.

 

Возникла такая задача:

Некое устройство генерирует раз в иногда управляющее слово и сигнал записи write длительностью в один такт к нему. Это в одном клоковом домене.

В другом клоковом домене есть шина авалоновская, которая должна читать это управляющее слово по сигналу read. Шина авалон выставляет сигнал чтения гораздо чаще, чем появляется новое управляющее слово. Причем при чтении регистр (? некий девайс), хранящий управляющее слово, должен сбрасываться.

Это как в обычных МК, например ждем флаг завершения преобразования АЦП, который при чтении автоматически сбрасывается).

 

Сразу же напрашивается обычное двухклоковое FIFO. Я его и поставил. Далее смотрю сигналтабом результат. Записал управляющее слово, все как надо. Читаю его раз, все норм. Следующее чтение (и все последующие) - тоже самое значение! Вроде бы должно было появиться что-то вроде 0xFF вслед за управляющим словом, не? Я что-то не так делаю или это принципиальное свойство FIFO?

 

Вообще, какое есть более правильное решение данной проблемы? Тут имеется переход из одного клокового домена в другой, если бы мне не нужно было сбрасывать управляющее слово после чтения, я бы поставил регистр тупо и написал бы set false_patch... Однако...

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

 

А как реализовать FIFO самостоятельно на регистрах, без использования блоков памяти?

 

 

QII10.1, Altera, Verilog (или SV)

 

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


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

А флаг empty используете ?

Память совсем не обязательно использовать, скажите ядру использовать регистры.

 

Скажите как часто должна сбоить ваша схема? Раз в сто лет, в миллиард лет?

 

Если делать руками, то получится 2 перехода между доменами.

Асинхронный сброс не поможет: при снятии сброса может прийти активный фронт клока, при активизации сброса на выходе имеет право случиться глитч.

Только синхронизатор.

Нужно вычислить количество регистров в цепочке при той разводке, которая получается при понуждении placer-а сделать регистры поближе, чтобы достигнуть нужной частоты сбоев. И в последнюю очередь надо задушить анализатор таймингов, чтобы не ругался.

А так как толпы инженеров не могут ошибаться водка полезна стандартного ядра DualClock FIFO достаточно для надежной работы ну почти любой схемы при почти любых сочетаниях клоков.

 

Я бы использовал готовое fifo и не парился. Ну можно исправить на регистровую реализацию, если память жалко. Синтезатор не дурак, почти все лишнее почикает.

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


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

А вот так не подойдет:

entity FIFO_Reg is
  generic(Width : integer);
Port ( Data_In	 : in  STD_LOGIC_VECTOR (Width-1 downto 0);
	   WRITE	  : in  STD_LOGIC;
	   FULL		: out  STD_LOGIC;
	   CLK		 : in  STD_LOGIC;
	   CE		 : in  STD_LOGIC;
	   RST	  : in  STD_LOGIC;
	   Dato_Out	: out  STD_LOGIC_VECTOR (Width-1 downto 0);
	   READ	   : in  STD_LOGIC;
	   EMPTY	   : out  STD_LOGIC:='1');
end FIFO_Reg;

architecture RTL of FIFO_Reg is

signal Empty_State, Empty_State_Next : std_logic:='1';
signal Data_Out_Buf, Data_Out_Next : std_logic_vector(Width-1 downto 0);

begin

EMPTY <= Empty_State;
DO <= Data_Out_Buf;

-- Sync Process --
process(CLK,nRESET)
begin
   if RST='1' then
	  Empty_State <= '1';
   elsif rising_edge(CLK) then
	  if CE='1' then
		 Empty_State <= Empty_State_Next;
		 Data_Out_Buf <= Data_Out_Next;
	  end if;
   end if;
end process;
-- End of Sync Process --

-- Comb Process --
process(Empty_State, nWRITE, Data_In, READ, Data_Out_Buf)
begin
   -----Default Values-----
   Empty_State_Next <= Empty_State;
   FULL <= '1';
   Data_Out_Next <= Data_Out_Buf;

   -----Case section-----
   case (Empty_State) is 
	  when '1' =>
		 if WRITE='0' then
			FULL <= '0';
			Data_Out_Next <= (others => 'X');
		 else
			Empty_State_Next <= '0';
			FULL <= '0';
			Data_Out_Next <= Data_In;
		 end if;
	  when '0' =>
		 if READ='1' then
			if WRITE='1' then
			   FULL <= '0';
			   Data_Out_Next <= Data_In;
			else
			   Empty_State_Next <= '1';
			   FULL <= '0';
			   Data_Out_Next <= (others => 'X');
			end if;
		 end if;
	  when others=>NULL;
   end case;
end process;

end RTL;

 

И можно последовательно подключить сколько угодно таких буферов.

Изменено пользователем ZED

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


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

Сразу же напрашивается обычное двухклоковое FIFO. Я его и поставил. Далее смотрю сигналтабом результат. Записал управляющее слово, все как надо. Читаю его раз, все норм. Следующее чтение (и все последующие) - тоже самое значение! Вроде бы должно было появиться что-то вроде 0xFF вслед за управляющим словом, не? Я что-то не так делаю или это принципиальное свойство FIFO?

это штатное поведение FIFO, см. http://www.altera.com/literature/ug/ug_fifo.pdf

используйте флаги empty и т.п.

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


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

Возникла такая задача:

фифо в вашей задаче вообще не нужно

 

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


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

фифо в вашей задаче вообще не нужно

Это не те роботы, которых вы ищите...

А что в их задаче нужно?

Какой еще готовый элемент может скрыть от пользователя тяготы перехода между клоками?

 

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


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

Второй раз даю линк, который уже дал Leka

http://electronix.ru/forum/index.php?showt...mp;#entry831264

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


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

Для начала я сделал вот так:

//clk1
input wrreq;
//clk2
input rdreq;
input read;
output data;

reg            [31:0]    fifo_contr_reg;
reg                        read_d;

//delay read signal for reset fifo_reg
always @(posedge csi_avalon_clk_clk) begin
    read_d <= read;
end
//reg
always @(posedge clk2 or posedge wrreq) begin
    //async preset (write control word from ALT2GXB)
    if (wrreq) begin
        fifo_contr_reg <= {20'd0, len, accept, crc_valid};
    end else begin
    //sync reset after read
        if (read_d)
            fifo_contr_reg <= 0;
    //read from avalon
        else     if (rdreq)
            data <= fifo_contr_reg;
        else
            fifo_contr_reg <= fifo_contr_reg;    
    end
end

Все вроде как заработало. Но случай когда wrreq будет очень близко от rdreq очень редкий, мне его не поймать...

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


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

А что в их задаче нужно?

почти два месяца не был на форуме, удивительно что со всеми случилось..... :blush:

 

решение для сабжевого случая :

Некое устройство генерируетраз в иногда управляющее слово и сигнал записи write длительностью в один такт к нему. Это в одном клоковом домене.

В другом клоковом домене есть шина авалоновская, которая должна читать это управляющее слово по сигналу read. Шина авалон выставляет сигнал чтения гораздо чаще, чем появляется новое управляющее слово. Причем при чтении регистр (? некий девайс), хранящий управляющее слово, должен сбрасываться.

 

 
module pipa (input logic iwclk, irclk, iwrite, iwdat, iread, ordat);

  logic write_at_wclk;
  logic write_at_rclk;

  logic wdat_latched;

  always_ff @(posedge iwclk) begin
    write_at_wclk <= iwrite;
    if (iwrite)
      wdat_latched <= iwdat;
  end

  pulse_synchronizer
  #(
    .pLENGTH ( 3 )
  )
  pulse_synchronizer
  (
    .clkin    ( iwclk ) , .resetin  ( 1'b0 ) , .sin   ( write_at_wclk ) ,
    .clkout   ( irclk ) , .resetout ( 1'b0 ) , .sout  ( write_at_rclk )
  );

  always_ff @(posedge irclk) begin
    if (write_at_rclk)
      ordat <= wdat_latched;
    else if (iread)
      ordat <= '0;
  end

endmodule

 

ну и не забыть добавить

 

set_clock_groups -exclusive -group iwclk 
set_clock_groups -exclusive -group irclk 

set_max_delay -from [get_registers {*|pipa|wdat_latched}] -to  [get_registers {*|pipa|ordat}] $<Two read clock period>

pulse_synchronizer.v

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


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

Скажу прямо - разобраться в коде des00 за ~15 минут не смог.

Прошу откликнуться тех, кто разобрался, сколько времени потратили на это - только честно.

 

 

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


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

"pulse syncronizer" - может "зависнуть", если частота clkin >> clkout, и при этом частота sin >> clkout - те терять все входные импульсы после первого. Тк триггер по clkout может не поймать сброс level.

 

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


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

Скажу прямо - разобраться в коде des00 за ~15 минут не смог.

Прошу откликнуться тех, кто разобрался, сколько времени потратили на это - только честно.

3-5 минут. На бумажке нарисовал.

 

"pulse syncronizer" - может "зависнуть", если частота clkin >> clkout, и при этом частота sin >> clkout - те терять все входные импульсы после первого. Тк триггер по clkout может не поймать сброс level.

Логично, что нужно успевать считывать слово, но задача так и была поставлена: частота чтения выше чем записи.

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


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

Проанализировал, что именно помешало мне сходу разобраться в коде:

 

1) внешний модуль pulse_synchronizer визуально врезан

в середину одной из двух параллельных цепочек:

iwrite --> pulse_synchronizer --> write_at_wclk --> ordat

iwrite --> wdat_latched --> ordat

 

2) выходной триггер ordat имеет два независимых входа разрешения записи:

write_at_rclk --> ordat

iread --> ordat

 

Имхо, эти усложнения - излишни, после упрощения:

 

module pipa (input logic iwclk, irclk, iwrite, iwdat, iread, ordat);

    logic write_at_rclk;

    pulse_synchronizer #(.pLENGTH( 3 )) pulse_synchronizer(
        .clkin    ( iwclk ) , .resetin  ( 1'b0 ) , .sin   ( iwrite ) ,
        .clkout   ( irclk ) , .resetout ( 1'b0 ) , .sout  ( write_at_rclk )
    );

    logic clr;
  
    always_ff @(posedge irclk) begin

        if (write_at_rclk)
            clr <= 0;
        else 
            if (iread)
                clr <= 1;
                
        if(iread)
            if (clr)
                ordat <= 0;
            else 
                ordat <= iwdat;
    end            
     
endmodule

Изменено пользователем Leka

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


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

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

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

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

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

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

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

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

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

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