Понимание скаляров и векторов в Verilog: биты, регистры и типы сетей
Verilog должен представлять отдельные биты и группы бит. Например, однобитный последовательный элемент — триггер. А 16-битный — регистр, хранящий 16 бит. Для этого Verilog имеет скалярные и векторные сети и переменные.
Скаляр и вектор
Объявление net или reg без диапазона считается 1-битным — скаляр. Если указан диапазон — это многобитная сущность, вектор.
wire o_nor; // скалярная сеть 1 бит
wire [7:0] o_flop; // 8-битная векторная сеть
reg parity; // скалярная переменная 1 бит
reg [31:0] addr; // 32-битная векторная переменная для адреса
Диапазон позволяет адресовать отдельные биты вектора. Старший бит (MSB) указывается слева в диапазоне, младший (LSB) — справа.
wire [msb:lsb] name;
integer my_msb;
wire [15:0] priority; // msb=15, lsb=0
wire [my_msb: 2] prior; // недопустимо: msb/lsb должны быть константными выражениями
Создаётся 16-битная сеть priority. MSB и LSB должны быть константными выражениями, не переменными. Но могут быть любыми целыми — положительными, отрицательными или нулём; LSB может быть больше, равен или меньше MSB.
Выбор бита (Bit-selects)
Любой бит векторной переменной можно выбрать и присвоить новое значение — это bit-select. Если бит-селект выходит за границы или равен x/z, возвращается x.
reg [7:0] addr; // 8-битный reg [7,6,5,4,3,2,1,0]
addr[0] = 1; // присвоить 1 биту 0
addr[3] = 0; // присвоить 0 биту 3
addr[8] = 1; // недопустимо: бита 8 не существует
Выбор части (Part-selects)
Можно выбрать диапазон смежных бит — part-select. Два типа: с константным и с индексным part-select.
reg [31:0] addr;
addr[23:16] = 8'h23; // биты 23..16 заменятся на 0x23 -> константный part-select
Переменный part-select удобен в циклах для выбора частей вектора. Начальный бит может варьироваться, но ширина должна быть константой.
[ +: ] // part-select инкрементируется от start-bit
[ -: ] // part-select декрементируется от start-bit
module des;
reg [31:0] data;
int i;
initial begin
data = 32'hFACE_CAFE;
for (i = 0; i < 4; i++) begin
$display ("data[8*%0d +: 8] = 0x%0h", i, data[8*i +: 8]);
end
$display ("data[7:0] = 0x%0h", data[7:0]);
$display ("data[15:8] = 0x%0h", data[15:8]);
$display ("data[23:16] = 0x%0h", data[23:16]);
$display ("data[31:24] = 0x%0h", data[31:24]);
end
endmodule
Simulation Log
ncsim> run data[8*0 +: 8] = 0xfe // ~ data [8*0+8 : 8*0] data[8*1 +: 8] = 0xca // ~ data [8*1+8 : 8*1] data[8*2 +: 8] = 0xce // ~ data [8*2+8 : 8*2] data[8*3 +: 8] = 0xfa // ~ data [8*3+8 : 8*3] data[7:0] = 0xfe data[15:8] = 0xca data[23:16] = 0xce data[31:24] = 0xfa ncsim: *W,RNQUIE: Simulation is complete.
Частые ошибки
module tb;
reg [15:0] data;
initial begin
$display ("data[0:9] = 0x%0h", data[0:9]); // Ошибка: Reversed part-select index expression ordering
end
endmodule
Verilog
- Освоение Verilog: полное руководство по проектированию цифровых схем
- Освоение конкатенации в Verilog: практическое руководство
- Понимание назначений в Verilog: типы, синтаксис и лучшие практики
- Блокирующие и неблокирующие назначения в Verilog: ключевые различия
- Мастерство функций в Verilog для эффективного RTL дизайна
- Понимание задач (Tasks) в Verilog: отличия от функций, синтаксис и применение
- Межназначенные и внутриназначенные задержки в Verilog: понимание и применение
- Генератор тактового сигнала в Verilog: проектирование и реализация
- Мастерство математических функций Verilog для эффективного аппаратного дизайна
- Мастерство $timeformat в Verilog: точность и контроль отображения времени