МАРСОХОД

Open Source Hardware Project

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

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

Вот что написано в Википедии: "Mультиплексор — устройство, имеющее несколько сигнальных входов, один или более управляющих входов и один выход. Мультиплексор позволяет передать сигнал с одного из входов на выход; при этом выбор желаемого входа осуществляется подачей соответствующей комбинации управляющих сигналов".

На языке Verilog мультиплексор можно описать разными способами.
Самый простой способ - это с использованием конструкции if-else.


reg q;
always @*
  if(sel)
    q = a;
  else
    q = b;


Такой фрагмент кода Verilog можно представить в схемотехническом виде:

мультиплексор 2:1

Таким образом, на выходе q появится сигнал идентичный сигналу a, если sel=1. Если же сигнал sel=0, то на выходе q будет сигнал равный сигналу b. Вот временная диаграмма:

временная диаграмма мультиплексора

Альтернативой if-else в коде Verilog для простого мультиплексора 2:1 может быть использование оператора "?".


reg q;
always @*
  q = sel ? a : b;


Программа RTLViewer среды Altera Quartus отображает такую конструкцию точно так же, как и в случае с if-else.

Еще один способ представления мультиплексора с использованием оператора case:


always @*
  case(sel)
    0: q=b;
    1: q=a;
  endcase


Вообще-то конструкция с использованием case в Altera RTLViewer выглядит несколько иначе:

мультиплексор с оператором case

Тем не менее, логика работы остается абсолютно такой же. На самом деле на этой картинке изображен декодер один-к-двум и только один из его выходов (старший) используется для управления мультиплексором. Но ведь у конкретно этого декодера старший выход OUT[1]=sel. Так что, эта схема абсолютно такая же, как и представленная выше.

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


reg q;
always @*
  if(sel==2'b00)
    q=a;
  else
  if
(sel==2'b01)
    q=b;
  else
    q=c;


Схемотехническое представление этой конструкции вот такое:

мультиплексор три к одному

Вот его временная диаграмма:

временная диаграмма мультиплексора три к одному

То же самое можно сделать и с помощью конструкции языка Verilog case:


reg q;
always @*
begin
  case
(sel)
    2'b00: q = a;
    2'b01: q = b;
  default:
      q = c;
  endcase
end


Эта конструкция мультиплексора будет работать точно так же, как и с if-else-if-else.

Хотелось бы обратить внимание на один тонкий момент.
При написании кода на Verilog нужно учитывать все возможные варианты событий.
Вот, например, мультиплексор 3:1. Выходных сигналов три a, b и c, а управляющих сигналов два sel[1:0].
Раз сигналов селектора два, то значит всего они описывают четыре случая, а не три, как у нас.
В описанных выше примерах все сделано правильно: там вариант q=c выполняется в случае sel==2'b10 и sel=2'b11 (значения селектора 2 или 3).

Проблема состоит в том, что иногда, по невнимательности, можно написать "нехороший" код.
Вот пример такого "нехорошего" кода:


reg q;
always @*
  if(sel==2'b00)
    q=a;
  else
  if
(sel==2'b01)
    q=b;
  else
  if
(sel==2'b10) // <---- вот это явно лишняя строка!
    q=c;


Да, у нас вроде бы описан мультиплексор, но что произойдет когда селектор станет равным трем?
Этот случай мы не описали в коде. Синтезатор считает, что в случае с sel==2'b11 значение на выходе не должно меняться, должно оставаться предыдущим. Значит в логике появится latch (защелка) - это своего рода элемент памяти.

Вот что показывает Altera Quartus RTLViewer:

 нехороший мультиплексор

Вот допускать появление в проекте элементов latch очень не желательно. Их состояние в начальный момент времени не определено, их трудно тестировать и следовательно поведение проекта в конечном счете может стать не предсказуемым. Кстати и Quartus выдает предупреждение: "Verilog HDL Always Construct warning at <location>: inferring latch(es) for variable "<name>", which holds its previous value in one or more paths through the always construct". И далее следующее предупреждение: "Latch <name> has unsafe behavior".

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

 

Комментарии  

+1 #5 Владимир Хлуденьков 14.03.2014 11:21
Если из HTML вручную текст копировать - не очень удобно получается.
+3 #4 Владимир Хлуденьков 14.03.2014 11:20
Здравствуйте. А можно вот эти все примеры в pdf перевести? Уж очень хорошо всё у вас написано.

P. S. Я бы на вашем месте книгу бы издал. У вас написано лучше чем у многих авторов.
+1 #3 nckm_ 19.04.2011 16:01
Цитирую Pe3ucTop:
Вопрос:
У вас везде присвоение идёт регистру, это получается не мултиплексер, а защелка выбранного значения. Обоснуй те пожалуйста такую протеворечивость.
Ведь мультиплексер в чистом виде :
wire a,b,c;
assign c = (c and a) or (not c and b);

в Verilog тип reg это не всегда "устройство хранения" - триггер или защелка (latch). Этот факт всегда вызывает недоумение у начинающих (и у меня когда-то то же).
Самое простой и немного примитивный способ различения вот такой:
если присвоение регистру идет в блоке always @(posedge clk), то регистр действительно становится триггером (flop). Если присвоение регистру идет в блоке always @*,
то такой регистр никогда не станет триггером, а является скорее аналогом wire.
Что касается защелок (latch), то по моему мнению нужно стараться избегать их появления в проекте. От них только беда.
0 #2 Alexey 19.04.2011 15:56
Так у них в списке чувствительност и always все сигналы в том числе и асинхронные. Нет защелки потому что нет использования фронтов /спадов (срезов) сигналов.
-1 #1 Pe3ucTop 19.04.2011 13:49
Вопрос:
У вас везде присвоение идёт регистру, это получается не мултиплексер, а защелка выбранного значения. Обоснуй те пожалуйста такую протеворечивост ь.
Ведь мультиплексер в чистом виде :
wire a,b,c;
assign c = (c and a) or (not c and b);

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


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


GitHub YouTube Twitter
Вы здесь: Начало Verilog Мультиплексор