2 лаба GPT
.docxMASTER TB
Этот код на языке Verilog описывает тестовый бенч (testbench) для модуля master, который, вероятно, представляет собой часть системы для взаимодействия с внешней Flash-памятью. Давайте разберем основные части кода:
timescale 1ns / 1ps: Устанавливает временной масштаб для симуляции, где 1ns - единица времени, а 1ps - единица задержки.
module master_tb();: Определение тестового бенча с именем master_tb.
Параметры модуля:
PERIOD: Период тактового сигнала (предположительно, 12 единиц времени).
LEN, LEN_D_FLASH, LEN_ADRESS_FLASH, LEN_DATA_FLASH: Различные параметры длины данных, адреса и т.д.
Объявление сигналов:
logic clk: Сигнал тактового сигнала.
logic reset: Сигнал сброса.
logic [1:0] CS: Сигналы управления чипом Flash-памяти.
logic [3:0] address_for_flash: Сигнал адреса для доступа к Flash-памяти.
logic [255:0] data_buffer: Буфер данных.
Объявление и инициализация памяти Flash:
logic [256-1:0] FLASH [0:16-1]: Объявление массива Flash-памяти размером 256 бит, представляющего 16 слов памяти.
Присваивание данных в Flash-памяти:
assign FLASH[0] = 255'b11: Присваивание определенных данных в нулевую ячейку Flash-памяти.
Инициализация и подключение модуля master:
master dut (...): Подключение и инициализация модуля master, где передаются сигналы для взаимодействия.
Таким образом, этот тестовый бенч создает некоторые сигналы управления и данные для внешней Flash-памяти, инициализирует Flash-память и подключает модуль master для тестирования его работы в данном окружении.
TB SPI
Этот код на языке Verilog представляет собой тестовый бенч (testbench) для некоторой системы, включающей в себя модуль master_spi, работу с Flash-памятью (W25Q16), индикаторы семисегментного дисплея (74HC595), и взаимодействие с датчиком (MPU6000). Давайте рассмотрим основные элементы кода:
Параметры и объявление тестового бенча (tb_spi):
bits: Параметр, указывающий на длину битовых шин данных (32 бита по умолчанию).
Объявление различных сигналов, представляющих системные сигналы и данные для тестирования.
Модуль master_spi и его подключение:
master_spi dut (...): Подключение и инициализация модуля master_spi с использованием портов тестового бенча.
Генерация тактового сигнала (sys_clk):
always #2 sys_clk = !sys_clk;: Создание переключающегося тактового сигнала.
Инициализация системных сигналов и данных:
Инициализация тактового сигнала, сброса, данных и других системных сигналов перед началом тестирования.
Таск transact_test для взаимодействия с модулем master_spi:
Симулирует передачу данных между тестовым бенчем и модулем master_spi.
Имитация работы с датчиком MPU6000:
Инициализация массива REGS для эмуляции данных, считываемых из регистров датчика MPU6000.
Таск out_segm_task для работы с индикаторами 74HC595:
Эмулирует вывод данных на семисегментные индикаторы, преобразуя данные в семисегментный формат.
Имитация работы с Flash-памятью W25Q16:
Инициализация массива FLASH для эмуляции данных, считываемых и записываемых в Flash-память.
Инициализация данных для тестирования:
Запуск тестовых сценариев для взаимодействия с датчиком MPU6000, семисегментными индикаторами и Flash-памятью.
Завершение симуляции ($finish):
Завершение симуляции после завершения тестов.
timescale 1ns / 1ps
parameter bits = 32;
module tb_spi();
// Объявление различных сигналов тестового бенча
logic sys_clk;
logic t_start;
logic [bits-1:0] d_in;
logic [bits-1:0] d_out;
logic [$clog2(bits):0] t_size;
logic cs;
logic rstn;
logic spi_clk;
logic miso;
logic mosi;
// Подключение модуля master_spi и инициализация портов
master_spi dut (
.sys_clk(sys_clk),
.t_start(t_start),
.d_in(d_in),
.d_out(d_out),
.t_size(t_size),
.cs(cs),
.rstn(rstn),
.spi_clk(spi_clk),
.miso(miso),
.mosi(mosi)
);
// Присвоение miso значения mosi
assign miso = mosi;
// Создание переключающегося тактового сигнала
always #2 sys_clk = !sys_clk;
// Инициализация системных сигналов и данных
initial begin
sys_clk = 0;
t_start = 0;
d_in = 0;
rstn = 0;
t_size = bits;
#4;
rstn = 1;
end
// Таск для взаимодействия с модулем master_spi
task transact_test;
input [bits-1:0] data;
begin
d_in = data[bits-1:0];
#3 t_start = 1;
#4 t_start = 0;
for (integer i = 0; i < bits; i++) begin
#4;
end
#16;
end
endtask
// Имитация работы с датчиком MPU6000
logic [7:0] REGS [0:117];
initial begin
int data_reg;
parameter DATA_BITS_NUM = $bits(data_reg);
for (int reg_num = 0; reg_num < 118; reg_num++) begin
data_reg = $urandom();
REGS[reg_num] = data_reg[7:0];
end
end
logic [7:0] address_for_MPU_from_TB;
logic [7:0] address_for_MPU_from_fpga;
logic [7:0] result_MPU;
// Имитация работы с индикаторами 74HC595
logic notOE = 1'b1;
logic [2:0] addr = 3'b000;
logic [7:0] segments [0:7];
task out_segm_task;
input [63:0] data;
begin
if (notOE) begin
for (int i = 0; i < 8; i++) begin
segments[i] <= (data[i*8 +: 8] === 8'hxx) ? 8'b0 : data[i*8 +: 8];
end
end
end
endtask
// Имитация работы с Flash-памятью W25Q16
logic [31:0] FLASH [0:7];
initial begin
int data_flash;
parameter DATA_BITS_NUM = $bits(data_flash);
for (int flash_page = 0; flash_page < 8; flash_page++) begin
for (int flash_32_bit = 0; flash_32_bit < 32; flash_32_bit += DATA_BITS_NUM) begin
data_flash = $urandom();
FLASH[flash_page][flash_32_bit +: DATA_BITS_NUM] = data_flash;
end
end
end
// Дополнительные сигналы для работы с Flash-памятью W25Q16
logic [23:0] address_for_W25_from_TB;
logic [23:0] address_for_W25_from_fpga;
logic [31:0] result_W25;
// Запуск тестовых сценариев
initial begin
#10;
// Чтение данных из датчика MPU6000
address_for_MPU_from_TB = 8'b0111_0100;
transact_test({2'b00, address_for_MPU_from_TB});
address_for_MPU_from_fpga = d_out[7:0];
result_MPU = REGS[address_for_MPU_from_fpga];
#100;
// Вывод данных на семисегментные индикаторы
out_segm_task({2'b00, result_MPU});
#100;
// Чтение данных из Flash-памяти W25Q16
address_for_W25_from_TB = 24'b0000_0000_0000_0010;
transact_test({2'b01, address_for_W25_from_TB});
address_for_W25_from_fpga = d_out[23:0];
result_W25 = FLASH[address_for_W25_from_fpga];
#100;
// Вывод данных на семисегментные индикаторы
out_segm_task({2'b01, result_W25});
#100;
// Запись данных в Flash-память W25Q16
address_for_W25_from_TB = 24'b0000_0000_0000_0101;
transact_test({2'b10, address_for_W25_from_TB});
address_for_W25_from_fpga = d_out[23:0];
data_for_W25_from_TB = 32'b1001_0000_0000_0000_0000_0000_0000_0110;
transact_test({2'b11, data_for_W25_from_TB});
data_for_W25_from_fpga = d_out[31:0];
FLASH[address_for_W25_from_fpga] = data_for_W25_from_fpga;
result_W25 = FLASH[address_for_W25_from_fpga];
#100;
// Вывод данных на семисегментные индикаторы
out_segm_task({2'b10, result_W25});
#100;
$finish;
end
endmodule
MASTER SV
Данный код на языке Verilog представляет собой модуль master, который реализует работу с интерфейсом Serial Peripheral Interface (SPI) для взаимодействия с устройствами. Давайте разберем его построчно:
timescale 1ns / 1ps: Устанавливает масштаб времени для симуляции.
verilogCopy code
`include "defines.v"
Включает файл defines.v, который вероятно содержит макроопределения (define) для различных значений, таких как FLASH_MEMORY, MPU_GYRO, и REGISTER. Это позволяет более чисто структурировать код и использовать символические имена вместо числовых значений.
verilogCopy code
/
Комментарии, описывающие режим работы SPI (Mode 0) и характеристики тактовой последовательности.
verilogCopy code
module master
Определение модуля master с входами CLK (тактовый сигнал), nRST (сигнал сброса), CS (Chip Select), address_for_flash (адрес для работы с Flash-памятью) и data_from_flash (данные, считанные из Flash-памяти).
verilogCopy code
always_ff @(posedge CLK or negedge nRST) begin
Всегда активный блок, реагирующий на положительный фронт тактового сигнала или отрицательный фронт сброса. Если сброс активен, обнуляет данные.
verilogCopy code
case (CS)
Кейс-структура, зависящая от сигнала CS (Chip Select), который, вероятно, указывает на тип устройства, с которым взаимодействует SPI. В данном случае, обрабатывается случай FLASH_MEMORY. Здесь вы можете вставить код для взаимодействия с Flash-памятью в зависимости от конкретных условий.
verilogCopy code
en
Завершение определения модуля master.
MASTER SV
Этот код Verilog представляет собой описание модуля master_spi, который реализует интерфейс Serial Peripheral Interface (SPI). Давайте рассмотрим его построчно:
module master_spi
#(
parameter reg_width = 32,
parameter counter_width = $clog2(reg_width),
parameter reset = 0, idle = 1, load = 2, transact = 3, unload = 4
)
(
// System Side
input rstn,
input sys_clk,
input t_start,
input [reg_width-1:0] d_in,
input [counter_width:0] t_size,
output logic [reg_width-1:0] d_out,
// SPI Side
input miso,
output logic mosi,
output logic spi_clk,
output logic cs
);
Определение модуля master_spi с параметрами ширины регистра (reg_width), ширины счетчика (counter_width), исходного состояния и состояний (reset, idle, load, transact, unload). Он имеет входы и выходы для системной стороны (rstn, sys_clk, t_start, d_in, t_size, d_out) и стороны SPI (miso, mosi, spi_clk, cs).
Объявление внутренних сигналов для хранения предыдущих значений MOSI и MISO, счетчика и состояния. always @(state) begin
case (state)
// ...
endcase
end
Блок комбинаторной логики, который управляет состоянием конечного автомата в зависимости от текущего состояния.
always @(posedge sys_clk) begin
if (!rstn)
state = reset;
else
case (state)
// ...
endcase
end
Блок, реагирующий на положительный фронт системного тактового сигнала, определяющий переходы между состояниями в соответствии с логикой конечного автомата.
assign mosi = ( ~cs ) ? mosi_d[reg_width-1] : 1'bz;
assign spi_clk = ( state == transact ) ? sys_clk : 1'b0;
Присвоение значений MOSI и SPI Clock в зависимости от состояния и CS (Chip Select).
////
Обновление значения MISO при каждом положительном фронте SPI Clock во время транзакции.
always @(posedge spi_clk) begin
if ( state == transact )
miso_d <= {miso_d[reg_width-2:0], miso};
end
Обновление значения MOSI и уменьшение счетчика при каждом отрицательном фронте SPI Clock во время транзакции.
always @(negedge spi_clk) begin
if ( state == transact ) begin
mosi_d <= {mosi_d[reg_width-2:0], 1'b0};
count <= count-1;
end
end