литература / 1kamkin_a_s_vvedenie_v_logicheskoe_proektirovanie_apparatury
.pdf
А.С. Камкин. Введение в логическое проектирование аппаратуры. Конспект лекций. 2012.
D |
SET |
Q |
|
||
|
CLR |
Q |
S |
SET |
Q |
|
||
R CLR Q |
||
J |
SET |
Q |
|
||
K CLR Q |
||
D-триггер является не чем иным, как единичной задержкой: он запоминает и воспроизводит на выходе (с задержкой) то, что подается ему на вход.
RS-триггер устанавливает состояние в 1, если S=1; сбрасывает состояние в 0, если R=1; не изменяет состояние, если RS=00; комбинация RS=11 запрещена.
JK-триггер работает как RS-триггер (где J=S, K=R), но при подаче на вход комбинации JK=11 инвертирует состояние.
Задание. Определить функцию перехода синхронных D-, RS- и JK-триггеров.
D: Q(t+1) = D(t)
RS: Q(t+1) = ~R(t)&(Q(t)|S(t)) | (x&S&R), x — неопределенное значение. JK: Q(t+1) = ~Q(t)&J(t) | Q(t)&~K(t)
Функция возбуждения памяти автомата строится в зависимости от типа используемых триггеров. Очевидно, что для D-триггеров эта функция совпадает с функцией переходов.
Задание. Реализовать единичную задержку через (D-триггер), используя:
1)синхронные RS-триггеры;
2)синхронные JK-триггеры.
Триггеры можно определить через схемы из функциональных элементов с обратными связями. Формально семантику таких схем мы определять не будем. Идея заключается в том, что выходное значение схемы стабилизируется не сразу, а после серии итераций (входы нужно держать неизменными некоторое время). Полученное стабильное состояние и есть выходное значение. Например, асинхронный RS-триггер можно представить следующей схемой.
R |
Q |
|
|
S |
~Q |
|
Эта схема на языке Verilog описывается следующим образом.
// асинхронный RS-триггер module rs_flipflop(q, n, r, s);
output q, n; input r, s;
nor gate1(q, r, n); nor gate2(n, s, q);
endmodule /* rs_flipflop */
Домашнее задание. Нарисовать схему для синхронного JK-триггера, описать схему на языке Verilog, написать функциональный тест.
Описание схем с памятью на языке Verilog
Рассмотрим пример D-триггера (D flip-flop).
// D-триггер с асинхронным сбросом
11
А.С. Камкин. Введение в логическое проектирование аппаратуры. Конспект лекций. 2012.
module d_flipflop(q, d, clk, rst); output q;
input d, clk, rst;
reg q; // возможность присваивания
always @(posedge clk or posedge rst) // список чувствительности if(rst)
q = 1’b0;
else
q = d; endmodule /* d_flipflop */
Моделирование памяти
Для моделирования памяти обычно используется конструкция reg.
Примеры
reg mem; |
// один бит |
||
reg |
mem[0:15]; |
// |
16-разрядный регистр |
reg |
[0:7] mem [0:31]; // |
32 8-разрядных регистров |
|
Ключевое слово reg можно использовать как в отношении внутренних данных, так и выходных сигналов (см. пример D-триггера).
Замечание. К регистрам нельзя применять непрерывное присваивание. Непрерывное присваивание можно применять только к проводам (net, в частности, wire). Для регистров следует использовать процедурное присваивание.
Процедурное присваивание
= — блокируемое присваивание;
<= — неблокируемое присваивание.
Примеры
// блокируемое присваивание a = 1; b = 2;
begin
a = b;
b = a; // a == 2, b == 2
end
// неблокируемое присваивание a = 1; b = 2;
begin
a <= b;
b <= a; // a == 2, b == 1
end
Always-блоки
Примеры
always // бесконечный цикл clk = #10 ~clk;
always @(posedge clk) // обработчик события
...
always @(posedge clk or posedge rst) // обработчик нескольких событий
...
// Гонка: возможны разные порядки always @(posedge clk) a = b;
12
А.С. Камкин. Введение в логическое проектирование аппаратуры. Конспект лекций. 2012.
always @(posedge clk) b = a;
// Гонки нет
always @(posedge clk) a <= b; always @(posedge clk) b <= a;
Конструкция @(событие1 or ... событиеn) называется списком чувствительности процесса.
Управляющие конструкции
Конструкция if
if(<expression1>) <statement1>;
else if(<expression2>) <statement2>;
...
else <default_statement>;
Конструкция case
case(<expression>) <alternative1>: <statement1>; <alternative2>: <statement2>;
...
default: <default_statement>; endcase
Пример. Мультиплексор 4-в-1.
module mux4_1(out, i0, i1, i2, i3, s1, s0); output out;
input i0, i1, i2, i3; input s1, s0;
reg out;
always @(s1 or s0 or i0 or i1 or i2 or i3) begin
case({s1, s0}) 2'b00: out = i0; 2'b01: out = i1; 2'b10: out = i2; 2'b11: out = i3; default: out = 1'bx; endcase
end
endmodule /* mux4_1 */
Задание. Описать на языке Verilog модуль управления пешеходным переходом.
`timescale 1s/1ms
Входы: button (импульсный сигнал).
Выходы: r1, y1, g1, r2, y2, g2 (потенциальные сигналы).
Домашнее задание. Модуль управления лифтом. Сформулировать требования. Продумать интерфейс. Описать на языке Verilog. Написать тест.
13
А.С. Камкин. Введение в логическое проектирование аппаратуры. Конспект лекций. 2012.
Лекция 3 «Примеры проектирования на языке Verilog»
В данной лекции будет рассмотрено несколько примеров проектирования аппаратуры. Цель лекции – продемонстрировать (пусть и в несколько упрощенной форме) основные этапы процесса проектирования аппаратуры (поведенческое проектирование и проектирование на уровне регистровых передач).
Пример 0. «Память прямого доступа на 4 слова»
`timescale 1ns/1ps
// RAM consisting of four 32-bit items
module ram(clk, rst, val_rd, val_wr, addr_in, data_in, val_out, data_out,
is_ready); |
|
|
|
input |
|
clk; |
|
input |
|
rst; |
|
input |
|
val_rd; |
|
input |
|
val_wr; |
|
input |
[1:0] |
addr_in; |
|
input |
[31:0] |
data_in; |
|
output |
|
val_out; |
|
output |
[31:0] |
data_out; |
|
output |
|
is_ready; |
|
reg |
[31:0] |
mem0; |
|
reg |
[31:0] |
mem1; |
|
reg |
[31:0] |
mem2; |
|
reg |
[31:0] |
mem3; |
|
reg |
[31:0] |
result; |
|
reg |
[1:0] |
state; |
|
// State encoding |
|
||
parameter RAM_IDLE |
= 2'b00; |
||
parameter RAM_READ |
= 2'b01; |
||
parameter RAM_WRITE |
= 2'b10; |
||
parameter RAM_RESULT = 2'b11; |
|||
assign |
is_ready = (state == RAM_IDLE); |
||
assign |
val_out |
= (state == RAM_RESULT); |
|
assign |
data_out = (state == RAM_RESULT) ? result : 32'h0000_0000; |
||
always @(posedge rst) begin
mem0 <= 32'hXXXX_XXXX; mem1 <= 32'hXXXX_XXXX; mem2 <= 32'hXXXX_XXXX; mem3 <= 32'hXXXX_XXXX; result <= 32'hXXXX_XXXX; state <= 2'b00;
end
always @(posedge clk) begin
if(state == RAM_IDLE) begin
// Read operation if(~rst & val_rd)
begin
state <= RAM_READ;
// Multiplexor 4-to-1 case(addr_in)
14
А.С. Камкин. Введение в логическое проектирование аппаратуры. Конспект лекций. 2012.
2'b00: result <= mem0; 2'b01: result <= mem1; 2'b10: result <= mem2; 2'b11: result <= mem3; endcase
end
// Write operation else if(~rst & val_wr)
begin
state <= RAM_WRITE; result <= 32'hXXXX_XXXX;
// Demultiplexor 1-to-4 case(addr_in)
2'b00: mem0 <= data_in; 2'b01: mem1 <= data_in; 2'b10: mem2 <= data_in; 2'b11: mem3 <= data_in; endcase
end
end else
begin
if(state == RAM_RESULT) begin
state <= RAM_IDLE; end
else begin
state <= RAM_RESULT; end
end
end endmodule /* ram */
Пример 1. «Очередь FIFO»
`timescale 1ns/1ps
// FIFO queue consisting of four 8-bit items
module fifo(clk, rst, val_rd, val_wr, data_in, val_out, data_out, is_full,
is_ready); |
|
input |
clk; |
input |
rst; |
input |
val_rd; |
input |
val_wr; |
input [31:0] data_in; |
|
output |
val_out; |
output [31:0] data_out; |
|
output |
is_full; |
output |
is_ready; |
// RAM[i] is available
reg val0, val1, val2, val3;
reg |
[1:0] |
addr0; |
reg |
[1:0] |
addr1; |
reg |
[1:0] |
addr2; |
reg |
[1:0] |
addr3; |
reg |
[1:0] |
last; |
wire [1:0] |
free_addr; |
|
wire [1:0] |
addr_in; |
|
15
А.С. Камкин. Введение в логическое проектирование аппаратуры. Конспект лекций. 2012.
assign is_full = val0 & val1 & val2 & val3;
assign free_addr = (~val0 ? 2'h0 : (~val1 ? 2'h1 : (~val2 ? 2'h2 :
(~val3 ? 2'h3 : 2'hX))));
assign addr_in = val_wr ? free_addr : (val_rd ? addr0 : 2'h0);
ram memory
(
.clk(clk),
.rst(rst),
.val_rd(val_rd),
.val_wr(val_wr),
.addr_in(addr_in),
.data_in(data_in),
.val_out(val_out),
.data_out(data_out),
.is_ready(is_ready)
);
always @(posedge rst) begin
val0 <= 1'b0; val1 <= 1'b0; val2 <= 1'b0; val3 <= 1'b0; addr0 <= 2'hX; addr1 <= 2'hX; addr2 <= 2'hX; addr3 <= 2'hX; last <= 2'h0;
end
always @(posedge clk) begin
if(~rst & val_wr) begin
@(val_out);
case(last) 2'h0: begin
addr0 <= free_addr; val0 <= 1'b1; last <= 2'h1; end
2'h1: begin
addr1 <= free_addr; val1 <= 1'b1; last <= 2'h2; end
2'h2: begin
addr2 <= free_addr; val2 <= 1'b1; last <= 2'h3; end
2'h3: begin
addr3 <= free_addr; val3 <= 1'b1; last <= 2'h3; end
endcase end
else if(~rst & val_rd) begin
case(addr0)
2'h0: val0 <= 1'b0; 2'h1: val1 <= 1'b0; 2'h2: val2 <= 1'b0; 2'h3: val3 <= 1'b0;
16
А.С. Камкин. Введение в логическое проектирование аппаратуры. Конспект лекций. 2012.
endcase
case(last)
2'h0: last <= 2'h0; 2'h1: last <= 2'h0; 2'h2: last <= 2'h1; 2'h3: last <= 2'h2; endcase
@(val_out);
addr0 <= addr1; addr1 <= addr2; addr2 <= addr3; addr3 <= 2'hX;
end
end
endmodule /* fifo */
Домашнее задание. Доделать модуль FIFO, написать базовый тест, результат отправить по почте.
Лекция 4 «Дискретно-событийное моделирование»
Введение
Как мы уже знаем, модели аппаратуры на HDL-языках можно выполнять в специальном программном окружении — симуляторе. Большинство симуляторов аппаратуры основано на парадигме дискретно-событийного имитационного моделирования (event-driven simulation),
называемой также принципом особых состояний. Суть этого подхода заключается в абстрагировании от непрерывной природы явлений (например, распространение электрического тока) и рассмотрении только основных событий в моделируемой системе (изменение уровня сигнала, окончание времени ожидания). Дискретно-событийное моделирование имеет огромную сферу приложений, включая рассматриваемое нами моделирование аппаратуры, а также моделирование бизнес-процессов, боевых действий, транспортных потоков. Основателем подхода считается Джеффри Гордон (1960-ые гг.).
Альтернативой событийному моделированию является моделирование по интервалам времени (cycle-driven simulation).
Дискретно-событийное моделирование аппаратуры
Основные понятия
Модельное время (время симулятора) — дискретная величина, не убывающая в процессе моделирования, значения которой кратны заданной точности моделирования.
Событие — это изменение значение сигнала, осуществляемое в определенное время. События вызываются присваиваниями и происходят мгновенно. Если присваивание не меняет значения сигнала, события не возникает.
Очередь присваиваний (транзакций) — упорядоченный по времени список запланированных присваиваний (с каждым присваиванием A ассоциировано время tA, когда оно осуществляется). Список является глобальным для всех сигналов модели.
Драйвер сигнала — проекция очереди присваиваний для данного сигнала, то есть драйвер сигнала — это список запланированных изменений этого сигнала.
Пример
A <= #2 1;
17
А.С. Камкин. Введение в логическое проектирование аппаратуры. Конспект лекций. 2012.
B <= #4 0;
C <= #8 1;
Очередь присваиваний: (A, 1, 2), (B, 4, 0), (C, 8, 1)
Обработчик события — множество процессов, которые запускаются при возникновении события. Обработчик события, может порождать новые присваивания (transaction generation), которые добавляются в очередь присваиваний. Важно отметить, что сами присваивания при этом не осуществляются.
Примеры
always @(posedge clk) ... // обработчик положительного фронта clk
assign z = #10 x & y // обработчик изменения x или y
Цикл работы симулятора
1.Получить очередное присваивание (или присваивания) A из очереди.
2.Изменить текущее время симулятора Tsim на время TA.
3.Осуществить присваивание (присваивания).
4.Если возникло событие, вызвать обработчик события.
Вначальный момент Tsim=0 и запускаются процессы инициализации (initial) и другие процессы, для которых не указан список чувствительности.
При обновлении очереди присваиваний (драйвера сигнала) возможны конфликты — одновременные присваивания различных значений. Разрешение конфликтов управляется типами соединений (например, wor и wand), которые в нашем курсе не рассматриваются.
Если несколько присваиваний имеют одно и то же время, их порядок не определен. Порядок вызова активных процессов также не определен. Для задания порядка «одновременных» присваиваний используются дельта-задержки.
Дельта-задержка
Дельта-задержка — это бесконечно малая задержка, используемая для упорядочивания событий, происходящих одновременно.
Примеры
initial A = 1;
initial A = 0; // порядок не определен
initial A = 1;
initial A = #0 0; // сначала A = 1, потом A = 0
Примеры
A <= #2 1; // в очередь добавляется <A, 1, Tsim+2>
A <= 1; // в очередь добавляется <A, 1, Tsim+1 >
Теоретически, любое конечное число дельта-задержек меньше одной единицы времени. На практике, максимальное число дельта-задержек, в одной единице времени является параметром симулятора.
Таким образом, в симуляторах используется двумерная модель времени. На оси абсцисс указываются моменты времени наступления событий. На оси ординат откладываются дельта-задержки. Например, (4, 2) означает, что событие происходит в момент времени 4 спустя две дельта-задержки.
18
