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

Не работает модуль на verilog

Проект Во вложении. entity - test3.qpf Собирал в Quartus II 9.1, использовал для теста встроенный симулятор (файл test3.vwf)
Ну, функциональное моделирование у Вас проходит безошибочно?

Если так, то ломающееся временное свидетельствует об асинхронщине (а она есть у Вас в модуле spi_slave), либо..

Не хотите для начала именно с асинхронщиной побороться, чтобы на примере этого проекта навсегда забыть о ней?

 

На всякий случай рекомендую и на метастабильность обратить внимание...

 

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


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

to Sprite Посмотрел я на времянку и мозг отказал минут на 5 - как машина может находиться одновременно в нескольких состояниях? Там вообще мусор должен быть на моделировании - начальное состояние не определено - либо сброс добавьте, либо начальное условие при инициализации. Или это картинка не моделирования, а сигнал тап?

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

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

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


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

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

Я всё ищу такую опцию для ModelSim-а, а то запарился каждый раз сброс прописывать.
Может, signal_force вас спасёт? Но, по-хорошему, все триггеры, включая FSM в проекте рекомендуется заводить со сбросами

(вот какой лучше: синхронизированный асинхронный или синхронный - каждый выбирает по себе )))

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

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


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

Может, signal_force вас спасёт?

Примерно так и делаю. Но всё равно ведь ручками приходится. Хотелось бы чтобы он сам по умолчанке делал.

 

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


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

Примерно так и делаю. Но всё равно ведь ручками приходится. Хотелось бы чтобы он сам по умолчанке делал.
Вот вы снова привязываетесь к инструменту. Комильфо проект (включая testbench) - инструментонезависимый.

Пишите так, чтобы и реализация и моделирование проходили бы одинаково и в Modelsime и в Active-HDL-е и где бы то ни было....

 

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


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

Ну, функциональное моделирование у Вас проходит безошибочно?

Если так, то ломающееся временное свидетельствует об асинхронщине (а она есть у Вас в модуле spi_slave), либо..

Не хотите для начала именно с асинхронщиной побороться, чтобы на примере этого проекта навсегда забыть о ней?

 

На всякий случай рекомендую и на метастабильность обратить внимание...

 

Спасибо за дельный совет! Действительно, данные (регистр data_in[15:0]) поступавшие в модуль были несинхронизированы, поправил. По совету iosifk поставил ветку default в state-машину. Но ошибка в модуле по прежнему имеется, в железе data_out после 10-15 раза выдает неверные данные, разбираюсь дальше.

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


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

Но ошибка в модуле по прежнему имеется, в железе data_out после 10-15 раза выдает неверные данные, разбираюсь дальше.
Пришлите "синхронизированный" модуль посмотреть.

Ошибка на временном моделировании так и осталась?

Кстати, а Вы умеете SignalTap-ом пользоваться?

 

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


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

Зачем вообще проводить временную симуляцию ?

Это потраченное впустую уйма времени !

Проводите в Modelsim функциональное моделирование. Когда HDL описание работает как задумано, то описываете временные ограничения. И практически наверняка проект заработает сразу.

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


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

Пришлите "синхронизированный" модуль посмотреть.

Ошибка на временном моделировании так и осталась?

Кстати, а Вы умеете SignalTap-ом пользоваться?

Моделировал в стандартном квартусовском симуляторе - ошибок нет, но при работе с железом ошибка присутствует: для этого специально поставил 2 компаратора на вход data_in и 2 компаратора на выход data_out, а сигналы с компараторов вывел на светодиоды платы. На входе данные всегда правильные, а выход после N передач выдает либо фиксированные данные, либо 0. SignalTap-ом пользоваться не умею.

module spi_slave
(
    input CLK,
    input CS,
    input MOSI,
    input SCK,
    input [15:0] DATA_IN,
    
    output reg MISO,
    output reg [15:0] DATA_OUT
);

    reg [15:0]     data_receive_reg;
    reg [15:0]     data_send_reg;
    reg [3: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'b0000;
        else
        begin
            data_receive_reg[15-bit_counter] <= MOSI;
            bit_counter <= bit_counter + 4'b0001;    
        end
    //============================        
    // Если CS=1 - обнуляем MISO
    // По фронту SCK выводим данные
    //============================
    always @(posedge SCK, posedge CS) 
        if (CS)
            miso_reg <= 1'b0;
        else
            miso_reg <= data_send_reg[15-bit_counter];
    
    //============================
    // Синхронизация данных
    //============================
    always @(posedge CLK) 
    begin
        DATA_OUT = data_receive_reg;
        MISO = miso_reg;
    end
    //============================
endmodule

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

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


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

Жуть !

1. Фильтруйте входные внешние асинхронные сигналы от пологих фронтов, и возможного дребезга около фронтов.

2. Работайте только про одному фронту синхросигнала. Хотите выделить фронт сигнала - применяйте схемы детектора фронтов(гуглится легко). Так как сделано у Вас - в FPGA не делается.

3.

    always @(negedge SCK, posedge CS) 
        if (CS)
            bit_counter <= 4'b0000;
        else
        begin
            data_receive_reg[15-bit_counter] <= MOSI;
            bit_counter <= bit_counter + 4'b0001;    
        end

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

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


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

Моделировал в стандартном квартусовском симуляторе - ошибок нет, но при работе с железом ошибка присутствует: для этого специально поставил 2 компаратора на вход data_in и 2 компаратора на выход data_out, а сигналы с компараторов вывел на светодиоды платы. На входе данные всегда правильные, а выход после N передач выдает либо фиксированные данные, либо 0.
Значит, модель Ваша не совпадает с действительностью.

И уж если взялись, то возьмите осциллограф. Раз интерфейс отлаживаете - смотрите его на экране осциллоскопа, а не на мигании светодиодов.

SignalTap-ом пользоваться не умею.
А вот это освойте: и сейчас пригодится, и в будущем. Начинать, например, можно отсюда.

 

И скрипт Вы, конечно, "синхронизировали" сильно. Сделайте так, как сказал Flip-fl0p.

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


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

Жуть !

1. Фильтруйте входные внешние асинхронные сигналы от пологих фронтов, и возможного дребезга около фронтов.

2. Работайте только про одному фронту синхросигнала. Хотите выделить фронт сигнала - применяйте схемы детектора фронтов(гуглится легко). Так как сделано у Вас - в FPGA не делается.

3. Но правильнее и красивее в сдвиговый регистр данные записывать. Записали и сдвинули. Приняли все биты - отдали данные в модуль, обрабатывающий слова.

 

Ошибку исправил, засинхронизировал сигнал CS, переписал модуль SPI как советовал Flip-fl0p. В железе все работает, но при компиляции куча варнингов, типа:

Warning: Presettable and clearable registers converted to equivalent circuits with latches. Registers power-up to an undefined state, and DEVCLRn places the registers in an undefined state.
    Warning (13310): Register "SPIslave:inst16|data_in_reg[15]" is converted into an equivalent circuit using register "SPIslave:inst16|data_in_reg[15]~_emulated" and latch "SPIslave:inst16|data_in_reg[15]~latch"
    Warning (13310): Register "SPIslave:inst16|data_in_reg[14]" is converted into an equivalent circuit using register "SPIslave:inst16|data_in_reg[14]~_emulated" and latch "SPIslave:inst16|data_in_reg[14]~latch"
    Warning (13310): Register "SPIslave:inst16|data_in_reg[13]" is converted into an equivalent circuit using register "SPIslave:inst16|data_in_reg[13]~_emulated" and latch "SPIslave:inst16|data_in_reg[13]~latch"
    Warning (13310): Register "SPIslave:inst16|data_in_reg[12]" is converted into an equivalent circuit using register "SPIslave:inst16|data_in_reg[12]~_emulated" and latch "SPIslave:inst16|data_in_reg[12]~latch"
    Warning (13310): Register "SPIslave:inst16|data_in_reg[11]" is converted into an equivalent circuit using register "SPIslave:inst16|data_in_reg[11]~_emulated" and latch "SPIslave:inst16|data_in_reg[11]~latch"
    Warning (13310): Register "SPIslave:inst16|data_in_reg[10]" is converted into an equivalent circuit using register "SPIslave:inst16|data_in_reg[10]~_emulated" and latch "SPIslave:inst16|data_in_reg[10]~latch"
    Warning (13310): Register "SPIslave:inst16|data_in_reg[9]" is converted into an equivalent circuit using register "SPIslave:inst16|data_in_reg[9]~_emulated" and latch "SPIslave:inst16|data_in_reg[9]~latch"
    Warning (13310): Register "SPIslave:inst16|data_in_reg[8]" is converted into an equivalent circuit using register "SPIslave:inst16|data_in_reg[8]~_emulated" and latch "SPIslave:inst16|data_in_reg[8]~latch"
    Warning (13310): Register "SPIslave:inst16|data_in_reg[7]" is converted into an equivalent circuit using register "SPIslave:inst16|data_in_reg[7]~_emulated" and latch "SPIslave:inst16|data_in_reg[7]~latch"
    Warning (13310): Register "SPIslave:inst16|data_in_reg[6]" is converted into an equivalent circuit using register "SPIslave:inst16|data_in_reg[6]~_emulated" and latch "SPIslave:inst16|data_in_reg[6]~latch"
    Warning (13310): Register "SPIslave:inst16|data_in_reg[5]" is converted into an equivalent circuit using register "SPIslave:inst16|data_in_reg[5]~_emulated" and latch "SPIslave:inst16|data_in_reg[5]~latch"
    Warning (13310): Register "SPIslave:inst16|data_in_reg[4]" is converted into an equivalent circuit using register "SPIslave:inst16|data_in_reg[4]~_emulated" and latch "SPIslave:inst16|data_in_reg[4]~latch"
    Warning (13310): Register "SPIslave:inst16|data_in_reg[3]" is converted into an equivalent circuit using register "SPIslave:inst16|data_in_reg[3]~_emulated" and latch "SPIslave:inst16|data_in_reg[3]~latch"
    Warning (13310): Register "SPIslave:inst16|data_in_reg[2]" is converted into an equivalent circuit using register "SPIslave:inst16|data_in_reg[2]~_emulated" and latch "SPIslave:inst16|data_in_reg[2]~latch"
    Warning (13310): Register "SPIslave:inst16|data_in_reg[1]" is converted into an equivalent circuit using register "SPIslave:inst16|data_in_reg[1]~_emulated" and latch "SPIslave:inst16|data_in_reg[1]~latch"
    Warning (13310): Register "SPIslave:inst16|data_in_reg[0]" is converted into an equivalent circuit using register "SPIslave:inst16|data_in_reg[0]~_emulated" and latch "SPIslave:inst16|data_in_reg[0]~latch"
Warning: Timing Analysis is analyzing one or more combinational loops as latches
    Warning: Node "inst16|data_in_reg[15]~latch|combout" is a latch
    Warning: Node "inst16|data_in_reg[14]~latch|combout" is a latch
    Warning: Node "inst16|data_in_reg[13]~latch|combout" is a latch
    Warning: Node "inst16|data_in_reg[12]~latch|combout" is a latch
    Warning: Node "inst16|data_in_reg[11]~latch|combout" is a latch
    Warning: Node "inst16|data_in_reg[10]~latch|combout" is a latch
    Warning: Node "inst16|data_in_reg[9]~latch|combout" is a latch
    Warning: Node "inst16|data_in_reg[8]~latch|combout" is a latch
    Warning: Node "inst16|data_in_reg[7]~latch|combout" is a latch
    Warning: Node "inst16|data_in_reg[6]~latch|combout" is a latch
    Warning: Node "inst16|data_in_reg[5]~latch|combout" is a latch
    Warning: Node "inst16|data_in_reg[4]~latch|combout" is a latch
    Warning: Node "inst16|data_in_reg[3]~latch|combout" is a latch
    Warning: Node "inst16|data_in_reg[2]~latch|combout" is a latch
    Warning: Node "inst16|data_in_reg[1]~latch|combout" is a latch
    Warning: Node "inst16|data_in_reg[0]~latch|combout" is a latch

 

Новый код ниже, не судите строго - только учусь)

module SPIslave(
    input clk,
    input CS,
    input MOSI,
    input SCK,
    input [15:0] data_in,
    output reg MISO,
    output reg [15:0] data_out,
    output reg data_ready
    );

reg [15:0] data_receive;
reg [15:0] data_in_reg;
reg [4:0]  bit_counter;
reg fall_CS_reg;
wire fall_CS;

    //----------------------------------------
    // По спаду SCK принимаем данные
    //----------------------------------------
    always @ (negedge SCK, posedge CS)
        if (CS)
            bit_counter <= 5'b00000;
        else
        begin
            data_receive <= { data_receive[14:0], MOSI };
            bit_counter <= bit_counter + 5'b00001;
        end
    //----------------------------------------
    // Выделяем спад CS
    //----------------------------------------
    always @(posedge clk)
        fall_CS_reg <= CS;
    assign fall_CS = fall_CS_reg & ~CS;


    //----------------------------------------
    // По фронту CS заносим данные в data_in_reg
    // По фронту SCK сдвигаем данные
    //----------------------------------------
    always @ (posedge SCK, posedge fall_CS)
    begin
        if (fall_CS)
            data_in_reg <= data_in;
        else
        begin
            MISO <= data_in_reg[15];
            data_in_reg <= (data_in_reg << 1);
        end
    end    

    //----------------------------------------
    // По переполнению счетчика выводим данные и сигнал готовности
    //----------------------------------------
    always @ (posedge clk)
    begin
        if (bit_counter[4])
            begin    
                data_out <= data_receive;
                data_ready <= 1'b1;
            end
        else
            begin
                data_out <= data_out;
                data_ready <= 1'b0;
            end
    end
endmodule

 

Кстати, RTL-схема получилась довольно интересная:

 

SPIslave.png

 

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


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

У вас тут большие проблемы с CDC (clock domain crossing). Точнее, его просто нет.

Вы формируете fall_CS_reg по clk, а используете для SCK. Так делать нельзя.

 

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

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


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

переписал модуль SPI как советовал Flip-fl0p.
Flip-fl0p советовал работать только от одного клока: у Вас это, как понимаю, clk.

И в списке чувствительности, помимо него, имеет право быть (для проекта комильфо) только, если, конечно, он Вам нужен, ещё асинхронный глобальный сброс.

А у Вас в этих списках зоопарк.

Кстати, боюсь предложить Вам ещё включить (если я правильно помню называние) Design Assistant )))

И пока перестаньте нас радовать Вашим RTL: давайте сначала код вылизывать.

Лучше выкладывайте экран функционального моделирования для этого модуля.

 

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


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

Ошибку исправил, засинхронизировал сигнал CS, переписал модуль SPI как советовал Flip-fl0p. В железе все работает, но при компиляции куча варнингов, типа:

 

Кстати, RTL-схема получилась довольно интересная:

Давайте с конца начнем...

Какой может быть интерес к "RTL-схема", если она потом оптимизируется и от нее мало что останется?

Ваш стиль кодирования "все в одном" приведет к мало-отлаженному проекту. Который будет трудно сопровождать...

На самом деле, все это гораздо проще ложится в набор автоматов:

нижний, который умеет только работать с битом,

средний, который умеет только передать-принять кадр, управляя при этом нижним,

верхний, который работает с сигналами типа CS и запускает средний на выполнение.

 

При этом, нижний может еще и фильтровать клоки и данные, если они приходят из SPI, а верхний может синхронизировать и фильтровать сигналы типа CS...

И когда к этому придете, то станет понятно, что "есть только один клок в проекте и сигнал разрешения - пророк его"... А попутно сделаете привязку асинхронных сигналов..

Потом сделайте еще параметры, в которых бы задавалось число клоков на один бит SPI отдельно для симуляции и отдельно для железа...Скажем, если для железа надо 100 клоков на бит, то дляя симуляции и 4-х хватит... Тогда симуляция будет делаться быстро..

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


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

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

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

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

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

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

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

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

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

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