МАРСОХОД

Open Source Hardware Project

Язык описания аппаратуры Verilog HDL

Сумматор с переносом на Verilog HDL

Как на языке Verilog HDL реализовать сумматор или вычитатель с переносом ? Вопрос кажется очень простым для тех, кто давно использует язык Verilog, но почему-то оказывается абсолютно непонятным для новичков – это видно из писем, которые к нам приходят.

Все очень просто.
Вот такой код Verilog описывает модуль сумматора с переносом:


module adder(
  input wire [7:0]a,
  input wire [7:0]b,
  output wire [7:0]out,
  output wire carry
);

assign {carry, out} = a + b;

endmodule


Ключевая фраза здесь: assign {carry, out} = a + b;

Фигурные скобки описывают группу сигналов подключенных к выходу сумматора. В данном примере входные сигналы a и b восьмибитные. При суммировании восьмибитных чисел результат должен быть девятибитный. Так и в этом примере: выходной сигнал уже девятибитный и состоит из старшего бита carry, он слева внутри фигурных скобок, и восьмибитного результата out.


В этом легко убедиться если откомпилировать такой модуль в среде Altera Quartus II и посмотреть результат в RTLViewer:
Сумматор с переносом на Verilog
Проверить правильность работы сумматора можно написав простой тестбенч. Подаем на входы сумматора разные числа и смотрим результат:

`timescale 1ns / 1ns

module testbench;

reg [7:0]var_a;
reg [7:0]var_b;
wire [7:0]r_out;
wire r_carry;

//instance of module being studied
adder adder_inst(
  .a(var_a),
  .b(var_b),
  .out(r_out),
  .carry(r_carry)
);

initial
begin

  $dumpfile("out.vcd");
  $dumpvars(0,testbench);
  var_a = 8'h55;
  var_b = 8'h01;
   #10;
  var_a = 8'h55;
  var_b = 8'hAA;
   #10;
  var_a = 8'h55;
  var_b = 8'hAB;
   #10;
  var_a = 8'h99;
  var_b = 8'h05;
   #10;
  var_a = 8'h99;
  var_b = 8'h67;
   #10;
  var_a = 8'h99;
  var_b = 8'h66;
   #10;
  $finish;
end

endmodule


Откомпилировать оба модуля, сумматор и тестбенч, легко с помощью IcarusVerilog, в командной строке:

> iverilog –o qqq adder.v tb.v

Потом симулируем икарусом:

> vvp qqq

Получается выходной файл содержащий все сигналы проекта out.vcd. Эти сигналы можно детально рассмотреть в программе GtkWave:

Суммирование с переносом

Видно, что перенос возникает там где результат суммирования не укладывается в восемь бит. Например, при сложении чисел 0x55 и 0xAB.

Аналогично, легко описать вычитатель с переносом:


assign
{carry, out} = a - b;


Если carry и out описаны как регистры, а не wire, то используется такая конструкция:


reg carry;
reg [7:0]out;

always @*
begin
  { carry, out } = a + b ;
end



Здесь always @* обозначает «всегда», при любых изменениях любых сигналов.

Читайте другие статьи из раздела "Язык описания аппаратуры Verilog HDL".

Комментарии  

0 #5 vinill 17.02.2016 00:35
А как реализовать сумматор если задано 3 входа? И, скажем два из них представлены в формате десятичного числа
0 #4 UA3MQJ 09.10.2014 09:42
О!
{ carry, out } = a + b ;

Это же как операция матчинга в Erlang! Синтаксис 1 в 1 при работе с tuple.
http://www.erlang.org/course/sequential_programming.html#patterns

Старший бит "сматчится" в carry, а младшие в out.
0 #3 nckma 06.03.2013 07:39
Цитирую alman:
А сколько тактов будет выполняться это суммироввание?

В данном случае рассматривается сумматор как комбинационная функция. Ее быстродействие зависит от типа микросхемы. Из-за того, что функция комбинационная сигналов тактирования у нее, конечно, нет.
0 #2 alman 05.03.2013 20:29
А сколько тактов будет выполняться это суммироввание?
0 #1 nick17 05.03.2013 11:16
А можно еще более нагляднее и без "сцепления":
Сделать результирующий сигнал девятибитным. Девятый бит вывести как перенос.

Добавить комментарий


Защитный код
Обновить


GitHub YouTube Twitter
Вы здесь: Начало Verilog Сумматор с переносом на Verilog HDL