реклама на сайте
подробности

 
 
3 страниц V  < 1 2 3  
Reply to this topicStart new topic
> Не работает модуль на verilog
Sprite
сообщение May 13 2018, 07:48
Сообщение #31


Частый гость
**

Группа: Участник
Сообщений: 154
Регистрация: 11-05-08
Пользователь №: 37 414



Добрый день всем и спасибо за конструктивную критику!

Вернул свой первоначальный вариант, немного доработав его (добавил сигнал data_ready)
Код
module spi_slave
(
    input CLK,
    input CS,
    input MOSI,
    input SCK,
    input [15:0] DATA_IN,
    
    output MISO,
    output reg [15:0] DATA_OUT,
    output reg data_ready
);

    reg [15:0]         data_receive_reg;
    reg [15:0]         data_send_reg;
    reg [4:0]          bit_counter;
    reg               miso_reg;

    //============================
    // По спаду CS заносим данные в
    // data_send_reg
    //============================
    always @(negedge CS)
    begin
        data_send_reg <= DATA_IN;
   end
    
    //============================
    // Если CS=1 - обнуляем bitcounter
    // По фронту SCK заносим данные
    // в регистр data_receive_reg
    //============================
    always @(negedge SCK, posedge CS)
        if (CS)
            bit_counter <= 4'b00000;
        else    
        begin
            data_receive_reg <= { data_receive_reg[14:0], MOSI };
            bit_counter <= bit_counter + 5'b00001;
        end
            
    //============================        
    // Если CS=1 - обнуляем MISO
    // По фронту SCK выводим данные
    //============================
    always @(posedge SCK, posedge CS, posedge bit_counter[4])
        if (CS)
            miso_reg <= 1'b0;
        else if (bit_counter[4])
            miso_reg <= 1'b0;
        else
            miso_reg <= data_send_reg[15-bit_counter];
    assign MISO = miso_reg;        
            
    //============================
    // Синхронизация данных
    //============================
    always @(posedge CLK)
    begin
        DATA_OUT = data_receive_reg;
        data_ready = (bit_counter[4])? 1'b1 : 1'b0;
    end
    //============================
endmodule


Жду конструктивной критики по коду!

Теперь немного вопросов:

Цитата(AnatolySh @ May 12 2018, 21:02) *
Flip-fl0p советовал работать только от одного клока: у Вас это, как понимаю, clk.
И в списке чувствительности, помимо него, имеет право быть (для проекта комильфо) только, если, конечно, он Вам нужен, ещё асинхронный глобальный сброс.
А у Вас в этих списках зоопарк.
Кстати, боюсь предложить Вам ещё включить (если я правильно помню называние) Design Assistant )))
И пока перестаньте нас радовать Вашим RTL: давайте сначала код вылизывать.
Лучше выкладывайте экран функционального моделирования для этого модуля.


1. По фронту clk работать можно, но как быть если частота clk = 36 МГц, а SPI CLK = 21МГц? Останется ли время на выделение фронтов? и обработку state-машин, как советовали Flip-fl0p и iosifk?
2. Для чего вводить сигнал асинхронного глобального сброса? Не совсем понимаю. Для установки триггеров в начальные значения? Каких именно?
3. Не совсем понял фразу "Какой может быть интерес к "RTL-схема", если она потом оптимизируется и от нее мало что останется?". Т.е. при добавлении в проект нового кода RTL-схема уже созданных блоков может быть изменена? Если это так, то как можно это предотвратить? И вообще как можно тогда быть уверенным, что любой идеальный код будет работать так, как это планировалось?
4. По совету AnatolySh поменял настройки вместо временного на функциональное моделирование.

Функциональная симуляция:



И RTL:




Проект с этим кодом прошил и поставил вчера на тест: с МК отправляю запись данных по адресу 2, затем считываю данные по этому адресу и сверяю с отправленным значением. Далее повторяю процедуру, но по этому же адресу пишу считываю и сверяю уже другие данные. Если данные отправленные и принятые не совпадают - то выставляю флаг ошибки. Пришел сегодня посмотреть результаты - отправлено принято всего 5 300 000 посылок, кол-во ошибок - 0. Результат вполне устраивает.
Но есть узкое место: Т.к. адрес и данные поступают двумя разными SPI-передачами по 16 бит, то в случае помехи по сигналу CS может произойти рассинхронизация в приеме дынных, проще говоря ПЛИС не поймет что пришло данные или адрес. Можно конечно ввести дополнительный сигнал синхронизации, но я думаю поступить по другому - держать CS в нуле на все 32 бита, пропуская последовательно адрес и данные.

Сообщение отредактировал Sprite - May 13 2018, 07:50
Go to the top of the page
 
+Quote Post
nice_vladi
сообщение May 13 2018, 08:26
Сообщение #32


Участник
*

Группа: Участник
Сообщений: 50
Регистрация: 7-09-16
Из: Томск
Пользователь №: 93 239



Цитата(Sprite @ May 13 2018, 07:48) *
Добрый день всем и спасибо за конструктивную критику!

Вернул свой первоначальный вариант, немного доработав его (добавил сигнал data_ready)
...


Я бы постарался отвязаться от работы на внешней тактовой частоте и завел бы внутри ПЛИС свою, с хорошим перетактированием, допустим, 100 МГц. Работать внутри ПЛИС на внешней частоте, асинхронной внутренним частотам ПЛИС - головная боль. Тем более, когда частоты невысокие и не составляет труда с помощью перетактирования затащить данные под внутреннюю частоту ПЛИС.

Тогда можно было бы очень просто продетектировать фронты тактовой частоты SPI и по ним (при условии опущенного CS) укладывать данные с шины данных в сдвиговый регистр. А окончание одной посылки отсчитывать флагом заполнения 3битного счетчика (он как раз 8 тактов насчитает).

Что-то вроде:

CODE


if (~CS) cnt <= cnt + 1'b1;
else cnt <= '0;

if (front & ~CS) shft_reg <= shft_reg << 1 | dat ;


if (&cnt) rdy_dat <= shft_reg;


И писанины меньше, и нагляднее. Ну и да: Questa/ModelSim - маст хев. Без них - никуда. Встроенный симулятор Квартуса - боль.
Go to the top of the page
 
+Quote Post
Flip-fl0p
сообщение May 13 2018, 08:50
Сообщение #33


В поисках себя...
****

Группа: Свой
Сообщений: 604
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140



Цитата
1. По фронту clk работать можно, но как быть если частота clk = 36 МГц, а SPI CLK = 21МГц? Останется ли время на выделение фронтов? и обработку state-машин, как советовали Flip-fl0p и iosifk?

У вас Cyclone III. Примените один блок PLL...

Цитата
2. Для чего вводить сигнал асинхронного глобального сброса? Не совсем понимаю. Для установки триггеров в начальные значения? Каких именно?

Для Cyclone III можно и без асинхронного глабального сброса. На данном чипе регистры можно принудительно инициализировать нужными значениями. Сделайте правильно без асинхронного сброса сначала...

Цитата
3. Не совсем понял фразу "Какой может быть интерес к "RTL-схема", если она потом оптимизируется и от нее мало что останется?". Т.е. при добавлении в проект нового кода RTL-схема уже созданных блоков может быть изменена? Если это так, то как можно это предотвратить? И вообще как можно тогда быть уверенным, что любой идеальный код будет работать так, как это планировалось?

RTL нужен только для того, чтобы посмотреть иерархию блоков, посмотреть какие блоки куда подключены. Ну и оценить приблизительно соответствует ли схема Вашему ожиданию. Но потом данная схема ложится на логические ячейки FPGA и от того RTL представления практически ничего не остается, т.к САПР всё это добро оптимизирует. Поэтому с точки зрения схемотехники - смотреть на RTL смысла нет.

Цитата
4. По совету AnatolySh поменял настройки вместо временного на функциональное моделирование.

Изучайте Modelsim. Это стандарт де-факто.

А вообще Вам уже говорили.
Сначала делайте автомат который принимает биты.
Он занимается только приемом битов.
Потом этот автомат переедает данные другому автомату, который уже обрабатывает слова. И.т.д. Сейчас Вы вернулись к неправильному варианту.

Вот есть сигнал SCK.
Вы его для начала пропускаете через цепочку синхронизаторов для подавления метастабильного состояния.
Затем пропускаете через простейший анти дребезг, чтобы удалить возможный дребезг сигнала.
Потом выделяете детектором фронта - нужный вам фронт.
И все это работает на системном клоке, который Вы формируете на PLL.
В итоге все синхронные always блоки будут содержать только @(posedge CLK)
Go to the top of the page
 
+Quote Post
iosifk
сообщение May 13 2018, 10:11
Сообщение #34


Гуру
******

Группа: Модераторы
Сообщений: 3 884
Регистрация: 8-09-05
Из: спб
Пользователь №: 8 369



Цитата(Sprite @ May 13 2018, 10:48) *
Проект с этим кодом прошил и поставил вчера на тест: с МК отправляю запись данных по адресу 2, затем считываю данные по этому адресу и сверяю с отправленным значением. Далее повторяю процедуру, но по этому же адресу пишу считываю и сверяю уже другие данные. Если данные отправленные и принятые не совпадают - то выставляю флаг ошибки. Пришел сегодня посмотреть результаты - отправлено принято всего 5 300 000 посылок, кол-во ошибок - 0. Результат вполне устраивает.

Про все дела уже написали, но вот есть еще и небольшенькая такая тонкость...
Если дело поставлено именно так: " отправляю запись данных по адресу 2, затем считываю данные по этому адресу и сверяю с отправленным значением", причем без паузы и без выдачи на шину данных другого кода, то вполне возможно, что читаете Вы не содержимое ячеек памяти, а паразитный емкостной заряд на шине... А он конечно всегда будет таким, какой Вы и выставляли на этой шине... sm.gif
Так что надо "записать по правильному адресу", потом выдать что-то по любому "пустому месту", лишь бы на шинах поменялись данные, а только потом читать...
А если делать по хорошему, то в блок, который открывает шинники ПЛИС по 3-му состоянию, надо сделать задержку на время разряда емкости на линиях. Так хоть будет немного дольше, но ПЛИС будет греться значительно меньше...




--------------------
www.iosifk.narod.ru
Go to the top of the page
 
+Quote Post
Sprite
сообщение May 15 2018, 03:29
Сообщение #35


Частый гость
**

Группа: Участник
Сообщений: 154
Регистрация: 11-05-08
Пользователь №: 37 414



Добрый день всем!

Еще одна редакция модуля с учетом исправлений и замечаний:

Код
module SPI_slave2
(
    input clk,
    input cs,
    input mosi,
    input sck,
    input [15:0] data_in,
    
    output reg miso = 1'b0,
    output reg [15:0] adr_out = 32'd0,
    output reg [15:0] data_out = 32'd0,
    output reg adr_ready = 1'b0,
    output reg data_ready = 1'b0,
    output wr,
    output [15:0] bitcnt
);

    reg[1:0] sck_reg;
    reg[1:0] mosi_reg;
    reg[5:0] bit_counter;
    reg[15:0] data_send_reg;

    wire sck_risingEdge;
    wire sck_fallingEdge;
    wire mosi_data;

    //---------------------------------
    // Выделяем фронт и спад сигнала sck
    //---------------------------------
    always @(posedge clk)
    begin
        if(cs)
            sck_reg <= 2'b00;
        else
            sck_reg <= {sck_reg[0], sck};
    end
    assign sck_risingEdge = (sck_reg == 2'b01);
    assign sck_fallingEdge = (sck_reg == 2'b10);

    //---------------------------------
    // Выделяем сигнал mosi
    //---------------------------------
    always @(posedge clk)
    begin
        if(cs)
            mosi_reg <= 2'b00;
        else
            mosi_reg <= {mosi_reg[0], mosi};
    end
    assign mosi_data = mosi_reg[1];

    //---------------------------------
    // Если cs==1 - очищаем приемный регистр
    // и обнуляем счетчик.
    // Иначе по спаду sck принимаем данные
    // и инкрементируем счетчик.
    //---------------------------------
    always @(posedge clk)
    begin
        if(cs)
        begin
            adr_out <= 16'd0;
            data_out <= 16'd0;
            bit_counter <= 6'b000000;
        end
        else if (sck_fallingEdge)
        begin
            if (bit_counter[4])
                data_out <= {data_out[14:0], mosi_data};
            else
                adr_out <= {adr_out[14:0], mosi_data};
            bit_counter <= bit_counter + 6'b000001;
        end
    end

    //---------------------------------
    // Выделяем сигналы готовности адреса и данных
    //---------------------------------
    always @(posedge clk)
    begin
        adr_ready <= (~cs) && (bit_counter[4]);
        data_ready <= (~cs) && (bit_counter[5]);
    end
    //---------------------------------
    // Если cs==1 - заносим в регистр данные для посылки
    // Иначе сдвигаем данные и отправляем побитно
    //---------------------------------
    always @(posedge clk)
    begin
        if(cs)
        begin
            miso <= 1'b0;
            data_send_reg <= data_in;
        end    
        else if (sck_risingEdge)
        begin
            if (bit_counter[4])
            begin
                miso <= data_send_reg[15];
                data_send_reg <= {data_send_reg[14:0], 1'b0};
            end
        end
    end
    
    assign wr = adr_out[15];
    assign bitcnt = bit_counter;
    
endmodule

По совету nice_vladi и Flip-fl0p поставил pll, умножил частоту на 3 - получил 108Мгц. Провел функциональную симуляцию - все ОК. Частота SPI - 5 МГц, пока выше не поднимал. Итоговый Waveform:



В результате появились "слаки"(



Насколько это криминально - не знаю.

Файл констрейна:
Код
derive_clock_uncertainty
create_clock -name clk -period 36.1MHz [get_ports {clk}]
create_clock -name sck -period 5MHz [get_ports {SCK}]
create_generated_clock -name CLK_108MHz -source [get_ports {clk}] -multiply_by 3 -duty_cycle 50 [get_nets {inst19|altpll_component|auto_generated|wire_pll1_clk[0]}]
Go to the top of the page
 
+Quote Post
Flip-fl0p
сообщение May 15 2018, 04:43
Сообщение #36


В поисках себя...
****

Группа: Свой
Сообщений: 604
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140



Вы как-то очень избирательно читаете rolleyes.gif
PLL поставили - уже хорошо. Работаете только по одному CLK - отлично !
А вот про цепочку синхронизаторов для подавления метастабильного состояния забыли.
Да и простейший фильтр дребезга не мешало бы поставить. Сигналы Вашего SPI относительно FPGA имеют очень пологие фронты. Это надо фильтровать. А то задолбаетесь искать сбои в работе, когда они будут. А они будут будьте уверены rolleyes.gif
И да. Я бы не считал линию SCK полноценным клоком. Соответственно из констрейнов его убрать нафиг.
Go to the top of the page
 
+Quote Post
Flip-fl0p
сообщение May 15 2018, 07:30
Сообщение #37


В поисках себя...
****

Группа: Свой
Сообщений: 604
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140



Смотрите как я делаю:
1. У меня отдельный модуль антидребезга, где внутри есть цепочка синхронизации для подавления метастабильного состояния. Я параметрами задаю длину цепочки синхронизации и время фильтрации дребезга.
2. У меня отдельный модуль детектора фронтов, где я параметрами задаю тип детектируемого фронта.
Самое главное, что это у меня отдельные модули, которые отлажены и гарантированно работают. И если что-то у меня не работает, то я знаю, что 100% проблема не в них. Тем более, эти модули присутствуют в большинстве проектов. Зачем по 100 раз описывать одно и то же. Да ещё и тестировать их потом ?




PS. Не претендую на правильность. Но практика показала, что так быстрее и удобнее.
Сначала на бумаге набросал всю схему и все алгоритмы, потом перенес на HDL - более 50% проекта собрал из готовых библиотечных блоков собственной разработки
Go to the top of the page
 
+Quote Post
Sprite
сообщение May 15 2018, 07:52
Сообщение #38


Частый гость
**

Группа: Участник
Сообщений: 154
Регистрация: 11-05-08
Пользователь №: 37 414



Цитата(Flip-fl0p @ May 15 2018, 11:43) *
Вы как-то очень избирательно читаете rolleyes.gif
PLL поставили - уже хорошо. Работаете только по одному CLK - отлично !
А вот про цепочку синхронизаторов для подавления метастабильного состояния забыли.
Да и простейший фильтр дребезга не мешало бы поставить. Сигналы Вашего SPI относительно FPGA имеют очень пологие фронты. Это надо фильтровать. А то задолбаетесь искать сбои в работе, когда они будут. А они будут будьте уверены rolleyes.gif
И да. Я бы не считал линию SCK полноценным клоком. Соответственно из констрейнов его убрать нафиг.


Синхронизаторы - это хорошо) Подумаю над этим. Если у Вас есть готовый пример фильтра антидребезга - может поделитесь? Насчет SCK - согласен, только я его потому и описывал в констрейне, т.к. надоели всякие варнинги типа "found dedicated clock...".
Go to the top of the page
 
+Quote Post
Flip-fl0p
сообщение May 15 2018, 07:57
Сообщение #39


В поисках себя...
****

Группа: Свой
Сообщений: 604
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140



Цитата(Sprite @ May 15 2018, 10:52) *
Синхронизаторы - это хорошо) Подумаю над этим. Если у Вас есть готовый пример фильтра антидребезга - может поделитесь? Насчет SCK - согласен, только я его потому и описывал в констрейне, т.к. надоели всякие варнинги типа "found dedicated clock...".

Над синхронизаторами не думать надо, а ставить их !
Вот пример фильтра.
http://allaboutfpga.com/wp-content/uploads...gic_circuit.jpg
Можно описать в виде FSM, но мне в виде схемы он понятней. Легко сделать параметризируемым
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 27th May 2018 - 19:12
Рейтинг@Mail.ru


Страница сгенерированна за 0.00918 секунд с 7
ELECTRONIX ©2004-2016