Необходимые инструменты
Мы собираемся использовать Verilog для этого проекта. Итак, должен подойти любой компилятор и симулятор verilog. Xilinx и ModelSim - действительно хорошие инструменты. Но поскольку я специалист по * nix, я собираюсь использовать Icarus Verilog для компиляции кода и gtkwave для просмотра временных диаграмм сигналов. Они бесплатны в использовании, просты в освоении и гораздо более легковесны, чем другие полноценные варианты.
Шаги по установке, настройке и использованию этих двух инструментов (verilog и gtkwave) описаны в другой моей статье.
Понятия
В сложной цифровой системе аппаратное обеспечение обычно разделено на две части:
a) Путь передачи данных, который состоит из функциональных блоков, в которых выполняются все вычисления. Обычно состоит из регистров, мультиплексоров, шины, сумматоров, умножителей, счетчиков и других функциональных блоков.
б) Канал управления, который реализует конечный автомат и подает управляющие сигналы в канал передачи данных в надлежащей последовательности. В ответ на управляющие сигналы по каналу передачи данных выполняются различные операции. Кроме того, он принимает входные данные из пути передачи данных, касающиеся различной информации о состоянии.
Переход состояния контролируется управляющим трактом или блоком управления или контроллером. Блок управления (CU) посылает все сигналы, необходимые для запуска любой операции в тракте передачи данных. Путь к данным состоит из элементов, которые обрабатывают данные и адреса. Обычно также имеется тактовый сигнал и шина данных, которые идут как по каналу передачи данных, так и по пути управления. Задавая определенную последовательность операций, блок управления может реализовать заданный алгоритм.
Следующая блок-схема показывает идею разделения системы на путь передачи данных и путь управления:
Блок-схема машины состояний.
Проблема для моделирования
Умножение путем повторного сложения
- Алгоритм: Умножение (a, b)
- Шаг 1. Получите значения для a и b.
- Шаг 2. Если (либо a = 0, либо b = 0), то
- Шаг 3. Установите значение продукта равным 0
- Шаг 4. Иначе
- Шаг 5. Установите значение product равным 0
- Шаг 6. В то время как (b > 0)
- Шаг 7. Установите значение product равным (product + a)
- Шаг 8. Установите значение b равным (b - 1)
- Шаг 9. Завершить цикл while
- Шаг 10. Конец, если
- Шаг 11. Выведите стоимость продукта
- Шаг 12. Остановка
Блок-схема
Блок-схема машины состояний.
Проектирование пути передачи данных и пути управления.
Наш канал передачи данных состоит из трех регистров: A, B и P, одного блока суммирования и одного блока сравнения. Более того, эти компоненты подключены к шине данных (через которую поступают входные данные) и различным входящим сигналам (LdA, LdP, clrP, LdB, decB, clk) от блока управления и генератора тактовой частоты. Кроме того, имеется исходящий сигнал состояния eqz. Кроме того, есть 3 провода: провод x, соединяющий регистр A с сумматором, провод, соединяющий регистр с сумматором и провод z, который переводит сумму A и P обратно в P.
Путь передачи данных.
Если мы видим систему в целом, то поступает 1 строка данных (data_in) и 2 сигнала (start и clk) и выходит один сигнал состояния (done). Эти 4 параметра - это то, что мы будем использовать на испытательном стенде также для тестирования нашей конструкции. Кроме этого, 5 управляющих сигналов поступают в блок передачи данных от блока управления, помимо тактового сигнала. И путь передачи данных возвращает сигнал состояния eqz (равный нулю) от компаратора к CU.
Схема данных и управления.
Блок управления и его сигналы помогают определять переходы в различные состояния для различных операций и условий. На следующей диаграмме показано, как блок-схема алгоритма сопоставляется с диаграммой конечного состояния:
Блок-схема алгоритма.
Реализация в Verilog.
Модуль для параллельного ввода-вывода регистра A. Этот регистр PIPO сохраняет 16-битные данные до тех пор, пока сигнал загрузки (ld) не будет установлен снова. Как только ld установлен, новые данные загружаются на следующем положительном фронте синхронизации.
Verilog Code:
module PIPO_R1 (dout, din, ld, clk); input [15:0] din; input ld, clk; output reg [15:0] dout; always @(posedge clk) // if load signal is on, load new data if (ld) dout <= din; endmodule
Модуль для параллельного ввода-вывода регистра P.
Этот регистр PIPO сохраняет 16-битные данные до тех пор, пока снова не будет установлен сигнал load (ld) или clear (clr). Как только ld установлен, новые данные загружаются на следующем положительном фронте синхронизации. Когда установлен сигнал clr, все данные стираются до 0.
Verilog Code:
module PIPO_R2 (dout, din, ld, clr, clk); input [15:0] din; input ld, clr, clk; output reg [15:0] dout; always @(posedge clk) // if clear signal is on, set register value to 0 if (clr) dout <= 16'b0; // else if load signal is on, load new data else if (ld) dout <= din; endmodule
Модуль для сумматора.
Принимает два 16-битных данных, складывает и возвращает обратно 16-битную сумму. Не заботится о переполнении.
Verilog Code:
module add (out, in1, in2); input [15:0] in1, in2; output reg [15:0] out; always @(*) out = in1 + in2; endmodule
Модуль для блока сравнения.
Проверяет, равны ли данные 0 или нет.
Verilog Code:
module comparator (eqz, data); input [15:0] data; output eqz; assign eqz = (data == 0); endmodule
Модуль для PIPO регистра B и счетчика (для уменьшения значения регистра B).
Регистр PIPO B загружает новые данные, если включен сигнал ld. Это уменьшает содержимое B на 1, если включен сигнал dec.
Verilog Code:
module counter (dout, din, ld, dec, clk); input [15:0] din; input ld, dec, clk; output reg [15:0] dout; always @(posedge clk) if (ld) dout <= din; else if (dec) dout <= dout - 1; endmodule
Модуль для пути передачи данных.
Он реализует дизайн пути передачи данных.
Verilog Code:
module datapath (eqz, LdA, LdB, LdP, clrP, decB, data_in, clk); input LdA, LdB, LdP, clrP, decB, clk; input [15:0] data_in; output eqz; wire [15:0] x, y, z, Bout, Bus; PIPO_R1 A (x, data_in, LdA, clk); PIPO_R2 P (y, z, LdP, clrP, clk); counter B (Bout, data_in, LdB, decB, clk); add AD (z, x, y); comparator COMP (eqz, Bout); endmodule
Модуль для контроллера.
Реализует схему контура управления, как показано на рисунке 6. Канал передачи данных выполняет фактическую обработку входных данных, а канал управления определяет, какая операция должна быть выполнена каналом передачи данных, используя сигналы LdA, LdB, LdP, clrP, decB и done. Вычислительный модуль также внедряет FSM.
Verilog Code:
module controller (LdA, LdB, LdP, clrP, decB, done, clk, eqz, start); input clk, eqz, start; output reg LdA, LdB, LdP, clrP, decB, done; reg [2:0] state; parameter s0=3'b000, s1=3'b001, s2=3'b010, s3=3'b011, s4=3'b100; always @(posedge clk) begin case (state) s0: if (start) state <= s1; s1: state <= s2; s2: state <= s3; s3: #2 if (eqz) state <= s4; s4: state <= s4; default: state <= s0; endcase end always @(state) begin case (state) s0: begin #1 LdA = 0; LdB = 0; LdP = 0; clrP = 0; decB = 0; end s1: begin #1 LdA = 1; end s2: begin #1 LdA = 0; LdB = 1; clrP = 1; end s3: begin #1 LdB = 0; LdP = 1; clrP = 0; decB = 1; end s4: begin #1 done = 1; LdB = 0; LdP = 0; decB = 0; end default: begin #1 LdA = 0; LdB = 0; LdP = 0; clrP = 0; decB = 0; end endcase end endmodule
Испытательный стенд.
Реализует тестовый стенд для тестирования модулей путем умножения 5 на 6 с использованием повторяющегося сложения. Файл дампа формы сигнала сохраняется в mul.vcd, который можно использовать для визуализации формы сигнала для каждого момента времени. Он также напечатает значение каждого продукта и значение сигнала состояния готово с их мгновенным значением времени.
Verilog Code:
module mul_test_bench; reg [15:0] data_in; reg clk, start; wire done; datapath DP (eqz, LdA, LdB, LdP, clrP, decB, data_in, clk); controller CON (LdA, LdB, LdP, clrP, decB, done, clk, eqz, start); initial begin clk = 1'b0; #3 start = 1'b1; #500 $finish; end always #5 clk = ~clk; initial begin #17 data_in = 5; #10 data_in = 6; end initial begin $monitor($time, " %d %b", DP.y, done); $dumpfile("mul.vcd"); $dumpvars(0, mul_test_bench); end endmodule
Вывод:
Вывод консоли.
График сигналов.