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

Начинаю изучать FPGA (verilog)

2 минуты назад, RobFPGA сказал:

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

А это  уже другие  премудрости - построение цифровой схемы  Когда  вы заводите внешние асинхронные к клоку clk сигналы (SS, SCLK) в синхронную схему   обязательно их надо  пропустить через синхронизатора (2-3 D триггера  подряд)  чтобы убрать эффект метастабильности. В железе  в отличии от программы - сигнал физически имеет конечную скорость и не всегда успевает долететь до середины Днепра... до разных частей схемы вовремя. И когда вы пишете ... if (SS==1) ...  это не значит что проверка идет физически в одном месте - реально может быть десятки/сотни физически разных мест где это строчка реализуется в железе. Поэтому  пропуская через синхронизатор вы гарантируте что вся ваша синхронная схема  будет получать чистый и один и тот же сигнал.


Для этого кстати служать и timing constrain которые вы тоже должны задавать для компиляции в конкретную FPGA.  Но это уже  к Verilog отношение  имеет опосредсвенно. 

Удачи! Rob.

Немножечко дополню. Физически сигнал ещё имеет время нарастания фронта. И если сигнал медленный а ПЛИС быстрая, то такой медленный сигнал может восприниматься схемой не всегда однозначно. А если учесть что линии могут быть отражения, и внешние наводки, о внутри ПЛИС одиночный сигнал от внешнего устройства может быть интерпретирован как несколько сигналов. Почти как дребезг от кнопки. Крайне желательно входной сигнал пропустить после синхронизаторов через небольшой фильтр дребезга. Во всяком случае у меня всегда все входные сигналы от медленных интерфейсов фильтруются от дребезга. И проблем у меня с ними не было.

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


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

3 hours ago, HardRock said:

Если правильно понимаю, самый "правильный" способ - это тактироваться от системного клока и вручную искать фронты SPI сигнала? Но при этом сложность реализации сильно возрастает...

Да. Именно. Но зато все будет работать.
 

2 hours ago, HardRock said:

 Не знал что можно писать posedge|negedge, в описании языка таких конструкций не находил,

Ээх, нельзя так писать. Ув. RobFPGA другое имел в виду, он некое обобщенное описание синтаксиса приводил..

Совсем без  стандарта вам не обойтись. Советую изучить вот этот документ:
1364.1-2002 - IEEE Standard for Verilog Register Transfer

http://www.iuma.ulpgc.es/~nunez/clases-FdC/verilog/Verilog-IEEE-1364.pdf

Там на страницах 9-10 как раз найдете, во что превращается конструкция вида
always @ (posedge clock or posedge set)

 

 

 

 

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


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

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

4 minutes ago, Джеймс said:
3 hours ago, HardRock said:

Если правильно понимаю, самый "правильный" способ - это тактироваться от системного клока и вручную искать фронты SPI сигнала? Но при этом сложность реализации сильно возрастает...

Да.

Нет... :wink:

Удачи! Rob.

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


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

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

1 minute ago, Джеймс said:

Флейма не будет ; )

Какого флейма?  - я же  сказал - "Нет" ... сложность не возрастет.  Даже проще будет! Это же всем ясно :biggrin:

Удачи! Rob. 

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


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

Just now, RobFPGA said:

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

Какого флейма?  - я же  сказал - "Нет" ... сложность не возрастет.  Даже проще будет! Это же всем ясно :biggrin:

Удачи! Rob. 

А, ясно  : )

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


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

8 часов назад, HardRock сказал:

Всем привет. Начал изучение FPGA, есть ряд вопросов.

Могу посоветовать посмотреть эти лекции по Верилогу.

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


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

На тему дебаунса, сделал на автомате с дебаунсом. Перестало работать. Посмотрел что происходит, получилось так (на фото). 

Первый канал это клок SPI, второй - тактирование циклона. Получается что дебаунс сюда не подходит. 

IMG_20200417_010646.jpg

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


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

13 часов назад, HardRock сказал:

самый "правильный" способ - это тактироваться от системного клока и вручную искать фронты SPI сигнала? Но при этом сложность реализации сильно возрастает...

 

Не ясно, что по-вашему "сложность", но выглядит оно примерно так:

 

assign MISO = (ssbuf[1]) ? spireg[7] : 1'bz;
always @(posedge clk) begin
 sclkbuf <= {  sclkbuf[0], SCLK };
 mosibuf <= {  mosibuf[0], MOSI };
 ssbuf   <= {    ssbuf[0], SS   };
 if (ssbuf == 2'b01) begin
  spireg <= spitx;
 end
 if (ssbuf == 2'b10) begin
  spirx <= spireg;
 end
 if (sclkbuf == 2'b01) begin
  spireg <= { spireg[6:0], mosibuf[1] };
 end
end

 

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


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

14 hours ago, HardRock said:

always @(SS, SCLK) begin

Sad Mickey Mouse Images Blood - Mickey Hands In Eyes, HD Png ...

Извините, не удержался.

10 hours ago, HardRock said:

На тему дебаунса, сделал на автомате с дебаунсом.

При чём тут debounce? Вам уже несколько раз сказали - посмотрите стандарты и примеры как "отрабатывается" написанный код. Элементарно посмотрите во что синтезируется Ваш первый модуль. Потом нарисуйте схему (да ручкой на бумажке) как Вы хотите, чтобы работал Ваш слейв. А потом попытайтесь описать то что нарисовано с помощью Verilog'а. Вот когда код синтезируется в то что нарисовано - тогда придёт понимание происходящего.

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


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

10 часов назад, HardRock сказал:

На тему дебаунса, сделал на автомате с дебаунсом. Перестало работать. Посмотрел что происходит, получилось так (на фото). 

Первый канал это клок SPI, второй - тактирование циклона. Получается что дебаунс сюда не подходит. 

А вот нельзя Вам по утрам в зеркало смотреться. А то ведь под горячую руку побьете зеркало. А оно не виновато, что "дебаунс сюда не подходит"...

Но, с другой стороны, эта переписка несколько оживила форум. 

И еще. Если не хотите искать учебники и стандарты, то и хрен с ними. Есть альтернативный и незатратный вариант. Надо найти щуку и тогда "все и сразу и само". Наверняка сейчас в гипермаркетах можно купить, главное чтобы была живая и говорящая...

 

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


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

Вобщем пока сделал так:

module SPISlave(
	input 	wire 	clk,
	/* --- SPI Connection --- */
	inout 	wire 	SS,
	input 	wire 	SCLK,
	input 	wire 	MOSI,
	output	wire 	MISO,
	
	/* --- RxTx Buffers --- */
	output	reg[7:0]  rx_buffer = 8'b00000000,
	input		wire[7:0]	tx_buffer,
	
	output	reg			io_next_byte
);
	//! Number of bits since start of session
	reg [4:0]   io_bits_count;
  
  //! FSM State
	reg [4:0]   fsm;

  integer  debounce;
 
  parameter WAIT_SS     = 0;
  parameter WAIT_SCLK   = 1;
  parameter READ_BIT    = 2;
  parameter WRITE_BIT   = 3;
  parameter NEXT_BIT    = 4;
  
 	initial begin
		io_bits_count 	<= 0;
		fsm 			      <= WAIT_SS;
    debounce        <= 0;
	end
  
  always @(posedge clk) begin
    case (fsm)
      // - Wait for SS
      WAIT_SS: begin
        io_bits_count <= 0;
        debounce      <= 0;
        if (SS == 1) fsm <= WAIT_SCLK;
      end
      
      // - Wait for SCLK goes HIGH
      WAIT_SCLK: begin
        if (SS == 1) begin
          if (SCLK == 1) begin
            fsm           <= READ_BIT;
            io_next_byte  <= 0;
          end
        end else begin
          fsm <= WAIT_SS;
        end
      end
  
      // - Ensure SCLK is high and read bit
      READ_BIT: begin
        if (SS == 1 && SCLK == 1) begin
          rx_buffer <= { rx_buffer[6:0], MOSI };
          fsm       <= WRITE_BIT;
        end else begin
          fsm <= WAIT_SS;
        end
      end
      
      // - Write next bit
      WRITE_BIT: begin
        if (SS == 1 && SCLK == 1) begin
          fsm <= NEXT_BIT;
        end else begin
          fsm <= WAIT_SS;
        end
      end
      
      // - Wait LO
      NEXT_BIT: begin
        if (SS == 1) begin
          if (SCLK == 0) begin
            if (debounce < 1) debounce <= debounce + 1;
            else begin
              io_bits_count <= io_bits_count + 1'b1;
              if (io_bits_count == 8) begin
                io_bits_count <= 0;
                io_next_byte  <= 1;
              end
              
              debounce <= 0;
              fsm <= WAIT_SCLK;
            end
          end
        end else begin
          fsm <= WAIT_SS;
        end
      end
    endcase
  end
  
	assign MISO = tx_buffer[7 - io_bits_count];
endmodule


Оставил тест на ночь в железе пинать 1 байт с небольшой задержкой и рестартом цикла + с ловушками что если циклон или микроконтроллер примут битые данные то тест останавливается. Передалось на данный момент чуть больше 6.5 мегабайт. Рабоает :) При произвольных перезагрузках железок или выдергивании проводов тоже работает.

Заметил на осцилографе что сбой происходил на заднем фронте SCLK (циклон почему-то начинал думать что SCLK уже LOW, хотя ещё HIGH) , добавил задержку в 1 такт при ожидании SCLK в ноль (состояние NEXT_BIT), стало работать стабильно. Но мне это кажется каким-то костылём под конкретную скорость работы порта и подключения (МК и циклон соединены через преобразователь уровней 3.3 - 5). Наверно при другой ситуации  может сбоить если нарастание / спад будет отличаться.

Как вообще в таких случаях стоит синхронизировать чтобы работало в общем случае? Выход с AVR'ки на осцилографе выглядит точнее, при том что забираю его уже с циклона (дублирую сигналы на отдельные выводы)

 

1 час назад, Plain сказал:

Не ясно, что по-вашему "сложность", но выглядит оно примерно так:

Интересный вариант) Попробую.

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


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

1 час назад, iosifk сказал:

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

К щуке придётся ещё искать пиво живое, а с ним сейчас сложно, карантин, да и совсем перестал употреблять спиртное уже несколько лет как, теперь только в бачок омывайки заливаю вкуснейший этиловый спирт)))

Так что придётся вникать во все нюансы по мере необходимости. Мне кстати вариант "жарьте, а масло потом поднесут", как вы говорили, в изучении больше нравится, быстрее практический опыт идёт чем "скучная теория". Благо требования к надёжности сильно ниже и это не промышленная разработка.

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


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

4 часа назад, Plain сказал:

 


assign MISO = (ssbuf[1]) ? spireg[7] : 1'bz;
always @(posedge clk) begin
 sclkbuf <= {  sclkbuf[0], SCLK };
 mosibuf <= {  mosibuf[0], MOSI };
 ssbuf   <= {    ssbuf[0], SS   };
 if (ssbuf == 2'b01) begin
  spireg <= spitx;
 end
 if (ssbuf == 2'b10) begin
  spirx <= spireg;
 end
 if (sclkbuf == 2'b01) begin
  spireg <= { spireg[6:0], mosibuf[1] };
 end
end

 

Можете пожалуйста прокомментировать как это работает? А оно реально работает и стабильно.

sclkbuf и ssbuf всё понятно - это детект фронтов.

Не понятно что происходит со spireg, он используется и для приема и для передачи, при этом вроде как данные не смешиваются.

 

Если правильно понял то в spireg при переходе SS из 0 в 1 записывается значение TX буфера, затем это значение с каждым тактом SPI клока выталкивается вправо (к старшим битам) в MISO, а на место освободившихся бит записывается значение из MOSI. Когда SS переходит в ноль, значение из spireg записывается в RX буфер.

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

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


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

а почему никто не советует какой-нибудь HLS - у альтеры же есть своя подобная штука? положим я олдфаг и HLS-ом этим никогда не пользовался.

но его же не зря так форсят (и усердно и уже давно) ксайлинс с альтерой - есть кто-нибудь в конфе кто пользовался?

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

???

 

1 hour ago, HardRock said:

Если правильно понял то в spireg при переходе SS из 0 в 1 записывается значение TX буфера, затем это значение с каждым тактом SPI клока выталкивается вправо (к старшим битам) в MISO, а на место освободившихся бит записывается значение из MOSI. Когда SS переходит в ноль, значение из spireg записывается в RX буфер.

 

это происходит одновременно, не последовательно. собственно поэтому и HDL, а не Питон, например

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


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

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

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

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

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

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

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

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

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

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