Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: FAQ по языкам описания аппаратуры
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Языки проектирования на ПЛИС (FPGA)
Страницы: 1, 2, 3
Flip-fl0p
А можно ли как-то значение типа STD_LOGIC_VECTOR вывести на консоль Modelsim'a простыми способом ? Может есть какая хитрая библиотека для этого ? На данный момент не вижу альтернатив, кроме как написать собственную функцию для преобразования STD_LOGIC_VECTOR ----> STRING, что делать не очень хочется...
UPD 12:00
Отвечу сам на свой вопрос.
Для того, чтобы напечатать значение STD_LOGIC_VECTOR в консоль можно написать следующее:
Код
    PRINTING_SLV_TO_CONSOLE : PROCESS
    (
        CLOCKx7
    )
    BEGIN
        IF RISING_EDGE(CLOCKX7) THEN                     -- Печатаем значение вектора по каждому фронту частоты CLOCKx7
            FOR i IN (DATA_REG'LENGTH-1) DOWNTO 0 LOOP   -- Для всех разрядов вектора DATA_REG
                REPORT STD_LOGIC'IMAGE(DATA_REG(i));     -- Выводим значение каждого разряда начиная со старшего.
            END LOOP;
            REPORT ""&LF;                                -- После того, как все символы вектора напечатали перейдем на новую строку
        END IF;
    END PROCESS;


В итоге на экране консоли будет следующее:
Код
# '0''0''0''0''1''1''0'
# '0''0''0''1''1''0''0'
# '0''0''1''1''0''0''0'
# '0''1''1''0''0''0''0'
# '1''1''0''0''0''0''0'
# '1''0''0''0''0''0''1'
# '0''0''0''0''0''1''1'


На вид не очень красиво, думаю потом подправлю на "красивый" вариант.
Flip-fl0p
Подскажите, как можно красиво сформировать единичный сигнал, каждый раз как происходит изменение состояний автомата ?
iosifk
Цитата(Flip-fl0p @ Apr 5 2017, 16:36) *
Подскажите, как можно красиво сформировать единичный сигнал, каждый раз как происходит изменение состояний автомата ?

так автоматом же и формировать...
andrew_b
Цитата(Flip-fl0p @ Apr 5 2017, 15:36) *
Подскажите, как можно красиво сформировать единичный сигнал, каждый раз как происходит изменение состояний автомата ?


Код
process (clk)
begin
    if rising_edge (clk)) then
        prev_state <= state;

        if (state = prev_state) then
                change <= '0';
        else
                change <= '1';
        end if;
    end if;
end process;
Flip-fl0p
Цитата(andrew_b @ Apr 5 2017, 16:12) *

Я похожее написал.
Код
    PROCESS
    (
        CLK
    )
    BEGIN
        IF (RISING_EDGE(CLK)) THEN
            ERROR_CNT_RST      <= '0';
            IF (PRESS_STATE /= NEXT_STATE) THEN
                ERROR_CNT_RST <= '1';
            END IF;
        END IF;
    END PROCESS;

Вот только получается беда.
Поскольку NEXT_STATE - это комбинационная функция, то такой подход генерирует огромнейшее количество слоёв логики.

Вроде бы идея сравнивать текущее состояние и прошедшее более красиво выглядит.
Код
    PRESS_STATE_TO_NEXT_STATE_PROC : PROCESS
    (
        CLK
    )
    BEGIN
        IF (RISING_EDGE(CLK)) THEN
            PRESS_STATE <= NEXT_STATE;        -- По каждому фронтму меняем состояние на то, которое вычислил автомат
            LAST_STATE  <= PRESS_STATE;       -- Запомним текущее состояние автомата              
            IF (SRST = '1') THEN              --  При активном синхронном сбросе
                PRESS_STATE <= IDLE;           -- Переходим в состояние ожидания
            END IF;
        END IF;
    END PROCESS;


Код
PROCESS
    (
        CLK
    )
    BEGIN
        IF (RISING_EDGE(CLK)) THEN
            ERROR_CNT_RST      <= '0';
            IF (PRESS_STATE /= LAST_STATE) THEN
                ERROR_CNT_RST <= '1';
            END IF;
        END IF;
    END PROCESS;
iosifk
Цитата(Flip-fl0p @ Apr 5 2017, 17:23) *
Поскольку NEXT_STATE - это комбинационная функция, то такой подход генерирует огромнейшее количество слоёв логики.

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

Flip-fl0p
Цитата(iosifk @ Apr 5 2017, 16:48) *
Да нет, получится схема сравнения между регистром текущего состояния и выходами комбинационной логики. И кк этому на выходе - триггер... И более ничего не добавится...
Только для чего это нужно?

Нужно для того, чтобы автомат не зависал в каком-то состоянии, в случае если нет входного воздействия.
Каждый раз, как автомат сменит состояние, сброситься счётчик, отсчитывающей время. Если счётчик досчитает до конца, значит автомат завис - и он сбросится в изначальное состояние, т.е. состояние ожидания.
x736C
Можно сделать так. Добавить один бит к слову, описывающему состояние автомата. Вместе со сменой состояния бит оказывается в положении единицы, а на следующем такте сбрасывается. В Верилоге есть CASEX, которая позволяет этот бит игнорировать. Но и с обычным CASE все просто можно сделать.
Golikov A.
В вашем описании автомата наверняка есть место

state <= next_sate, синхронное под клоком.
добавьте в это место

Код
if(state != next_state)
    Counter <= MAX_DELAY;
else
    Counter <= Counter - 1'b1;


ну и до кучи
Код
if(Counter == 0)
    state <= IDLE;



а про слои логики не стоит думать, это же наверняка FPGA, там это в ЛУТы ляжет будет ок.
Flip-fl0p
Цитата(Golikov A. @ Apr 5 2017, 21:02) *
В вашем описании автомата наверняка есть место

state <= next_sate, синхронное под клоком.
добавьте в это место

Код
if(state != next_state)
    Counter <= MAX_DELAY;
else
    Counter <= Counter - 1'b1;


ну и до кучи
Код
if(Counter == 0)
    state <= IDLE;



а про слои логики не стоит думать, это же наверняка FPGA, там это в ЛУТы ляжет будет ок.

Да я так и делал. При таком подходе If(state != next_state) получается огромное количество логики(я сейчас говорю про technology map viewer, т.е то, что непосредственно в кристалл ложиться). Возможно всё дело в том, что автомат у меня кодируется по типу ONE-HOT, завтра на работе в свободное от работы время попробую поиграться с атрибутами синтеза. Может в них дело.
На данный момент, наилучший результат дал ввод третьего состояния автомата - LAST_STATE. И сравнение текущего состояния с прошедшим. По типу того как ищется фронт сигнала
iosifk
Цитата(Flip-fl0p @ Apr 5 2017, 19:20) *
Нужно для того, чтобы автомат не зависал в каком-то состоянии, в случае если нет входного воздействия.
Каждый раз, как автомат сменит состояние, сброситься счётчик, отсчитывающей время. Если счётчик досчитает до конца, значит автомат завис - и он сбросится в изначальное состояние, т.е. состояние ожидания.


Неверно в принципе!
Проверять нужно не все подряд состояния, а только те, в которых идет ожидание какого-то сигнала. Добавьте туда проверку вотчдога и выход по нему. Но не в исходное, а в состояние в котором фиксируется ошибка.
И еще должны быть состояния, инициализирующие вотчдог.
Беда ТС в том, что он пытается сделать что-то нестандартное, хотя для этого вполне подходят стандартные средства. Надо просто ими уметь пользоваться.
Flip-fl0p
Цитата(iosifk @ Apr 5 2017, 22:25) *
Неверно в принципе!
Проверять нужно не все подряд состояния, а только те, в которых идет ожидание какого-то сигнала. Добавьте туда проверку вотчдога и выход по нему. Но не в исходное, а в состояние в котором фиксируется ошибка.
И еще должны быть состояния, инициализирующие вотчдог.
Беда ТС в том, что он пытается сделать что-то нестандартное, хотя для этого вполне подходят стандартные средства. Надо просто ими уметь пользоваться.

Возможно я и неправильный подход выбираю, спорить не буду, мне ещё учиться и учиться....
Но если не пытаться что-то делать, как тогда узнать какой подход правильный, а какой нет ?
Вот и приходиться изворачиваться, придумывать велосипеды с треугольными колёсами, особенно когда не знаешь, а как вообще правильно делать.
Профессионалами не рождаются - ими становятся(С)
Ну , а если по теме.
Сейчас делаю модель EEPROM памяти на I2C шине.
Частота работы I2C нигде не задаётся, и по сути может быть практически любая. Поэтому я работаю с фронтами, в частности выделю фронты по линиям SCL, SDC.
Безусловно, предварительно я перенес сигналы с этих линий в клоковый домен, и сделал минимальную фильтрацию, убирающую небольшие иголки, или провалы сигнала.
Но, к примеру, я получил старт посылку, и начал принимать биты адреса, т.е. мой автомат перешёл в состояние приёма адреса. Выход из состояния приёма адреса будет только тогда, когда я приму все 7 бит адреса. Приход бита я определяю по наличию фронта на линии SCL.
А если мастер передал только 5 бит, и по какой-то причине отключился\помер\перезагрузился ? Соответствнно мой автомат этого не знает, и продолжает ждать приёма всех 7 бит.....
В итоге он залипнет в этом состоянии. Вот я и думаю, как обойти это.
На самом деле, сейчас мысль появилась о том, что такой счётчик действительно не самая разумная затея. Используя свойства протокола I2C можно автоматически выводить SLAVE автомат из "залипших" состояний.
iosifk
Цитата(Flip-fl0p @ Apr 6 2017, 09:36) *
А если мастер передал только 5 бит, и по какой-то причине отключился\помер\перезагрузился ? Соответствнно мой автомат этого не знает, и продолжает ждать приёма всех 7 бит.....

Перед началом приема автомат попадет в состояние, в котором взведет таймер и после этого попадет в состояние приема битов. Там автомат будет проверять готовность по приему всех битов и сигнал от таймера. Если биты готовы, то автомат перейдет в состояние, где остановит таймер. Или, если биты не готовы, но готов таймер, то автомат перейдет в состояние отработки ошибки...
Это же все просто. Нарисуйте блок-схему, из нее состояния автомата и всё....
Тем более для I2C можно сделать автомат для битов, автомат для слов-посылок и автомат для верхнего процесса. И тут будет все совсем просто....
Flip-fl0p
Цитата(iosifk @ Apr 6 2017, 08:47) *
Перед началом приема автомат попадет в состояние, в котором взведет таймер и после этого попадет в состояние приема битов. Там автомат будет проверять готовность по приему всех битов и сигнал от таймера. Если биты готовы, то автомат перейдет в состояние, где остановит таймер. Или, если биты не готовы, но готов таймер, то автомат перейдет в состояние отработки ошибки...
Это же все просто. Нарисуйте блок-схему, из нее состояния автомата и всё....
Тем более для I2C можно сделать автомат для битов, автомат для слов-посылок и автомат для верхнего процесса. И тут будет все совсем просто....

Именно.
Но с таким подходом, когда анализируются фронты по линии SCL, возможна ситуация, практически в любом состоянии работы автомата SLAVE, когда по линии SCL фронт не приходит, и как следствие автомат "залипает", поскольку именно изменение линии SCL является условием переключения состояний автомата.
Вот моя первая мысль и была сделать такой таймер, который Вы описали. Только чтобы таймер на любом состоянии работал, поскольку практически любое состояние потенциально опасное. Кроме состояния ожидания. Вот и самый логичный вывод, к которому я пришел - счетчик, который сбрасывается при любом изменении состояния автомата. Если счётчик досчитал до конца - значит надо сбросить автомат в исходное состояние.
Граф переходов я безусловно нарисовал, это первое с чего я начинаю проектирование автомата.
Возможно сам подход - анализировать фронты линии SCL неправильный. Но других разумных вариантов я на данный момент не вижу.
Golikov A.
1. Вообще то на I2C есть start condition, он обозначает начало посылки, ровно как есть и stop condition. Именно ими и стоит оперировать, а не счетчиками. Иначе если мастер послал и умер, перегрузился и опять послал до выхода вашего таймаута, вы его начало посылки в адрес пихнете или в данные, а дальше понесется беда....

2. Есть 2 варианта счетчиков сторожевой таймер и таймаут. Сторожевой таймер должен идти всегда, и в определенных состояниях сбрасываться. В целом переход из состояния в состояние тоже годится как точка сброса сторожевого таймера. Таймаут заводится на конкретное действие и не сбрасывается, а просто выключается когда действие произошло. Это разные таймеры и у них разное назначение. И как правильно замечено переход по тайким таймерам лучше делать не в IDLE, а в RECOVERE где ошибку залогируют и проведут верную процедуру восстановления автомата. Если надо про назначения таймеров могу написать подробнее

3. Если автомат one-hot то можно сделать |(state ^ next_state) и проверить эту штуку на равенство 0, думаю беда в том что состояния действительно длинные, потому и много надо чтобы вычислить функцию. Все что вы добиваетесь использованием last_state это вы разбиваете логику формирования нового состояния и проверки равенства со старым на 2 части. В целом да, это будет работать быстрее, но с задержкой в 1 такт, хотя может это и не страшно.
Flip-fl0p
Цитата(Golikov A. @ Apr 6 2017, 09:23) *
1. Вообще то на I2C есть start condition, он обозначает начало посылки, ровно как есть и stop condition. Именно ими и стоит оперировать, а не счетчиками. Иначе если мастер послал и умер, перегрузился и опять послал до выхода вашего таймаута, вы его начало посылки в адрес пихнете или в данные, а дальше понесется беда....

2. Есть 2 варианта счетчиков сторожевой таймер и таймаут. Сторожевой таймер должен идти всегда, и в определенных состояниях сбрасываться. В целом переход из состояния в состояние тоже годится как точка сброса сторожевого таймера. Таймаут заводится на конкретное действие и не сбрасывается, а просто выключается когда действие произошло. Это разные таймеры и у них разное назначение. И как правильно замечено переход по тайким таймерам лучше делать не в IDLE, а в RECOVERE где ошибку залогируют и проведут верную процедуру восстановления автомата. Если надо про назначения таймеров могу написать подробнее

3. Если автомат one-hot то можно сделать |(state ^ next_state) и проверить эту штуку на равенство 0, думаю беда в том что состояния действительно длинные, потому и много надо чтобы вычислить функцию. Все что вы добиваетесь использованием last_state это вы разбиваете логику формирования нового состояния и проверки равенства со старым на 2 части. В целом да, это будет работать быстрее, но с задержкой в 1 такт, хотя может это и не страшно.

1. Ну да, я поэтому и писал, что есть лучше вариант, чем делать счетчик. Что особенности протокола I2C позволяют вывеси автомата из залипания.
Например:
Принимаем биты адреса.
Автомат залип в состоянии приёма адреса, т.к. мастер перезагрузился.
Но так или иначе мастер при следующем обращении начнет посылку со старт бита. Так почему бы условие старт не применить для сброса автомата ?
2. Вот тут да, не очень улавливаю разницу между таймерами. Для меня что один, что другой - обычный счетчик.
3. Для полноценной реализации всех функций EEPROM (повторный старт, приём адрес ячейки к которой идет обращение, страничный доступ и пр.) потребовалось 12 состояний автомата. Может действительно попробовать разбить автомат на несколько маленьких... А задержка в 1 такт не критична. Частота кварца 25 МГц. Максимальная частота работы I2C 400 КГц.
Golikov A.
1. Не "почему бы", а именно так и надо делать. Вернее даже правильнее из любого состояние по старту переходить в состояние начала приема посылки, а по стопу в идле. При штатной работе это не меняет логику, при нештатной сохраняет работоспособность и правильную реакцию. Если стоп появился раньше времени, то нельзя работать с полученными данными. Ровно как появление старта в середине приема говорит о поврежденных данных и необходимости все начинать сначала.

2. По реализации да, оба счетчики. Отличаются по назначению.
Сторожевой таймер - это таймер для ситуаций о которых вы не знаете. Он отлавливает непредвиденное поведение, ошибки работы и проектирования, ошибки описания, человеческий фактор. То есть он запускается как бы на всякий случай. Поэтому он не может включатся и включатся по вашему желанию, ибо нет гарантии что вы по той же ошибке его не выключите. Этот таймер идет всегда, а вы в ситуация когда точно уверены что все хорошо его сбрасываете. Логика у него должна быть железобетонной и крайне примитивной. Это как гудок у машиниста в кабине поезда, уснул не сбросил он орет и будит. Его нельзя отключить, надо постоянно сбрасывать, иначе бы машинист его выключил, затем уснул и вся система зря.

Таймер таймаута - это таймер когда вы знаете что делаете, таймер ожидаемой ситуации. То есть вы говорите я хочу принять данные, но если мне их в течение секунды не пришлют я все бросаю и иду в ИДЛЕ. В этом случае перед приемом вы заряжаете таймер, и ждете, получили данные - хорошо, выключили таймер пошли дальше, нет - тоже хорошо у вас сработал таймаут и вы по нему перешли дальше куда надо. Это аналог кухонного таймера. Поставили мясо тушиться, зарядили таймер на время когда оно точно будет готово. При этом продолжаете сами за ним время от времени следить. Увидели что оно готово, - ОК выключили таймер сняли мясо, не видели, но сработал таймер, ну тоже ОК, тогда оно точно готово, пора снимать.

3. Не надо работать за синтезатор, опишите автомат просто состояниями по числам 0, 1, 2, 3, 4, 5... 11. в 4 битном векторе состояний и отдайте это все на работу синтезатора. Он найдет автомат, он сам перекодирует состояния, в оне хот если надо быстро, в грея если переходы последовательны, он сам выберет баланс между скоростью и ресурсами. Чем более абстрактно вы описываете задачу, тем больше у синтезатора возможностей для оптимизации. Направляйте синтезатор, а не зажимайте его руками. Алгоритмы все хитрее и человек уже часто проигрывает машине, так чего с ней соревноваться, пусть работает на нас!
Flip-fl0p
Цитата(Golikov A. @ Apr 6 2017, 11:22) *

Спасибо за объяснения. А автомат я не зажимаю. Наоборот за счет применения перечисляемых типов, компилятору больше свободы для "творчества".
Код
    TYPE STATE_MACHINE_TYPE IS
    (
        IDLE,                                                   -- Состояние ожидания              
        START,                                                  -- Состояние старт бита.
        ADDRES_SLAVE,                                           -- Состояние приёма адреса SLAVE устройства
        DIRECTION,                                              -- Приём бита направления
        ACK_SLAVE_ADDR,                                         -- Состояние подтверждения приёма адреса SLAVE устройства
        RAM_ADDRES,                                             -- Состояние приёма адреса ячейки RAM  
        ACK_RAM_ADDRES,                                         -- Подтверждение приёма адреса ячекий памяти
        WRITE_DATA,                                             -- Состояние записи данных в SLAVE устройство
        READ_DATA,                                              -- Состояние чтения данных из SLAVE устройства
        ACK_READ,                                               -- Состояние выдачи бита поддтверждения при чтении
        ACK_WRITE,                                              -- Состояние выдачи бита поддтверждения при записи.
        STOP                                                    -- Состояние приёма стоп бита
    );                                                          
    SIGNAL PRESS_STATE, NEXT_STATE : STATE_MACHINE_TYPE;        -- Регистры хранения состояний автомата
Flip-fl0p
Приветствую. Возник небольшой вопрос про тип BOOLEAN в VHDL. Для обучения я очень много скачивал разных примеров схем на VHDL. Но практически ни в одном из примеров я не встречал применение типа BOOLEAN.
Можете помочь разобраться, а какое данному типу есть практическое применение.
Немного прочитав про этот тип, я узнал, что это перечисляемый тип
Код
type boolean is (false,true);

Правильно ли я понимаю, что при применении данного типа синтезатор может самостоятельно назначить какому логическому сигналу соответствует false,true. Т.е. если синтезатору будет удобнее чтобы False соответствовала лог.1 а true лог.0. он так и сделает. Таким образом синтезатор сам подставит то значение типу, которое позволит ему получить более минимизированную логическую функцию, т.е. при синтезе применение типа BOOLEAN в качестве каких либо "флагов" более предпочтительно чем применение логических сигналов "1" и "0";
warrior-2001
Я даже больше скажу. Некоторые синтезаторы вообще меняют "1" и "0" местами в проекте, если им так удобнее. Тоесть они перелопачивают всю логику, и потом разработчик долго смотрит в логический анализатор и понять не может, отчего его сигнал в неактивном состоянии, а все работает. Это касается лишь тех случаев, когда вся логика является внутренней. Таким образом со внешними выводами синтезаторы себе такого не позволяют.
Flip-fl0p
Цитата(warrior-2001 @ May 2 2017, 15:44) *
Я даже больше скажу. Некоторые синтезаторы вообще меняют "1" и "0" местами в проекте, если им так удобнее. Тоесть они перелопачивают всю логику, и потом разработчик долго смотрит в логический анализатор и понять не может, отчего его сигнал в неактивном состоянии, а все работает. Это касается лишь тех случаев, когда вся логика является внутренней. Таким образом со внешними выводами синтезаторы себе такого не позволяют.

Т.е. я правильно понял, что имеет смысл флаги объявлять как BOOLEAN, а то, каким уровнем будет представлен флаг отдать на откуп синтезатору ?
warrior-2001
Цитата(Flip-fl0p @ May 2 2017, 14:55) *
Т.е. я правильно понял, что имеет смысл флаги объявлять как BOOLEAN, а то, каким уровнем будет представлен флаг отдать на откуп синтезатору ?


Я и не припомню, чтобы пользовался BOOLEAN где-то, кроме generate. И там я true ставил в "1" скорее для читаемости кода!
Что сделает синтезатор - мне не важно. И только когда я этот флаг вытащу в логический анализатор мне понадобится информация об уровне сигнала.
krotan
Цитата(Partisan @ Sep 28 2006, 08:13) *
Дж. Уэйкерли Проектирование цифровых устройств в 2-х т. Постмаркет Москва 2002 г., всего 1088 стр.
Про ABEL и VHDL. djvu 12 метров
было найдено у вьетнамцев (если я ничего не перепутал) на www.vsofts.net , правда под названием Digital Design (3rd Edition) M. Morris Mano Morris M Mano, загружал модератор по нику Vodka1504, мож чего перепутал

http://electronix.ru/redirect.php?http://s...kerly.part1.rar
http://electronix.ru/redirect.php?http://s...kerly.part2.rar
http://electronix.ru/redirect.php?http://s...kerly.part3.rar
http://electronix.ru/redirect.php?http://s...kerly.part4.rar
Pass: www.vsofts.net
В указанном месте нет... Ни у кого не сохранилось?
x736C
Первая и третья есть на gen.lib.rus.ec
krotan
Всё, нашёл в другом месте. Если кому-то ещё надо, перевыложу здесь, объём 76 Мб.
Flip-fl0p
Вопрос тем кто пишет на VHDL.
Для настроек модуля мне понадобилась функция округления значения до большего числа с отбрасыванием дробной части.
В пакете ieee.math_real.all есть такая функция - ceil
Насколько мне известно данная библиотека не является стандартной. Посему возникает вопрос, имеются ли подводные камни при использовании совместно библиотек:
Код
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    use ieee.math_real.all;
Tausinov
Цитата(Flip-fl0p @ Jan 10 2018, 13:29) *
Вопрос тем кто пишет на VHDL.
Для настроек модуля мне понадобилась функция округления значения до большего числа с отбрасыванием дробной части.
В пакете ieee.math_real.all есть такая функция - ceil
Насколько мне известно данная библиотека не является стандартной. Посему возникает вопрос, имеются ли подводные камни при использовании совместно библиотек:
Код
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    use ieee.math_real.all;


Если я не ошибаюсь, то можно отдельно только функцию "заинклудить", чтобы не беспокоиться о совместимости. И, вроде, даже есть еще более хитрый способ с вызовом функции через название пакета ieee.math_real.ceil, но это неточно.

Код
use ieee.math_real.ceil;


andrew_b
Цитата(Tausinov @ Jan 10 2018, 13:40) *
Правильно всё.
Flip-fl0p
Господа, прошу помощи с описанием двумерных массивов на VHDL.
Объявил вот такой вот массив :
Код
type SDRAM is array (0 to 3, 0 to 3) of std_logic_vector (15 downto 0);
variable memory : SDRAM;

Хочу я записать по адресу SDRAM(0,0) что-нибудь.
Я пишу так :
Код
memory(0, 0) := DQ;

Но столкнулся с проблемой, что меняя индексы строки т.е проводя записи в memory(0, 0) , memory(0, 1) memory(0, 2) итд. у меня данные пишутся только по адресу memory(0, 0).
Соответственно с чтением массива проблема аналогичная.
upd.
При чём если записать так:
Код
              
for i in 0 to 3 loop
    memory(0, i) <= DQ;
end loop;

Данные пишутся во все ячейки.... Не понимаю...
Как это побороть ? И в чём моя ошибка ?
Ну и второй вопрос.
А каким образом можно аналогичный массив создать (чтобы можно было обращаться к данным по адресу строки и столбца) в неситезируемом подмножестве VHDL, для минимизации вычислительных ресурсов.
Массив нужен для простенькой модели SDRAM памяти
Александр77
Цитата(Flip-fl0p @ Jan 22 2018, 16:32) *
Я пишу так :
Код
memory(0, 0) := DQ;

А может должно быть так
memory(0)(0):=DQ;
Flip-fl0p
Цитата(Александр77 @ Jan 22 2018, 17:36) *
А может должно быть так
memory(0)(0):=DQ;

Так тоже не работает crying.gif
Stewart Little
Цитата(Flip-fl0p @ Jan 22 2018, 16:32) *
type SDRAM is array (0 to 3, 0 to 3) of std_logic_vector (15 downto 0);

Это что такое?
Flip-fl0p
Цитата(Stewart Little @ Jan 22 2018, 18:33) *
Это что такое?

Двумерная матрица размерностью 4 х 4 с глубиной ячейки 16 бит.
Stewart Little
Цитата(Flip-fl0p @ Jan 22 2018, 16:32) *
Господа, прошу помощи с описанием двумерных массивов на VHDL.

А у Вас сколькимерный массив получается?
Flip-fl0p
Цитата(Stewart Little @ Jan 22 2018, 18:39) *
А у Вас сколькимерный массив получается?

Я его понимаю как двумерный массив. С глубиной ячейки 16 бит.
Но фактически это трехмерный массив.
andrew_b
Цитата(Flip-fl0p @ Jan 22 2018, 16:32) *
Но столкнулся с проблемой, что меняя индексы строки т.е проводя записи в memory(0, 0) , memory(0, 1) memory(0, 2) итд. у меня данные пишутся только по адресу memory(0, 0).
Код покажите.

Цитата
Ну и второй вопрос.
А каким образом можно аналогичный массив создать (чтобы можно было обращаться к данным по адресу строки и столбца) в неситезируемом подмножестве VHDL, для минимизации вычислительных ресурсов.
От массива никуда не уйти всё равно. Для минимизации ресурсов используйте переменную, а не сигнал.
Flip-fl0p
Вроде разобрался в проблеме !
Проблемой оказалась то, что у меня адрес из типа std_logic_vector конвертировался в тип integer.
Но в векторе адреса у меня присутствовали безразличные значения. И при конвертации в integer из -за этих безразличных значений integer всегда оставался нулем.
Например:
Есть шина адреса
Код
addr : in std_logic_vector(3 downto 0)

В моей модели памяти данная шина мультиплексированная (модель SDRAМ потому-что)
Поэтому адрес фактически у меня передавался за 2 этапа.
В первом этапе у меня декодировался адрес строки.
Потом декодировался адрес столбца.
Код
row_addr <= to_integer(unsigned(A)); -- к примеру адрес строки  b"1111" т.е 15
col_addr <= to_integer(unsigned(A)); -- А в случае столбца адрес выглядел так:  b"--11" т.е 3. Т.е первые 2 бита безразличны.

Из-за безразличных значений адрес столбца всё время декодировался как 0...
Буду теперь внимательнее быть smile3046.gif
Flip-fl0p
Господа, а можете объяснить в чем особый смысл применения типа record в VHDL ?
Ну да, удобно когда вместо кучи выходных\входных портов - применяется готовый тип.
Но за это мы платим ухудшением читаемости кода. Во всяком случае мне такой код понимать сложнее.
Более того разрядность векторов такого типа не всегда можно настраивать параметрами.
Нпример если я в пакете обьявлю такой тип, то в пакет я не могу передать параметры с модуля верхнего уровня (во всяком случае Quartus 13.1 не поддерживает эту фичу VHDL 2008)
Читал статью http://www.gaisler.com/doc/vhdl2proc.pdf и др. Но как-то не впечатлило... Если не сложно поделитесь пожалуйста примерами, когда применение типа record оправдано и позволяет упростить код и улучшит его читаемость.
Flip-fl0p
Господа, столкнулся с некоторым неудобством при работе с "безразличными" значениями.
В VHDL есть так называемые безразличные значения, которые дают подсказку синтезатору, что нам все-равно какое значение у сигнала, что позволяет более корректно описать поведение схемы, и дает больше свободы для синтезатора, например:
Код
...
constant  dont_care : std_logic_vector(31 downto 0) := (others => '-');
signal    a         : std_logic;
signal    b         : std_logic_vector(31 downto 0);
signal    c         : natural range 0 to 511;
...

a <= '-';                             -- Присваиваем сигналу а безразличное значение.
b <= (others => '-');                 -- Присваиваем вектору b безразличное значение.
c <= to_integer(unsigned(dont_care)); -- Присваиваем числу   c безразличное значение.

...

Но неудобство возникает, когда есть сигнал типа integer/natural.
Т.к для того, чтобы ему присвоить безразличное значение приходится объявлять константу, содержащую безразличное значение. И через преобразования типов присваивать эту константу. Жить конечно можно. Но не очень удобно.
А по-другому никак не присвоить такое значение для типа integer. Во всяком случае у меня не получается...
Как можно по-другому присвоить безразличное значение для integer ?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.