Как написать простой в обслуживании код Verilog?

внешний интерфейс
Как написать простой в обслуживании код Verilog?

Как мы все знаем, существует два основных языка описания оборудования (HDL), используемых для разработки FPGA:Верилог и VHDL, VHDL появился раньше, чем Verilog, и благодаря простоте синтаксиса и схожести с языком C Verilog широко используется крупными компаниями.

На самом деле я выучил язык VHDL в колледже. Позже, поскольку компания использовала Verilog, я снова выучил Verilog. К счастью, у меня есть основа языка C, и Verilog быстро начал работать.

Существуют три основные версии стандартных документов Verilog, а именно:Верилог-1995, Верилог-2001, Верилог-2005, опубликованы IEEE. Последним стандартом Verilog является версия 2005. По сравнению с двумя предыдущими версиями версия 2005 проще и гибче.

Хотя некоторые официальные коды, такие как некоторые основные коды IP Xilinx, по-прежнему основаны на стандарте Verilog-2001, чтобы быть совместимыми с предыдущими инструментами синтеза, я по-прежнему настоятельно рекомендую вам использовать последний стандарт Verilog-2005.

IEEE-2005

Таким образом, эта статья основана на стандарте синтаксиса IEEE-2005, а именно «IEEE P1364-2005/D3: проект стандарта для аппаратного обеспечения Verilog®. Язык описания" официальный стандартный документ. Посмотреть в конце статьиОфициальный стандартный документ IEEE-2005получить метод.

Хорошая спецификация кода может улучшить читаемость, возможность повторного использования, простоту и ясность кода, что также является проявлением профессионального качества.

наша цель:Write Nowhere, Read Everywhere

封面

Каково содержание?

  • название

    • именование файлов
    • наименование порта
    • именование переменных
    • наименование параметра
  • структура

    • весь кадр
    • портовая декларация
    • Пробелы и отступы делают код более понятным
    • Скобки улучшают читаемость
  • создавать экземпляр

  • Примечания

  • разное

  • Загрузка стандарта IEEE-2005

название

Именование в основном включает в себя имена файлов и модулей, имена портов, имена переменных, имена параметров и т. д. В двух словах:содержательно, коротко и легко читается, главное этоне используйте пиньинь!

именование файлов

Имя файла и имя модуля совпадают, и в один файл записывается только один модуль.

文件命名Имена файлов должны быть осмысленными, короткими и легко читаемыми.Используйте строчные буквы для имен файлов и разделяйте имена файлов символами подчеркивания.

  • Базовый модуль класса драйвера назван с использованиемdrv_xxxтип, например:drv_led.v,drv_i2c.v,drv_ad7606.v
  • Последовательный порт отправляет байт:uart_tx_byte.v
  • Асинхронный и синхронный FIFO, с указанием глубины и ширины:fifo_async_512_16.vиfifo_sync_256_64.v

Имя файла TestBench запрашивает имя исходного файла, за которым следует _tb, например, исходный файлdrv_led.v, соответствующий файл тестового стенда называетсяdrv_led_tb.v

Модули верхнего уровня единообразно именуются какtop.v,илиtop_project_name.v, например, верхний уровень примера проекта чтения и записи EEPROM называетсяtop_eeprom_demo.v

наименование порта

Именование портов такое же, как и имя файла, с однородным использованием строчных букв и разделением их символами подчеркивания.

Если это модуль верхнего уровня и подключен к фактическому выводу FPGA, добавьте_pad_i,_pad_o,_pad_ioчтобы назвать его, указывая, что он подключен к фактическому аппаратному выводу FPGA.

顶层端口命名

именование переменных

  • Унифицированное использование тактовых сигналовclkИмя, если это конкретная тактовая частота, вы можете добавить тактовую частоту после, напримерclk_50m
  • Сигнал сброса именуется сначала единообразно, если он активен на низком уровне, после него добавляется _n, напримерrst_n
  • Именование флаговых битов:flag_rise/flag_fall/flag_clr
  • Добавлено наименование зарегистрированного сигнала ударов_reg:reg rxd_reg
  • Добавить суффикс для именования регистров сдвига_sreg:reg [3:0] busy_sreg

Некоторые распространенные сокращения:

сокращение все заклинания значение
rst reset перезагрузить
clk clock Часы
rd read читать
wr write написать
addr address адрес
ack acknowledge отклик

Более распространенные аббревиатуры имен портов и переменных можно найти в следующих статьях:

blog.CSDN.net/сердечная ручка мечты…

наименование параметра

Параметры в Verilog аналогичны определениям в языке C, есть следующие две категории.localparamиparameter, разница между ними заключается в том, что первый не может передавать параметры во время создания экземпляра, а второй может передавать параметры во время создания экземпляра.

Для других переменных имена файлов все в нижнем регистре, только определения параметров имеютобработка всех заглавных букв, когда вам нужно определить некоторые константы, вы можете указать значимое имя через объявление параметра. как:

parameter LED_ON     = 1'b0;
parameter LED_OFF    = !LED_ON;
parameter BAUD_RATE  = 115200;
parameter TIME_100MS = 25_000_000;

Состояние конечного автомата обычно определяется с помощью localparam и указанием осмысленного имени, единообразно с использованием формата Sn_NAME и указанием разрядности. как:

localparam S0_IDLE  = 4'd0;
localparam S1_START = 4'd1;
localparam S2_DOING = 4'd2;
localparam S3_END   = 4'd3;

localparam S_FINISH = 4'd4;
localparam S_ERROR  = 'd5;//auto adaptive

структура

весь кадр

Рекомендуется, чтобы файл модуля Verilog был записан в следующей структуре.

/* 1.文件头: 说明版权信息,文件功能,作者,版本历史等 */
/* 2.端口声明: input/output/inout */
/* 3.宏定义: `define */
/* 4.参数定义: localparam/parameter */
/* 5.寄存器定义: reg */
/* 6.线网类型定义: wire */
/* 7.互联定义: assign */
/* 8.时序逻辑描述: always */

Пример:

/* 1.file head */

/***********************************************************
Copyright 2021 'wechat:mcu149'. All rights reserved.

FileName: drv_led.v
Function: led driver
Author  : mcu149
SVN     :
    SVN Revision: 1490
    SVN Date: 2021-06-05 19:49:49
Revision:
    2020-09-09: Rev 1.0
    2020-10-01: Rev 1.1
************************************************************/

/* 2.input/output/inout */
module drv_led(
    //Inputs
    input rst_n,
    input clk_50m,
    input en,
    
    //Outputs
    output led1,
    output reg led2 = 0      //define initial value is 0
);

/* 3.define */

/* 4.parameter/localparam */
parameter TIME_500MS = 32'd25_000_000;

/* 5.reg */
reg [31:0] cnt = 0;

/* 6.wire */
wire flag_toggle = (cnt == TIME_500MS);
    
/* 7.assign */
assign led1 = (en == 0) ? 0 : cnt[20];

/* 8.always block */
always @ (posedge clk_50m) begin
    if(!rst_n)
        cnt <= 0;
    else if(flag_toggle)
        cnt <= 0;
    else 
        cnt <= cnt + 1;
end

always @ (posedge clk_50m) begin
    if(!rst_n)
        led2 <= 0;
    else if(!en) 
        led2 <= 0;
    else if(en) begin
        if(flag_toggle)
            led2 <= !led2;
    end
end

endmodule

портовая декларация

Входные порты объединяются, выходные порты объединяются, а двунаправленные порты объединяются. Если выходному сигналу необходимо определить начальное значение, его можно указать непосредственно при определении порта, что также является новой функцией, добавленной в Verilog-2005.

端口命名

На этом этапе некоторые друзья могут быть разделены по функциям, например, по соединению одного и того же чипа.

Преимущество разделения ввода и вывода заключается в том, что при создании экземпляра легко различить, что является вводом, а что — выходом.

Пробелы и отступы делают код более понятным

  • Добавление пробела к обоим концам оператора может сделать структуру программы более понятной и читаемой.
  • Стиль отступа принимает стиль KR, то есть начало пишется в конце строки и не занимает отдельной строки, а конец занимает отдельную строку.
  • Отступ равномерно использовать 4 пробела вместо клавиши TAB
  • Если/else и другие операторы состоят только из одной строки, то begin-end можно не указывать.
  • Разумно добавляйте пустые строки, чтобы различать блоки, и разделяйте разные всегда блоки символами новой строки.

Ниже приведены спецификации написания этих двух кодов: Разумные отступы и разумное увеличение пробелов значительно повышают удобочитаемость.

合理缩进

Скобки улучшают читаемость

В школе есть несколько экзаменационных вопросов, чтобы проверить владение учениками различными операторскими приоритетами, даны некоторые античеловеческие вопросы.

Выполнение практического проекта не похоже на экзамен, преследуется читабельность и простота использования, поэтому при использовании нескольких операторов, чтобы повысить читаемость и избежать двусмысленности, не скупитесь на скобки для обозначения приоритета операций.

运算符优先级

создавать экземпляр

Создание экземпляра можно рассматривать как душу разработки FPGA.Процесс создания экземпляра на самом деле является процессом вызова аппаратного модуля.Например, мы используем Verilog для описания модуля декодера 3-8, который можно использовать в разных местах (создание экземпляра) он , и названные ut0/ut1/ut2 и т. д., а также могут указывать параметры во время создания экземпляра, такие как модули отправки и получения последовательного порта, для достижения совместимости с различными скоростями передачи данных путем указания разных параметров.

  • Порядок создания экземпляра и объявления порта согласован, входные порты размещаются вместе, а выходные порты размещаются вместе.
  • Для многобитных сигналов необходимо указывать ширину в битах при создании экземпляра для повышения удобочитаемости.
  • Модуль верхнего уровня только создает экземпляр модуля и не записывает никаких операторов управления.

Пример:

wire [7:0] rx_data;
wire rx_done;
wire rx_err;

/* 串口接收1字节 */
uart_rx_byte #(
    .BAUD_RATE(32'd115200),
    .EN_PARITY(2'd0),  //0:无校验位, 1:奇校验, 2:偶校验
    .EN_STOP_2(1'b0)   //1:使能2位停止位
)uart_rx_byte_0(
    // Inputs
    .clk(clk_32m),
    .rst_n(rst_n),
    .rxd(uart_rxd),

    // Outputs
    .data_rx(rx_data[7:0]),	//指定位宽
    .done(rx_done),
    .err(rx_err)
);

Примечания

Не верьте, какой код является лучшим комментарием! Я не отрицаю, что код некоторых людей написан очень хорошо, с разумными именами и понятным форматом.

Но я не думаю, что вы дошли до того момента, когда нет гарантии, что каждый сможет прочитать некомментированный код. Комментарии предназначены не только для просмотра другими, но и для них самих.Хорошая память не так плоха, как плохое письмо.

Унифицированное использование аннотаций/**/аннотацию или используйте//Смешанное использование, см. личные привычки!

  • Функция переменной должна быть аннотирована после каждого определения переменной.
  • Каждая всегда блокирующая функция требует комментария
  • Значение состояния конечного автомата должно быть аннотировано
  • Комментарии должны быть добавлены после условного оператора
  • Модификация кода, комментарии также должны быть изменены соответствующим образом

разное

  • Разумное использование generate for может определять и создавать экземпляры модулей в пакетах, уменьшая объем кода и улучшая читаемость.
  • Использование задач и функций в тестовом стенде может повысить эффективность
  • Операция сдвига заменена операцией сращивания и заполнения 0, которая легче читается.
  • Последовательная логика единообразно использует неблокирующее присваивание, то есть<=символ
  • Строка символов не должна превышать 80 символов. Если она слишком длинная, ее следует обработать переносом
  • Сначала существует дизайн верхнего уровня, а затем функции подмодуля разделяются, или подход снизу вверх.
  • Модульная конструкция для улучшения возможности повторного использования модуля
  • Старайтесь не использовать if/else, если вы можете использовать case
  • переменная типа reg, проверьте, защелкивается ли она по мере необходимости

Загрузка стандарта IEEE-2005 Verilog

Обратите внимание на общедоступную учетную запись (ID: обучение разработке электронных схем) справочный ответ [Стандарт Verilog】ПолучатьIEEE_Verilog_1364_2005.pdfСтандартный документ.

Отрицательный пример спецификации кода Verilog, вы можете обратиться к:Как написать код Verilog, который не могут поддерживать мои коллеги?