Jump to content

    

Влияние смежных цепей на работу схемы.

Доброго времени суток.

В проекте есть модуль spi slave.  Обнаружил ошибку в логике данного модуля. При нормальном состоянии, когда мастер генерирует ss в начале каждого байта, счетчик nb постоянно сбрасывается по фронту ss и выход sdout находится в 0. Если по какой либо причине сигнал ss отсутствует, nb начинает считать до 8 и затем выдаст на выходе sdout 1. Таким образом модуль выдаст ошибку если долго нет ss от мастера.  Получается не работает блок логики, срабатывающий по фронту ss.


module spi_slave (rstb,ss,sck,sdin,done,rdata, sdout, nfOut);
input rstb;
input ss;
input sck;
input sdin; 
output reg done;
output reg [7:0] rdata;


output reg sdout;
output wire [2:0] nfOut;

reg [7:0] rreg;
reg [3:0] nb = 0;           // счетчик бит
reg [3:0] nf = 0;

assign nfOut = nf[2:0];

always @(posedge sck or negedge rstb)
begin
if (rstb == 0)
  begin                     // сбросить в исходное при сигнале сброса

  done = 0;
  nb   = 0;
  nf    = 0;
  sdout = 0;
  end
else
  if (ss == 0)              // идет прием байта
    begin 
    rreg ={rreg[6:0],sdin}; // прием старшим вперед, сдвиг влево
    nb = nb + 1;            // increment bit count
    if(nb != 8) done = 0;
    else                    // на 8 импульсе выставить done
      begin
      rdata=rreg;
      done = 1;
      nb   = 0;
      nf = nf + 1;
      if(nf == 8) 
        begin
        sdout = 1;
        nf    = 0;   
        end
      end
    end
  else                      // байт принят и переписан
    begin
    nb   = 0;
    done = 0;
    nf = 0;
    sdout = 0;
    end
end
endmodule

Проблема заключается в том, что при работе уже на железе (Cyclone II E52C8),  механизм сброса счетчика nb не работает, и каждый 8 байт я вижу одиночный импульс на sdout.

Осторожно трафик.

Спойлер

Но главное не это. Я случайно обнаружил, что если убрать сброс Sdout вот здесь:

always @(posedge sck or negedge rstb)
begin
if (rstb == 0)
  begin                     // сбросить в исходное при сигнале сброса

  done = 0;
  nb   = 0;
  nf    = 0;
  sdout = 0;
  end

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

У меня подозрение, что данные изменения вносят паразитные емкости, которые влияет на работу модуля spi.

Ниже представлена диаграмма, после внесения вышеописанных изменений.

Осторожно трафик.

Спойлер

Пропали импульсы на sdout, младший бит счетчика больше 1 не считает. Собственно так и должно работать.

Edited by Cianid

Share this post


Link to post
Share on other sites

Как насчет неблокирующих присваиваний?

Share this post


Link to post
Share on other sites

Когда я почувствовал, что точно железячная поблема (код в modelsim прошел массу тестов), то рука невольно на автомате уже тянется в раздел Timing Analyzer. 

Share this post


Link to post
Share on other sites
4 часа назад, ViKo сказал:

Как насчет неблокирующих присваиваний?

Проблема не должна быть в этом. Я прогонял данную схему в симуляции. Просто если вывести какие нибудь промежуточные точки на пины, чтобы посмотреть осциллографом, уже тогда  ПЛИС перестает корректно работать. 

Share this post


Link to post
Share on other sites

Странно, вы пишите: " механизм сброса счетчика nb не работает, и каждый 8 байт я вижу одиночный импульс на sdout" Но тогда причем здесь

reg [3:0] nb = 0;           // счетчик бит

Так все таки, байты или биты? как она должна у вас работать? Что именно вы сделали в симуляторе?

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

Share this post


Link to post
Share on other sites
2 часа назад, des00 сказал:

Странно, вы пишите: " механизм сброса счетчика nb не работает, и каждый 8 байт я вижу одиночный импульс на sdout" Но тогда причем здесь


reg [3:0] nb = 0;           // счетчик бит

Так все таки, байты или биты? как она должна у вас работать? Что именно вы сделали в симуляторе?

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

Да, я ошибся, счетчик байтов это nf. При нормальной работе этот счетчик не должен считать дальше 1, т.к при следующем фронте ss он сбросится.

Share this post


Link to post
Share on other sites
1 hour ago, Cianid said:

т.к при следующем фронте ss он сбросится.

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

Share this post


Link to post
Share on other sites
24 минуты назад, des00 сказал:

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

Можете пояснить?

Share this post


Link to post
Share on other sites
42 minutes ago, Cianid said:

Можете пояснить?

вы работаете по фронту частоты SCK. в SPI интерфейсе она мало того что отключаема, так еще и ее фронт не обязательно присутствует при сигнале выбора слейва. Т.е. вы не ловите фронт сигнала ss, вы ловите его уровень, при фронте сигнала SCK. 

Share this post


Link to post
Share on other sites
15 hours ago, Cianid said:

Просто если вывести какие нибудь промежуточные точки на пины, чтобы посмотреть осциллографом, уже тогда  ПЛИС перестает корректно работать. 

Так может сперва код написать правильно?

Share this post


Link to post
Share on other sites
17 hours ago, Cianid said:

Проблема не должна быть в этом. Я прогонял данную схему в симуляции. Просто если вывести какие нибудь промежуточные точки на пины, чтобы посмотреть осциллографом, уже тогда  ПЛИС перестает корректно работать. 

Обычно SPI синхронизируют с внутренней частотой ПЛИС, используя фронты сигналов sck и ss как разрешение для частоты ПЛИС.

Share this post


Link to post
Share on other sites
7 часов назад, likeasm сказал:

Обычно SPI синхронизируют с внутренней частотой ПЛИС, используя фронты сигналов sck и ss как разрешение для частоты ПЛИС.

Не сказал бы. Многое зависит от соотношения частот. Если SPI быстрый, то так лучше не делать.

Share this post


Link to post
Share on other sites

 

2 часа назад, dvladim сказал:

Не сказал бы. Многое зависит от соотношения частот. Если SPI быстрый, то так лучше не делать.

А почему так лучше не делать. Лично я бы делал так:

1. Синхронизировал все сигналы SPI с внутренней частотой ПЛИС.

2. В случае если SPI медленный - поставил бы простейший антидребезг, чтобы исключить влияние пологих фронтов сигналов SPI.

3. Поставил бы детекторы фронтов на сигналы SPI. 

4. Вся схема работала бы на внутренней частоте ПЛИС, а вся обработка бы велась событийно - по детектированным фронтам SPI.

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

Share this post


Link to post
Share on other sites
6 hours ago, Flip-fl0p said:

 

А почему так лучше не делать. Лично я бы делал так:

1. Синхронизировал все сигналы SPI с внутренней частотой ПЛИС.

2. В случае если SPI медленный - поставил бы простейший антидребезг, чтобы исключить влияние пологих фронтов сигналов SPI.

алгоритм не полный, что бы вы делали, "В случае если SPI быстрый". положим 90МГц. Ваши действия?

Share this post


Link to post
Share on other sites
32 minutes ago, des00 said:

алгоритм не полный, что бы вы делали, "В случае если SPI быстрый". положим 90МГц. Ваши действия?

нарезал бы всё внутренним 400 МГц клоком и жил бы припеваючи. :))

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this