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

    

ModelSim, вопросы новичка

А какую цель Вы ставите перед собой ?

Сделать правильно ?

Или научиться ?

Или сделать и забыть ?

Просто Ваш код, ничего кроме дерганья глаза у меня не вызвал...

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


Ссылка на сообщение
Поделиться на другие сайты
А какую цель Вы ставите перед собой ?

Сделать правильно ?

Или научиться ?

Сделать правильно и научиться.

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

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


Ссылка на сообщение
Поделиться на другие сайты
Вот код одного из модулей:
Во-первых, используйте defin-ы для Ваших констант:

`define arr_dim 16

`define arr_rng [`arr_dim-1:0]

и тогда

output [15:0]data_4,

выливается в

output `arr_rng data_4,

далее

wire s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12,s13,s14,s15,s16;

пишется как

wire [16:1] s;

или снова как выше через defin-ы.

Далее

AND2 AND2_01(.IN1(addr[0]), .IN2(wr), .OUT(s1));

если не важно указание имени инстанциированного модуля, то его можно опустить:

AND2 (.IN1(addr[0]), .IN2(wr), .OUT(s1));

вообще, подозреваю, что такую последовательность Ваших примитивов можно описать через generate

В модуле используется элемент AND2, экземпляры которого я создаю. Но элемент AND2 так же как и DFF не могу найти ни в одной из библиотек, подключал уже все файлы из папки C:\altera\15.0\modelsim_ase\altera\verilog\src

Я подозреваю, что это из за того, что проект разрабатывался в Quartus 9.1, а ModelSim используется от версии квартуса 15.0 где отсутствует библиотека для cyclone III. Как мне быть? Перейти на Quartus 13.1?

Либо использовать ModelSim-Altera(Starter)Edition от той версии Quartus-a, которая поддерживает интересующий чип, либо (здесь могу врать) скомпилить библиотеки для того ModelSima, который чип не поддерживает, но с которым хочется работать.
Изменено пользователем Marat Zuev

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


Ссылка на сообщение
Поделиться на другие сайты
Спасибо, попробую. Еще один вопрос: как описать этот BDF на verilog?

В квартусе есть функция "convert to HDL code" и этот BDF превратится в код на Verilog.

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


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

AND2 AND2_01(.IN1(addr[0]), .IN2(wr), .OUT(s1));

ram ram_01(.data(data), .wren(s1), .address(w_VCC), .clock(clk), .q(data_1));

...

 

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

 

А еще про память: это поптыка самостоятельно создать что-то вроде IP Core альтеры, которое разведется в RAM память? Если так - тогда стоит полистать мануалы по стилям кодинга от Альтеры же - там примеры, как написать, что бы ваш код лег именно в память, а не логику.

 

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


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

С учетом замечаний Marat Zuev переписал модуль, получилось компактнее! :biggrin:

module ram_blocks(
    input clk, 
    input [15:0]addr, 
    input [15:0]data, 
    input wr,
    
    output [15:0]data_1,
    output [15:0]data_2,
    output [15:0]data_3,
    output [15:0]data_4,
    output [15:0]data_5,
    output [15:0]data_6,
    output [15:0]data_7,
    output [15:0]data_8,
    output [15:0]data_9,
    output [15:0]data_10,
    output [15:0]data_11,
    output [15:0]data_12,
    output [15:0]data_13,
    output [15:0]data_14,
    output [15:0]data_15,
    output [15:0]data_16);
    
    wire     [15:0]data_out[15:0];
    wire     [16:0]s;
    
    genvar i;
    generate
    for(i = 0; i < 16; i = i + 1)
    begin : ram_generation
        assign s[i] = addr[i] & wr;
        ram     ram_inst(.data(data), .wren(s[i]), .address(1'b1), .clock(clk), .q(data_out[i]));        
    end
    endgenerate

    assign data_1 = data_out[0];
    assign data_2 = data_out[1];
    assign data_3 = data_out[2];
    assign data_4 = data_out[3];
    assign data_5 = data_out[4];
    assign data_6 = data_out[5];
    assign data_7 = data_out[6];
    assign data_8 = data_out[7];
    assign data_9 = data_out[8];
    assign data_10 = data_out[9];
    assign data_11 = data_out[10];
    assign data_12 = data_out[11];
    assign data_13 = data_out[12];
    assign data_14 = data_out[13];
    assign data_15 = data_out[14];
    assign data_16 = data_out[15];
        
endmodule

nice_vladi по поводу использования AND2-примитива согласен с Вами, сделал через & и assign, но вот DFF так и не нашел в библиотеке, пришлось описывать вручную:

    wire     w_cs
    reg     dff_out;
    
    always @(posedge clk)
    begin
        dff_out <= cs;
    end
    assign w_cs = dff_out;

Неудобно немного получается, но с этим можно мириться.

Проект скомпилил в Modelsim 6.5, симуляция собралась с варнингами:

# ** Warning: (vsim-3009) [TSCALE] - Module 'ram_blocks' does not have a `timescale directive in effect, but previous modules do.
#         Region: /tb/main_inst_tb/mem_block1/ram_blocks1
# Loading work.decoder
# ** Warning: (vsim-3009) [TSCALE] - Module 'decoder' does not have a `timescale directive in effect, but previous modules do.
#         Region: /tb/main_inst_tb/mem_block1/decoder1

Как-то можно от них избавиться? Объявлять `timescale в каждом файле?

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


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

А если надо 1024 разряда ?

Вы вроде хотите научиться делать правильно. Тут Вам могут помочь, и обязательно помогут. Но от вас требуется правильно сформулировать задачу !

Я так и не понял толком, что Вы хотите сделать. Похоже на некое подобие памяти. Но где такое может пригодиться я ума не приложу !

P.S. Спускаться на уровень описания взаимодействия триггеров между собой необходимо лишь в том случае, когда требуется выжать из чипа каждый мегагерц. Но без правильного файла констрейнов, и атрибутов синтеза - грош цена такому описанию... Один фиг, синтезатор разложит по-своему. Да и не стоит недоверять синтезатору. Синтезатор умный. Если правильно описана схема на поведенческом уровне , то синтезатор её сам прекрасно разместит в ячейках FPGA. Почти всегда синтезатор делает это лучше, чем разработчик.

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


Ссылка на сообщение
Поделиться на другие сайты
Но от вас требуется правильно сформулировать задачу !

Я так и не понял толком, что Вы хотите сделать. Похоже на некое подобие памяти. Но где такое может пригодиться я ума не приложу !

Я тоже не понял. Ведь адрес-то только один, а значит одновременно все блоки памяти считываться и записываться не будут. А тогда почему надо много мелких блоков, а не один, в который все и поместится?

И вот это:

assign s = addr & wr;

ram ram_inst(.data(data), .wren(s), .address(1'b1), .clock(clk), .q(data_out));

совершенно криво, можно даже сказать, что уродливо... :(

 

Короче, проект методически начат не верно, отсюда и все вопросы...

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


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

Спасибо всем за критику)

 

Задачу в двух словах описать можно так: есть МК и есть ПЛИС. На ПЛИС построено несколько конечных автоматов, каждый из которых работает со своими данными, которые загружаются из МК по SPI по разным адресам RAM. Поскольку каждый блок работает со своим словом данных и нужно чтобы данные всегда были видимы блоку я отказался от использования одного компонента RAM, скажем 16x16, выдающего по адресу только одно значение данных и использую несколько блоков RAM минимальной разрядности (что, как справедливо заметил Иосиф Григорьевич, криво и уродливо;)), Компонент RAM пришлось генерировать через визард, т.к. другого способа добавить ячейку RAM я не нашел (создавать RAM из темплейтов пробовал - при компиляции создаются D-триггеры, что громоздко и неоптимально ввиду лишней занимаемой памяти). Минимальная разрядность адреса блока RAM через визард - 2, если указываю 1 - выдает ошибку.

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

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


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

Довольный как слон :biggrin:

Все получилось! Собрал проект в modelsim 10.3, все работает, нашел благодаря ему пару ошибок, которые в стандартном квартус-симуляторе не отображались:

 

sim_good.png

 

В момент времени, когда начинал работать умножитель на одном модуле появлялось неопределенное состояние, вспомнил Иосифа Григорьевича, добавил reset описание default и вуаля! Сейчас соберу все в красивый скрипт, чтобы на кнопку только ПЭМС и все как я люблю - во весь экран файл симуляции) Доделок конечно еще много, но какая-то конкретика есть. Впереди освоение TimeQuest...

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

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


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

 

Задачу в двух словах описать можно так: есть МК и есть ПЛИС. На ПЛИС построено несколько конечных автоматов, каждый из которых работает со своими данными, которые загружаются из МК по SPI по разным адресам RAM. Поскольку каждый блок работает со своим словом данных и нужно чтобы данные всегда были видимы блоку я отказался от использования одного компонента RAM, скажем 16x16, выдающего по адресу только одно значение данных и использую несколько блоков RAM минимальной разрядности

У Вас что, автоматы всегда работают с данными в памяти одновременно?

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

 

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


Ссылка на сообщение
Поделиться на другие сайты
У Вас что, автоматы всегда работают с данными в памяти одновременно?

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

Чтение через арбитр подразумевает поочередное обращение к данным, а мне они (данные) нужны всегда, этот вариант я продумывал в самом начале.

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


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

И в каждом состоянии автомат пользуется этими данными? Или все же не в каждом?

 

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


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

Конечно не в каждом, но зачем лишние заморочки? Данные передаются с начала процесса одной колбасой по SPI, каждое слово ложится в RAM по конкретному адресу и далее используется отдельными блоками (автоматими). Зачем здесь арбитр и дополнительная синхронизация автоматов по выборке данных из одного большого RAM-блока?

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


Ссылка на сообщение
Поделиться на другие сайты
Конечно не в каждом, но зачем лишние заморочки? Данные передаются с начала процесса одной колбасой по SPI, каждое слово ложится в RAM по конкретному адресу и далее используется отдельными блоками (автоматими). Зачем здесь арбитр и дополнительная синхронизация автоматов по выборке данных из одного большого RAM-блока?

Так и запихните в Ваш каждый автомат блок памяти. И по SPI грузите в нужный автомат, нужные данные. Так логичнее схема смотрится, как мне кажется.

Есть SPI контроллер, который принимает данные. Есть простенький Арбитр - который принимаемые по SPI данные записывает в память автомата. И есть ваши автоматы, которые уже работают с памятью, куда арбитр данные загнал.

Вообще неплохо было бы сначала на бумаге структурную схему проекта нарисовать. Затем описать алгоритмы в виде блок схем, или графов перехода, или опять в виде структурной схемы прохождения данных. И затем уже все это дело перенести на HDL ;)

 

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

SPI.jpg

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


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

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти