|
|
1 år sedan | |
|---|---|---|
| .. | ||
| readme.md | 1 år sedan | |
//Verilog 2001 Style
module Top (
input Rst_i,
input Clk_i,
output Led_o
);
//Verilog 1995 Style
module Top (Rst_i, Clk_i, Led_i);
input Rst_i;
input Clk_i;
output Led_o;
_i - вход
_o - выход
_io - вход/выход
_d1 - сигнал, задержанный на 1 такт
_d2 - сигнал, задержанный на 2 такта
ShReg - сдвиговый регистр, инициализируемый сигналом
reg dataValid;
reg dataValid_d1;
reg dataValid_d2;
always @(posedge Clk_i) begin
dataValid_d1 <= dataValid;
dataValid_d2 <= dataValid_d1;
end
reg [3:0] dataValidShReg;
always @(posedge Clk_i) begin
dataValidShReg <= {dataValidShReg[2:0], dataValid};
end
При сдвиге новой строки используется табуляция, между словами одной строки используются пробелы. В настройках используемого редактора необходимо в настройках Табуляции указать размер табуляции равный 4. Для улучшения читаемости кода, допускается использование табуляции между словами одной строки.
Имя сигнала сброса должно содержать в себе "Rst". Помимо этого в названии может отображаться дополнительная информация о полярности сигнала сброса, является он синхронным или асинхронным, локальным или глобальным и т.п. Например:
input Rst_i, // simple reset definition
input RstGlbl_i, // global reset
input RstAsync_i // asynchronous reset
Имя тактового сигнала должно содержать в себе "Clk". Помимо этого в названии может отображаться дополнительная информация о тактовой частоте, является ли сигнал однополярным или дифференциальным и т.п.
input Clk_i, // simple clock definition
input Clk50Mhz_i, // 50 MHz clk
input Clk_pi, Clk_ni, //differential clock
Служебные входы (сигналы сброса и тактовые сигналы) обычно объявляются в начале списка портов модуля. Исключение составляют случаи, когда эти сигналы являются неотъемлемой частью функциональной или логической группы сигналов (например, шина AXI содержит в себе и тактовый сигнал, и сигнал сброса, которые следует объявить рядом с остальными сигналами этой шины).
Порты модуля могут образовывать функциональные или логические группы:
Такие группы следует:
Например:
module spi (
input Rst_i,
input Clk_i,
input [7:0] DataToSpi_i,
input DataToSpiNd_i,
output [7:0] DataFromSpi_o,
output DataFromSpiValid_o,
output SpiClk_o,
output SpiMosi_o,
output SpiCs_o,
input SpiMiso_i
);
По умолчанию - активным уровнем сигнала считаем '1'. Исключением являются случаи использования стандартизированных интерфейсов, интерфейсов IP-ядер и т.п.
Архитектура ПЛИС подразумевает работу преимущественно в рамках правил синхронного дизайна, которые включают следующее:
Во избежание некорректной привязки блока else условного оператора if всегда обрамляем блоки кода в if-блоке на уровнях выше самого низкого границами begin end. Например:
if (condition1) begin
if (condition2) begin
doSomething;
end
end else begin
if (condition3) begin
if (condition4) begin
doSomething;
end else begin
doSomething;
end
end else begin
doSomething;
end
end
Для упрощения переносимости/повторного использования кода между различными семействами ПЛИС одного производителя или между ПЛИС разных производителей рекомендуется там, где это допустимо, использовать синтезируемое соответствующим образом описание примитивов. В основном это относится к аппаратным умножителям и блоковой памяти. Например, для описания двухпортовой памяти с одним портом на запись и одним на чтение с независимыми тактовыми сигналами вместо явного объявления BRAM можно использовать описание вида:
parameter DataWidth = 36;
parameter AddrWidth = 10;
reg [RAM_WIDTH-1:0] ramBlock[(2**AddrWidth)-1:0];
reg [RAM_WIDTH-1:0] dataOut;
wire [AddrWidth-1:0] addrA, addrB;
wire [DataWidth-1:0] inDataA;
wire [DataWidth-1:0] outDataB;
wire wrEnA;
always @(posedge clkA) begin
if (wrEnA) begin
ramBlock[addrA] <= inDataA;
end
end
always @(posedge clkB) begin
outDataB <= ramBlock[addrB];
end
Также, вместо явного описания блока DSP, используемого для простого умножения двух 18-битных знаковых чисел, можно применить следующее описание:
wire signed [17:0] aIn;
wire signed [17:0] bIn;
reg signed [35:0] p;
always @(posedge <clock>) begin
p <= aIn * bIn;
end
Замечание: При использовании описанного подхода необходимо удостовериться:
Замечание: В случае невозможности использования неявного описания примитивов допустимо использовать явное их описание. Для упрощения переносимости кода рекомендуется обернуть описание этого примитива промежуточным модулем-оберткой (wrapper) с интерфейсом, содержащим входы и выходы логически и функционально значимые для описываемого блока. Например, если мы описываем таким образом блок умножителя:
module multiplierWrapper (
input Rst_i,
input Clk_i,
input signed [17:0] A_i,
input signed [17:0] B_i,
output signed [35:0] P_o
);
DSP48A1 # (
//...
//Parameters definition
//...
) dsp48Inst (
//...
//Port connections
//...
);
endmodule
Такой подход при переходе на другую архитектуру позволяет просто заменить блок с аппаратным примитивом на аналогичный для новой архитектуры ПЛИС без изменения интерфейса подключения.