Verilike

From PSXDEV
Revision as of 16:08, 6 December 2013 by Org (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Verilike -- это специальный скриптовый язык описания цифровой логики. Inspired by Verilog.

Contents

Обзор

Verilike - это транслируемый язык, который предназначен для симуляции цифровых схем. Базовая конструкция - это регистровая передача :

{out1, out2, ..., outN} = cell (expr1, expr2, ..., exprN);

То есть одна регистровая передача имитирует стандартную ячейку или некий кусок схемы.

Как видно, у ячейки может быть несколько выходов.

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

С помощью модулей можно конструировать свои кастомные cell.

Типы данных

Всего два типа данных : wire и reg.

wire не сохраняет своего состояния между двумя итерациями симуляции.

reg при начале симуляции имеет значение 'x' (не определено).

Из проводов и регистров можно делать массивы, например : wire some[8];

Значения

  • Логические уровни : '1' - '9', означающие weak и strong (то есть логическая единица может быть "слабой" и "сильной"). При симуляции "мощность" не учитывается. Это нам нужно для задания стандартных ячеек PSX CPU, которые могут выдавать сигнал разной степени мощности.
  • Земля : '0'
  • Отсоединено (high-Z): 'Z', 'z'
  • Неизвестное значение (undefined): 'X', 'x'
  • Фронт сигнала : '/' - raising (нарастающий, posedge), '\' - falling (спадающий, negedge)

Операции

Операций у нас как таковых нет.

Клиент, который использует Verilike перед симуляцией должен определить "библиотеку" операций.

То есть он должен передать ядру симуляции список ячеек с callback-ами, что делют ячейки. Например NOT:

void cell_not ( var_t * input, var_t * output )
{
    if ( input[0].val[0] == '0' ) output[0].val[0] = '1';
    else output[0].val[0] = '0';
}
 
add_cell ( "not", cell_not, 1 /*количество входов*/, 1 /*количество выходов*/ );

После этого Verilike-скрипт может использовать эту ячейку в своей работе.

Единственное что регистровая передача может быть мгновенной, реализуемой операцией =, а может быть внеблочной <= (непосредственно присваивание производится после выполнения всего блока). Реализуется внеблочное присваивание путём использования теневых значений (shadows): при обычном присваивании значения переменных такие же как и теневые, поэтому после выхода из блока они просто обновляются, внеблочное присваивание помещает значения только в теневые, которые после выполнения блока заменяют старые значения.

Ключевые слова

module, endmodule, block, begin, end, reg, wire, input, output, posedge, negedge

module: Задает новый модуль, в котором содержатся синтезируемые блоки:

module name (input wire a, input wire b, output wire x, output reg y);
...
endmodule

После ключевого слова module указывается имя модуля, которое потом можно использовать в качестве составных ячеек, затем в скобках перечисляются входы и выходы в любом порядке. input может быть с таким же именем, что и output (для двунаправленных проводов).

begin и end просто задают начало и конец группы регистровых передач.

block: определяет чувствительный блок (аналог always в Verilog)

block (posedge clk, res)
    begin
       ...
    end

Чтобы сделать постоянный блок - нужно указать * в качестве параметров.

block (*)
    begin
       ...
    end

Ключевые слова posedge и negedge позволяют инициировать исполнение блока только если смена сигнала произошла на raising/falling edge.