~ cd case verilog
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.
Рисунок 1. Временная диаграмма делителя 5.
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