Case — это оператор выбора, который сравнивает значение переменной или выражения со случаем перечисленным в нем для выполнения блока кода при удачном совпадении или в ином случае по умолчанию, если был прописан соответствующий оператор. Оператор начинается с ключевого слова case и заканчивается endcase. Помимо определенных случаев можно указать исполнение по умолчанию через ключевое слово default, если совпадений не было найдено.
Принцип работы оператора case изложен следующих пунктах:
1) Вычисляется значение выражения или переменной.
2) Найденное значение в порядке возрастание сравнивается с константами выражениями из заданного списка.
3) Если находится совпадение с одним из случаев, то исполняется блок кода, связанный с этим ним.
4) Когда совпадений не было обнаружено, исполняется оператор по умолчанию, следующие за ключевым словом default.
Объявление случаев с одинаковыми значениями или не моделируемыми переменными является ошибкой. Если битовая ширина сравниваемых значения не равна, то значение меньшей длины дополняется нулями в старших битах до одинаковой длины.
Синтаксис
Синтаксис объявления оператора выбора case c блоком выполнения по умолчанию default.
case (/* переменная или выражение */)
(/* случай 1 */): begin
// объявление кода
end
(/* случай 2 */): begin
// объявление кода
end
(/* случай 3 */): begin
// объявление кода
end
...
(/* случай n */): begin
// объявление кода
end
default: begin
// объявление кода
end
endcase
Примеры
Выбор оконечного устройства контроллером c сase
module kon(mosi, oena0, oena1, oena2, oena3, data, ena, clk);
parameter DW = 16; // битовая длина шин
input [(DW - 1): 0] data; // шина данных
input ena, clk; // сигнал включения и тактовый сигнал
output [(DW - 1): 0] mosi;// сигнал MOSI(Master Out Slave In)
// выходные сигналы включения интерфейса SPI
output oena0, oena1, oena2, oena3;
// с тирггером на выходе
reg oena0, oena1, oena2, oena3;
reg [(DW - 1): 0] addr; // адрес команды
reg ffbit; // флаг первого слова потока
reg [4:0] sch_we, sch_re; // счетчики
assign eram = ena & ~ffbit; // сигнал включения записи в память
// экземпляр модуля памяти
tram ram(data, clk, eram, sch_we, sch_re, mosi);
always @(posedge clk) begin
if (ena) begin
// обнуление
sch_re <= 0;
oena0 <= 0;
oena1 <= 0;
oena2 <= 0;
oena3 <= 0;
if (ffbit) begin
// первым словом ловим адресс
addr <= data;
ffbit <= 0;
end else begin
// увеличиваем счетчик записи
sch_we <= sch_we + 1;
end
end else begin
// обнуление
ffbit <= 1;
sch_we <= 0;
// выбор подчиненного устройства SPI
case (addr)
0: begin
// отправляет цап
oena0 <= 1;
end
1: begin
// отправляет Контроллеру PMBUS
oena1 <= 1;
end
2: begin
// отправляет КМБО
oena2 <= 1;
end
default: begin
// отправляет внутреннему регистру
oena3 <= 1;
end
endcase
// увелииваем счетчик чтения памяти
sch_re <= sch_re + 1;
end
end
endmodule
// память
module tram(data, clk, we, addr_we, addr_re, out);
parameter DW = 16;
parameter AW = 4;
input [(DW - 1): 0] data;
input [(AW - 1): 0] addr_we, addr_re;
input clk, we;
output reg [(DW - 1): 0] out;
reg [(DW - 1): 0] ram [(2**AW - 1): 0];
always @(posedge clk) begin
if (we)
ram[addr_we] <= data;
out = ram[addr_re];
end
endmodule
Делить тактовой частоты на 5 c сase
Делитель тактовой частоты на дробное число возможно организовать только с помощью построения собственного счетчика, которого невозможно прописать без оператора case. Также важным элементом является запаздывающий сигнал. Временная диаграмма показаны на рисунке 1.

module div5x0(out, sig, reset);
input sig; // тактовый сигнал
input reset; // асинхронный сброс
output out; // деленный тактовый сигнал
reg [2:0] sch = 1; // собственный счетчик
reg dl_sig = 0; // запаздывающий сигнал
always @(posedge sig, posedge reset) begin
if (reset) begin // сброс
sch <= 1;
end else begin // логика счетчика
case (sch)
1: sch <= 3;
3: sch <= 4;
4: sch <= 2;
2: sch <= 6;
6: sch <= 1;
default: sch <= 1;
endcase
end
end
always @(negedge sig, posedge reset) begin
if (reset) begin // сброс
dl_sig <= 0;
end else begin // логика запаздывающего сигнала
if (sch == 3) begin
dl_sig <= 1;
end else begin
dl_sig <= 0;
end
end
end
assign out = sch[0] | dl_sig;
endmodule