9.4 Условное оператор if-else
Условный оператор (или оператор if-else) используется для принятия решения о том, будет ли выполняться оператор. Формально синтаксис приведен в Синтаксисе 9-4.
conditional_statement ::=
if ( expression )
statement_or_null [ else statement_or_null ]
| if_else_if_statement
Если выражение оценивается как true (то есть имеет ненулевое известное значение), то выполняется первый оператор. Если выражение равно false (то есть имеет нулевое значение или значение равно x или z), то первый оператор не выполняется. Если есть оператор else и выражение равно false, то выполняется оператор else.
if (expression)
if (expression != 0)
if (index > 0)
if (rega > regb)
result = rega;
else // else applies to preceding if
result = regb;
if (index > 0) begin
if (rega > regb)
result = rega;
end
else result = regb;
9.4.1 Конструкция if-else-if
Конструкция в синтаксисе 9-5 встречается настолько часто, что заслуживает отдельного краткого обсуждения:
if_else_if_statement ::= (From A.6.6)
if ( expression ) statement_or_null
{ else if ( expression ) statement_or_null }
[ else statement_or_null ]
Эта последовательность выражений if (известная как конструкция if-else-if) является наиболее общим способом написания многоходового решения. Выражения оцениваются по порядку. Если какое-либо выражение истинно, выполняется связанный с ним оператор, и на этом вся цепочка завершается. Каждое объявление — это либо одно объявление, либо блок объявлений.
Последняя else-часть конструкции if-else-if обрабатывает случай, когда ни одно из вышеперечисленных условий не было выполнено. Иногда для случая по умолчанию нет явного действия. В этом случае оператор else можно опустить, или использовать его для проверки ошибок, чтобы поймать невозможное условие.
Например:
// объявление регистров и параметров
reg [31:0] instruction, segment_area[255:0];
reg [7:0] index;
reg [5:0] modify_seg1,
modify_seg2,
modify_seg3;
parameter
segment1 = 0, inc_seg1 = 1,
segment2 = 20, inc_seg2 = 2,
segment3 = 64, inc_seg3 = 4,
data = 128;
// проверка индексной переменной
if (index < segment2) begin
instruction = segment_area [index + modify_seg1];
index = index + inc_seg1;
end
else if (index < segment3) begin
instruction = segment_area [index + modify_seg2];
index = index + inc_seg2;
end
else if (index < data) begin
instruction = segment_area [index + modify_seg3];
index = index + inc_seg3;
end
else
instruction = segment_area [index];
9.5 Оператор case
Оператор case — это многоходовой оператор принятия решений, который проверяет, соответствует ли выражение одному из нескольких других выражений, и соответствующим образом ветвится.
Синтаксис оператора case показан в Синтаксисе 9-6.
case_statement ::=
case ( expression )
case_item { case_item } endcase
| casez ( expression )
case_item { case_item } endcase
| casex ( expression )
case_item { case_item } endcase
case_item ::=
expression { , expression } : statement_or_null
| default [ : ] statement_or_null
Объявление default должно быть необязательным. Использование нескольких объявлений по default в одном объявлении case должно быть незаконным.
Выражение case и выражение элемента case могут быть вычислены во время выполнения. Ни одно из них не должно быть константным выражением.
Например:
reg [15:0] rega;
reg [9:0] result;
case (rega)
16'd0: result = 10'b0111111111;
16'd1: result = 10'b1011111111;
16'd2: result = 10'b1101111111;
16'd3: result = 10'b1110111111;
16'd4: result = 10'b1111011111;
16'd5: result = 10'b1111101111;
16'd6: result = 10'b1111110111;
16'd7: result = 10'b1111111011;
16'd8: result = 10'b1111111101;
16'd9: result = 10'b1111111110;
default result = 'bx;
endcase
Выражение case, указанное в круглых скобках, должно быть оценено ровно один раз и перед любым из выражений элементов case. Выражения элементов регистра должны быть оценены и сравнены в том порядке, в котором они приведены. Если имеется элемент case по умолчанию, он игнорируется во время линейного поиска. Во время линейного поиска, если одно из выражений элемента case соответствует выражению, указанному в круглых скобках, то выполняется оператор, связанный с этим элементом case, и линейный поиск завершается. Если все сравнения неудачны и задан элемент по умолчанию, то выполняется присваивание элемента по умолчанию. Если выражение по умолчанию не задано и все сравнения неудачны, то ни одно из выражений элемента case не будет выполнено.
Помимо синтаксиса, оператор case отличается от многоходовой конструкции if-else-if двумя важными моментами:
1) Условные выражения в конструкции if-else-if являются более общими, чем сравнение одного выражения с несколькими другими, как в операторе case.
2) Оператор case дает окончательный результат, когда в выражении есть значения x и z.
При сравнении выражений case сравнение будет успешным только тогда, когда каждый бит точно совпадает со значениями 0, 1, x и z. Как следствие, необходимо тщательно подходить к определению выражений в выражении case. Длина битов всех выражений должна быть одинаковой, чтобы можно было выполнить точное побитовое сравнение. Длина всех выражений элементов case, а также выражения в круглых скобках должна быть равна длине самого длинного выражения case и выражения элемента case. Если любое из этих выражений является беззнаковым, то все они должны рассматриваться как беззнаковые. Если все эти выражения являются знаковыми, то все они должны рассматриваться как знаковые.
Причина предоставления сравнения выражения случая, которое обрабатывает значения x и z, заключается в том, что оно обеспечивает механизм для обнаружения таких значений и уменьшения нежелательных случаев, который может быть порожден их присутствием.
Например:
case (select[1:2])
2'b00: result = 0;
2'b01: result = flaga;
2'b0x,
2'b0z: result = flaga ? 'bx : 0;
2'b10: result = flagb;
2'bx0,
2'bz0: result = flagb ? 'bx : 0;
default result = 'bx;
endcase
В этом примере, если select[1] равен 0 и flaga равен 0, то даже если значение select[2] равно x или z, результат должно быть равно 0, что решается третьим случаем.
case (sig)
1'bz: $display("signal is floating");
1'bx: $display("signal is unknown");
default: $display("signal is %b", sig);
endcase
9.5.1 Объявление case с условием обработки «не заботиться»
Два других типа объявлений case предусмотрены для обработки условий «не заботиться» в сравнениях case. Один из них рассматривает высокоимпедансные значения (z) как условия «не беспокоить», а другой рассматривает как высокоимпедансные, так и неизвестные (x) значения как условия «не беспокоить».
Объявление этих case можно использовать так же, как и традиционные объявление case, но они начинаются с ключевых слов casez и casex, соответственно.
Значения «не заботиться» (значения z для casez, значения z и x для casex) в любом бите либо выражения case, либо элементов case должны рассматриваться как условия «не заботиться» во время сравнения, и эта позиция бита должна не учитываются. Условия do-not-care в выражении case можно использовать для динамического управления тем, какие биты должны сравниваться в любой момент времени.
Синтаксис литеральных чисел позволяет использовать вопросительный знак (?) вместо z в объявлении случаев. Это обеспечивает удобный формат для указания битов «не беспокоить» в объявленных случая.
Например:
reg [7:0] ir;
casez (ir)
8'b1???????: instruction1(ir);
8'b01??????: instruction2(ir);
8'b00010???: instruction3(ir);
8'b000001??: instruction4(ir);
endcase
reg [7:0] r, mask;
mask = 8'bx0x0x0x0;
casex (r ^ mask)
8'b001100xx: stat1;
8'b1100xx00: stat2;
8'b00xx0011: stat3;
8'bxx010100: stat4;
endcase
9.5.2 Константные выражения в операторе case
Константное выражение может быть использовано для выражения регистра. Значение постоянного выражения должно сравниваться с выражениями элементов регистра.
Например:
reg [2:0] encode ;
case (1)
encode[2] : $display("Select Line 2") ;
encode[1] : $display("Select Line 1") ;
encode[0] : $display("Select Line 0") ;
default $display("Error: One of the bits expected ON");
endcase
В данном примере выражение case — это постоянное выражение (1). Элементы case являются выражениями (битовыми выборами) и сравниваются с постоянным выражением на предмет совпадения.
9.6 Циклические операторы
Существует четыре типа циклических операторов. Эти операторы позволяют управлять выполнением оператора ноль, один или несколько раз.
forever — Непрерывное выполнение оператора.
repeat — Выполняет оператор фиксированное количество раз. Если выражение оценивается как неизвестный или высокий импеданс, оно рассматривается как ноль, и оператор не выполняется.
while -Выполняет оператор до тех пор, пока выражение не станет ложным. Если выражение становится ложным, оператор не выполняется вообще.
for — Контролирует выполнение связанного с ним объявлений с помощью следующего трехэтапного процесса:
1) Выполняет назначение, обычно используемое для инициализации переменной, которая управляет количеством выполняемых циклов.
2) Оценивает выражение. Если результат равен нулю, цикл for завершается. Если результат не равен нулю, цикл for должен выполнить связанный с ним оператор(ы), а затем выполнить шаг c). Если выражение оценивается в неизвестное или высокоимпедансное значение, оно должно рассматриваться как ноль.
3) Выполняет назначение, обычно используемое для изменения значения переменной управления циклом, затем повторяет шаг b).
Синтаксис 9-7 показывает синтаксис для различных операторов цикла.
loop_statement ::=
forever statement
| repeat ( expression ) statement
| while ( expression ) statement
| for ( variable_assignment ; expression ; variable_assignment )
statement
В остальной части этого подраздела представлены примеры трех операторов цикла. Цикл forever должен использоваться только в сочетании с управлением синхронизацией или оператором disable. Поэтому этот пример представлен в разделе 9.7.2.
Например:
parameter size = 8, longsize = 16;
reg [size:1] opa, opb;
reg [longsize:1] result;
begin : mult
reg [longsize:1] shift_opa, shift_opb;
shift_opa = opa;
shift_opb = opb;
result = 0;
repeat (size) begin
if (shift_opb[1])
result = result + shift_opa;
shift_opa = shift_opa << 1;
shift_opb = shift_opb >> 1;
end
end
begin : count1s
reg [7:0] tempreg;
count = 0;
tempreg = rega;
while (tempreg) begin
if (tempreg[0])
count = count + 1;
tempreg = tempreg >> 1;
end
end
begin
initial_assignment;
while (condition) begin
statement
step_assignment;
end
end
for (initial_assignment; condition; step_assignment) statement