1 of 27

Комбинационная логика

Введение в проектирование на языке Verilog

Прутьянов В. В.

2 of 27

  • Виды цифровых схем
  • Сумматор
  • Арифметико-логические операции в языке Verilog
  • Мультиплексор
  • Конструкция always @(*) и блокирующее присваивание
  • Конструкция case-endcase
  • Энкодер
  • Декодер
  • АЛУ
  • Branch Unit

3 of 27

Цифровые схемы

Комбинационные

Последовательностные

Синхронные

4 of 27

Цифровые схемы

Комбинационные

Последовательностные

Синхронные

5 of 27

Побитовые операции в языке Verilog

  • NOT: ~x
  • OR: x & y
  • AND: x | y
  • XOR: x ^ y

Разрядность результата &, |, ^ определяется по наибольшей из разрядностей операндов

Источник: IEEE Std 1364-2001 Verilog Hardware Description Language

6 of 27

Full adder

module full_adder(

input a,

input b,

input carry_in,

output sum,

output carry_out

);

assign sum = (a ^ b) ^ carry_in;

assign carry_out = (a & b) | ((a ^ b) & carry_in);

endmodule

7 of 27

Ripple-carry adder (RCA)

module rca #(parameter N = 4)(

input [N-1:0] a,

input [N-1:0] b,

output [N-1:0] sum

);

wire [N:0] c;

assign c[0] = 1'b0;

genvar i;

generate

for (i = 0; i < N; i = i + 1)

begin : gen_adders

full_adder fa(

.a(a[i]), .b(b[i]), .carry_in(c[i]), .sum(sum[i]), .carry_out(c[i+1]));

end

endgenerate

endmodule

8 of 27

Carry look-ahead adder (CLA)

module cla #(parameter N = 4)(

input [N-1:0] a,

input [N-1:0] b,

output [N-1:0] sum

);

wire [N:0] c;

wire [N-1:0] P = a | b;

wire [N-1:0] G = a & b;

assign c[0] = 1'b0;

assign c[N:1] = G | (P & c);

genvar i;

generate

for (i = 0; i < N; i = i + 1)

begin : gen_adders

full_adder fa(.a(a[i]), .b(b[i]), .carry_in(c[i]), .sum(sum[i]), .carry_out(c[i+1]));

end

endgenerate

endmodule

9 of 27

Сумматор в Verilog

module adder #(

parameter N = 8

)(

input [N-1:0] a,

input [N-1:0] b,

output [N-1:0] sum

);

assign sum = a + b;

endmodule

10 of 27

Сумматор в Verilog

module adder #(

parameter N = 8

)(

input [N-1:0] a,

input [N-1:0] b,

output [N-1:0] sum

);

assign sum = a + b;

endmodule

  • Существует много различных архитектур сумматоров и других вычислительных устройств
  • Современные САПРы распознают типовые блоки и хорошо оптимизируют комбинационную логику
  • Если нет дополнительной, неизвестной САПРу, информации о входных данных, ручные оптимизации могут привести к потере времени и не дать результата

11 of 27

Операторы в языке Verilog

  • Побитовые (bitwise): ~x, x & y, x | y, x ^ y
  • Логические: !x, x && y, x || y
  • Арифметические: x + y, x - y, -x, x * y, x / y, x % y, x ** y
  • Сдвига: x << y, x >> y (логический), x <<< y, x >>> y (арифметический)
  • Отношения: x == y, x != y, x < y, x > y, x <= y, x >= y
  • Редукции (reduction): &x, |x, ^x
  • Другие: x ? y : z (тернарный оператор), {x, y} (конкатенация), {x{y}} (повторение)

12 of 27

Знаковые и беззнаковые типы в Verilog

  • По-умолчанию все объявляемые с помощью wire/reg/parameter/etc. сигналы являются беззнаковыми
  • Чтобы сигнал интерпретировался в виде дополнительного кода (two’s complement) при выполнении арифметических операций, используется ключевое слово signed
    • signed reg [15:0] x;
    • signed wire [9:0] y = x >>> 8;
  • Системные задачи $signed(), $unsigned() позволяют конвертировать знаковые и беззнаковые сигналы
    • unsigned reg [15:0] x;
    • signed wire [15:0] y = $signed(x) >>> 8;

13 of 27

Мультиплексор

  • Имеет m входов для n-разрядных данных, один k-разрядный (k = ⎡log₂(m)⎤) адресный вход и один n-разрядный выход
  • Передает данные от входа с номером, соответствующим значению адресного входа, на выход
  • В случае 2 входов удобно использовать тернарный оператор или if-else
  • В случае более 2 входов удобно использовать блок case-endcase

14 of 27

Мультиплексор 2-в-1

module mux #(

parameter WIDTH = 32

)(

input wire [WIDTH-1:0] i0, i1,

input wire sel,

output wire [WIDTH-1:0] out

);

assign out = sel ? i1 : i0;

endmodule

15 of 27

Конструкция always @(*) и блокирующее присваивание

module mux #(

parameter WIDTH = 32

)(

input wire [WIDTH-1:0] i0, i1,

input wire sel,

output reg [WIDTH-1:0] out

);

always @(*) begin

if (sel)

out = i1;

else

out = i0;

end

endmodule

  • Конструкции if-else, case-endcase могут присутствовать внутри initial и always конструкций
  • Внутри initial и always невозможно использовать непрерывное присваивание, только блокирующее или неблокирующее
  • В списке чувствительности (sensitivity list) для always указываются события, по которым срабатывают присваивания
  • Сигнал слева от blocking assignment должен иметь тип reg
  • Символ * в списке чувствительности означает срабатывание при изменении любого сигнала в модуле, поэтому конструкции always @(*) используются для моделирования комбинационной логики

16 of 27

Конструкция always @(*) и блокирующее присваивание

module mux #(

parameter WIDTH = 32

)(

input wire [WIDTH-1:0] i0, i1,

input wire sel,

output reg [WIDTH-1:0] out

);

always @(*) begin

if (sel)

out = i1;

else

out = i0;

end

endmodule

  • Конструкции if-else, case-endcase могут присутствовать внутри initial и always конструкций
  • Внутри initial и always невозможно использовать непрерывное присваивание, только блокирующее или неблокирующее
  • В списке чувствительности (sensitivity list) для always указываются события, по которым срабатывают присваивания
  • Сигнал слева от blocking assignment должен иметь тип reg
  • Символ * в списке чувствительности означает срабатывание при изменении любого сигнала в модуле, поэтому конструкции always @(*) используются для моделирования комбинационной логики

always @(*) begin

case (sel)

1'b0: out = i0;

1'b1: out = i1;

endcase

end

17 of 27

Конструкция always @(*) и блокирующее присваивание

module mux3(

input wire i0, i1, i2,

input wire sel0, sel1,

output wire out

);

reg x, y;

assign out = y;

always @(*) begin

if (sel0)

x = i1;

else

x = i0;

end

always @(*) begin

if (sel1)

y = i2;

else

y = x;

end

endmodule

  • С точки зрения симулятора, событие изменения сигнала x в результате работы 1-го always вызывает срабатывание 2-го always
  • Порядок вхождения самих конструкций в коде не имеет значения

18 of 27

Конструкция always @(*) и блокирующее присваивание

module bad_mux3(

input wire i0, i1,

input wire sel0, sel1,

output wire out

);

reg x, y;

assign out = y;

always @(*) begin

if (sel0)

x = i1;

else

x = i0;

end

always @(*) begin

if (sel1)

y = x;

end

endmodule

19 of 27

Конструкция always @(*) и блокирующее присваивание

module bad_mux3(

input wire i0, i1,

input wire sel0, sel1,

output wire out

);

reg x, y;

assign out = y;

always @(*) begin

if (sel0)

x = i1;

else

x = i0;

end

always @(*) begin

if (sel1)

y = x;

end

endmodule

  • Если не обработать все случаи в конструкциях if-else, case-endcase, схема перестает быть комбинационной
  • Если sel1 == 0 во втором always, симулятор оставляет предыдущее значение сигнала y, значит схема должна сохранять свое состояние
  • При синтезе такого кода образуется latch
  • Таких ситуаций следует избегать, например с помощью линтеров или сообщений синтеза

Warning (10240): Verilog HDL Always Construct warning at bad_mux3.v(19): inferring latch(es) for variable "y", which holds its previous value in one or more paths through the always construct

20 of 27

Verilator: линтинг

$ verilator --lint-only bad_mux3.v

%Warning-LATCH: bad_mux3.v:18:1: Latch inferred for signal 'mux3.y' (not all control paths of combinational always assign a value)

: ... Suggest use of always_latch for intentional latches

18 | always @(*) begin

| ^~~~~~

... For warning description see https://verilator.org/warn/LATCH?v=5.040

... Use "/* verilator lint_off LATCH */" and lint_on around source to disable this message.

%Error: Exiting due to 1 warning(s)

21 of 27

Блоки case/casez-endcase

always @(*) begin

case ({sel1, sel0})

2'b00: y = i0;

2'b01: y = i1;

2'b10: y = i2;

2'b11: y = i2;

endcase

end

always @(*) begin

case ({sel1, sel0})

2'b00: y = i0;

2'b01: y = i1;

default: y = i2;

endcase

end

always @(*) begin

casez ({sel1, sel0})

2'b00: y = i0;

2'b01: y = i1;

2'b1?: y = i2;

endcase

end

  • В конструкциях case/casez-endcase доступен вариант default
  • В casez-endcase можно использовать символ ? для незначимого бита/цифры (don’t care value)

22 of 27

Энкодер

  • Энкодер (encoder, шифратор) (в широком смысле) – цифровое устройство, преобразующее входной двоичный код в выходной двоичный код, обычно имеющий меньшую разрядность
  • [Одноединичный] энкодер (one-hot encoder) принимает на вход 2^k-битное слово с одной 1 (one-hot) или одним 0 (one-cold) и возвращает k-битный номер позиции 1 или 0 соответственно
  • Приоритетный энкодер (priority encoder) принимает на вход 2^k-битное слово и возвращает k-битный номер позиции наиболее (MSB) или наименее (LSB) значащей 1 соответственно

// 4-to-2 MSB priority encoder

module enc4(

input wire [3:0] i_data,

output reg [1:0] o_enc,

output wire o_vld

);

always @(*) begin

casez (i_data)

4'b1???: o_enc = 2'd3;

4'b01??: o_enc = 2'd2;

4'b001?: o_enc = 2'd1;

4'b0001: o_enc = 2'd0;

default: o_enc = 2'dX;

endcase

end

assign o_vld = |i_data; // Reduction OR

endmodule

23 of 27

Декодер

  • Декодер (decoder, дешифратор) (в широком смысле) преобразует входной двоичный код в выходной двоичный код, обычно имеющий большую разрядность
  • [Одноединичный] декодер (one-hot decoder) принимает на вход k-битное слово и возвращает слово с одной 1 (one-hot) или одним 0 (one-cold) в позиции соответствующей входному номеру

// 2-to-4 one-hot decoder

module dec4(

input wire [1:0] i_data,

output wire [3:0] o_dec

);

assign o_dec = 4'b1 << i_data;

endmodule

module dec4(

input wire [1:0] i_data,

output reg [3:0] o_dec

);

always @(*) begin

case (i_data)

2'd0: o_dec = 4'b0001;

2'd1: o_dec = 4'b0010;

2'd2: o_dec = 4'b0100;

2'd3: o_dec = 4'b1000;

endcase

end

endmodule

24 of 27

Функции

  • Функция в Verilog – блок кода, который выполняет вычисления и возвращает одно значение
  • Функции могут иметь входы (input), локальные переменные, использовать конструкции if, case, for для описания поведения, а также вызовы других функций
  • Функции не могут использовать задержки и события (#, @, wait и т.д.), поведенческие блоки (initial, always), определения и экземпляры модулей, непрерывные присваивания
  • Подходят для переиспользования кода, в т.ч. комбинационной логики в синтезируемом коде

function slt; // Signed less-than

input [WIDTH-1:0] a, b;

begin

slt = $signed(a) < $signed(b);

end

endfunction

wire a_lt_b;

assign a_lt_b = slt(a, b);

25 of 27

АЛУ

Арифметико-логическое устройство – блок в вычислительном устройстве (CPU, GPU и др.), производящий арифметические, логические и побитовые операции над целыми числами

ADD

Сложение

rd = rs1 + rs2

SUB

Вычитание

rd = rs1 - rs2

SLL

Логический* сдвиг влево

rd = rs1 << rs24:0

SLT

Rd в 1, если rs1 знаково* меньше, чем rs2

rd = (rs1 <s rs2)

SLTU

Rd в 1, если rs1 беззнаково* меньше, чем rs2

rd = (rs1 <u rs2)

XOR

Побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ

rs = rs1 ^ rs2

SRL

Логический* сдвиг вправо

rd = rs1 >> rs24:0

SRA

Арифметический* сдвиг вправо

rd = rs1 >>> rs24:0

OR

Побитовая операция ИЛИ

rd = rs1 | rs2

AND

Побитовая операция И

rd = rs1 & rs2

* См. детали по R операциям RV32I в The RISC-V Instruction Set Manual Volume I: Unprivileged ISA

26 of 27

Блок сравнения

Блок сравнения – опциональный (его роль может выполнять ALU) блок для проверки выполнения условия в инструкциях условного перехода (branch)

BEQ

Переход, если равно

out = (rs1 == rs2)

BNE

Переход, если не равно

out = (rs1 ≠ rs2)

BLT

Переход, если знаково* меньше

out = (rs1 < rs2)

BGE

Переход, если знаково* больше или равно

out = (rs1 ≥ rs2)

BLTU

Переход, если беззнаково* меньше

out = (rs1 < rs2)

BGEU

Переход, если беззнаково* больше

out = (rs1 ≥ rs2)

* См. детали по B операциям RV32I в The RISC-V Instruction Set Manual Volume I: Unprivileged ISA

27 of 27

Задание

  • Спроектировать и проверить мультиплексор параметризованной разрядности на 4 входа
  • Спроектировать и проверить комбинационное АЛУ для вычисления результата команд типа R архитектуры RV32I
  • Спроектировать и проверить блок сравнения для проверки условий команд типа B архитектуры RV32I