Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Лабораторная работа №2
по курсу «ИУС на ПЛИС»
на тему:
«Логические интерфейсы и IP ядра»
Работу выполнил
студент группы ВТ-20
Лавриненко А.Д.
Москва 2013
Цель работы: Ознакомиться с инструментами языка Verilog HDL, позволяющими провести параметризацию. Оформить модуль, реализующий интерфейс UART, полученный в ходе выполнения лабораторной работы №1 в виде IP ядра.
Отчет
Рис. 1.1 Структурная схема IP ядра UART
Назначение. IP ядро UART предназначено для организации внешнего интерфейса обмена данными между внешним цифровым устройством и софт-процессором Microblaze по универсальной шине AXI с поддержкой интерфейса AXI4-Lite.
Характеристики:
- данные передаются последовательно по одному байту в сопровождении так называемых «стартового» и «стопового» битов (см. рис. 2.1) по двум независимым линиям rxd и txd приемника и передатчика модуля соответственно; в состоянии ожидания на линиях rxd и txd установлен логический уровень «0» ;
Рис. 2.1 Временная диаграмма обмена данными между внешним цифровым устройством и модулем интерфейса UART по независимым линиям rxd и txd
- поддерживаются следующие скорости обмена данными межу софт-процессором Microblaze и внешним цифровым устройством:
- поддержка универсального интерфейса AXI4-Lite;
- IP ядро UART slave-устройство на шине AXI.
Сигналы модуля и их назначение
Табл. 1 Сигналы IP ядра UART и их назначение
Имя сигнала |
Направление сигнала |
Разрядность |
Описание |
S_AXI_ACLK |
input |
1 |
Глобальная тактовая частота, по переднему фронту S_AXI_ACLK синхронизируются все сигналы |
S_AXI_ARSTN |
input |
1 |
Глобальный сигнал сброса. Активный уровень логический «0» |
S_AXI_AWADDR |
input |
32 |
Адрес (Memory Mapped) для записи данных в модуль IP ядра UART со стороны Master-устройства на шине AXI (процессора Microblaze) |
S_AXI_AWVALID |
input |
1 |
Сигнал подтверждения адреса S_AXI_AWADDR |
S_AXI_WDATA |
input |
32 |
Данные для записи в модуль IP ядра UART, выставленные Master-устройством на шине AXI |
S_AXI_WSTRB |
input |
4 |
Строб записи данных |
S_AXI_WVALID |
input |
1 |
Сигнал подтверждения данных для записи S_AXI_WDATA и строба записи данных S_AXI_WSTRB на шине |
S_AXI_BREADY |
input |
1 |
Сигнал готовности Master-устройства на шине AXI принимать ответную информацию |
S_AXI_ARADDR |
input |
32 |
Адрес (Memory Mapped) для чтения данных из модуля IP ядра UART со стороны Master-устройства на шине AXI (процессора Microblaze) |
S_AXI_ARVALID |
input |
1 |
Сигнал подтверждения адреса S_AXI_ARADDR |
S_AXI_RREADY |
input |
1 |
Сигнал готовности чтения данных или ответной информации Master-устройством на шине AXI |
S_AXI_ARREADY |
output |
1 |
Сигнал готовности адреса чтения. Указывает на то, что устройство модуля IP ядра UART (slave-устройство на шине AXI) готово принять адрес для чтения и сопровождающие управляющие сигналы |
S_AXI_RDATA |
output |
32 |
Данные для чтения из модуля IP ядра UART Master-устройством на шине AXI |
S_AXI_RRESP |
output |
2 |
Сигнал статуса операций чтения (известно 4 состояния сигнала S_AXI_RRESP: OKAY, EXOKAY, SLVERR, DECERR) |
S_AXI_RVALID |
output |
1 |
Сигнал подтверждения данных для чтения S_AXI_RDATA на шине AXI Master-устройством |
S_AXI_WREADY |
output |
1 |
Сигнал готовности устройства модуля IP ядра UART принять данные S_AXI_WDATA от Master-устройства |
S_AXI_BRESP |
output |
2 |
Сигнал статуса операций записи (известно 4 состояния сигнала S_AXI_RRESP: OKAY, EXOKAY, SLVERR, DECERR) |
S_AXI_BVALID |
output |
1 |
Сигнал подтверждения статуса операций записи S_AXI_BRESP |
S_AXI_AWREADY |
output |
1 |
Сигнал готовности адреса записи. Указывает на то, что устройство модуля IP ядра UART (slave-устройство на шине AXI) готово принять адрес для записи и сопровождающие управляющие сигналы |
rxd |
input |
1 |
Вход интерфейса UART |
txd |
output |
1 |
Выход интерфейса UART |
Настройка IP ядра UART и организация обмена данными между процессором Microblaze и внешним цифровым устройством, используя интерфейс UART
Система на базе процессора Microblaze с подключенным к ней разработанным IP ядром UART готова к работе.
Рис 3.1 Временная диаграмма обмена данными между процессором Microblaze и внешним цифровым устройством с использованием разработанного IP ядра UART
В процессе моделирования был рассмотрен следующий пример: процессор по шине AXI выставляет данные в адресуемый регистр управления slv_reg1(данные для передачи 8 младших разрядов регистра, сигнал начала передачи 8-й разряд регистра) для передачи внешнему устройству с помощью IP ядра UART. В файле тестовых воздействий выходной сигнал системы uart_ip_0_txd_pin (выход интерфейса UART) замкнут на входной uart_ip_0_rxd_pin (вход интерфейса UART).
В результате отрабатывается передача данных по линии uart_ip_0_txd_pin и прием по линии uart_ip_0_rxd_pin с задержкой в 1 такт системной частоты. Принятые данные записываются в младшие разряды адресуемого со стороны процессора регистра состояний slv_reg0, что и отображено на временной диаграмме.
// bit rate: 9600 kbit/sec
// clock : 100 MHz
module uart_top #(parameter FREQ = 100,
parameter RATE = 1,
parameter MAJ_DIV = 128)
(
input clock,
input reset_n,
input data_tx,
output data_recieved,
input trans_en,
output rec_succ,
output error,
output uart_busy,
input rxd,
output txd
);
wire clock;
wire reset_n;
wire [7:0] data_tx;
reg [7:0] data_recieved;
wire trans_en;
reg rec_succ;
reg error;
reg uart_busy;
wire rxd;
wire txd;
// LOCAL PARAMETERS
// FREQ is in MHz
// if FREQ = 100, real frequency is 100 MHz (100 000 000 Hz)
// real rate = 9600*RATE;
// if RATE = 2, real rate is 19200 bod/sec
localparam CNT_PULSES = (FREQ*1000000)/(9600*RATE);
// shift reg for TX
reg [9:0] tx_reg;
reg [13:0] tx_cnt;
reg [1:0] state_tx;
// shift reg for RX
reg [9:0] rx_reg;
reg [13:0] rx_cnt;
reg [1:0] state_rx;
reg [3:0] tx_cnt_bits;
reg [3:0] rx_cnt_bits;
reg rx_maj;
assign txd = tx_reg[0];
majority_scheme #(CNT_PULSES, MAJ_DIV)
majority_scheme_inst(
.clock(clock),
.reset_n(reset_n),
.rx_maj(rx_maj),
.rx_cnt(rx_cnt),
.maj_out_bit(maj_out_bit)
);
always @(posedge clock or negedge reset_n)
if (~reset_n)
begin
tx_reg <= 0;
rx_reg <= 0;
rx_cnt <= 0;
tx_cnt <= 0;
state_tx <= 0;
state_rx <= 0;
uart_busy <= 0;
data_recieved <= 0;
rec_succ <= 0;
rx_maj <= 0;
tx_cnt_bits <= 0;
rx_cnt_bits <= 0;
error <= 0;
end
else
begin
// One pulse
rec_succ <= 0;
// Transmitter
case (state_tx)
// idle
0: begin
if (trans_en)
state_tx <= 1;
end
// register data to transmit
1: begin
uart_busy <= 1;
tx_reg[8:1] <= data_tx;
tx_reg[9] <= 0; // stop bit
tx_reg[0] <= 1; // start bit
state_tx <= 2;
end
// transmit 10 bits
2: begin
if (tx_cnt == 10417)
begin
tx_cnt <= 0;
tx_reg[8:0] <= tx_reg[9:1];
tx_reg[9] <= 0;
tx_cnt_bits <= tx_cnt_bits + 1;
if (tx_cnt_bits == 9)
begin
state_tx <= 0;
uart_busy <= 0;
tx_cnt_bits <= 0;
end
end
else
tx_cnt <= tx_cnt + 1;
end
endcase
// Reciever
case (state_rx)
// idle
0: begin
if (rxd)
state_rx <= 1;
end
// recieve 10 bits
1: begin
rx_maj <= rxd;
if (rx_cnt_bits == 10)
begin
state_rx <= 2;
rx_cnt_bits <= 0;
end
if (rx_cnt == CNT_PULSES)
begin
rx_cnt <= 0;
rx_reg[9] <= maj_out_bit;
rx_reg[8:0] <= rx_reg[9:1];
rx_cnt_bits <= rx_cnt_bits + 1;
end
else
rx_cnt <= rx_cnt + 1;
end
// register recieved data
2: begin
data_recieved <= rx_reg[8:1];
if (~rx_reg[9])
rec_succ <= 1;
else
error <= 1;
state_rx <= 0;
end
endcase
end
endmodule
module majority_scheme #(parameter CNT_PULSES = 1,
parameter MAJ_DIV = 2)
(
// System
input wire clock,
input wire reset_n,
input wire [13:0] rx_cnt,
input wire rx_maj,
output reg maj_out_bit
);
localparam MIN_CNT_ONES = CNT_PULSES/(64*MAJ_DIV);
reg [2:0] cnt_ones;
always @(posedge clock or negedge reset_n)
if (~reset_n)
begin
maj_out_bit <= 0;
cnt_ones <= 0;
end
else
begin
if (rx_cnt[MAJ_DIV + 5:0] == 7'b0000000)
begin
if (rx_maj)
cnt_ones <= cnt_ones + 1;
else
cnt_ones <= cnt_ones + 0;
end
if (cnt_ones > MIN_CNT_ONES && rx_cnt == CNT_PULSES - 1)
begin
maj_out_bit <= 1;
cnt_ones <= 0;
end
else if (cnt_ones <= MIN_CNT_ONES && rx_cnt == CNT_PULSES - 1)
begin
maj_out_bit <= 0;
cnt_ones <= 0;
end
end
endmodule
`uselib lib=unisims_ver
`uselib lib=proc_common_v3_00_a
module user_logic
(
// -- ADD USER PORTS BELOW THIS LINE ---------------
// --USER ports added here
// -- ADD USER PORTS ABOVE THIS LINE ---------------
txd,
rxd,
// -- DO NOT EDIT BELOW THIS LINE ------------------
// -- Bus protocol ports, do not add to or delete
Bus2IP_Clk, // Bus to IP clock
Bus2IP_Resetn, // Bus to IP reset
Bus2IP_Data, // Bus to IP data bus
Bus2IP_BE, // Bus to IP byte enables
Bus2IP_RdCE, // Bus to IP read chip enable
Bus2IP_WrCE, // Bus to IP write chip enable
IP2Bus_Data, // IP to Bus data bus
IP2Bus_RdAck, // IP to Bus read transfer acknowledgement
IP2Bus_WrAck, // IP to Bus write transfer acknowledgement
IP2Bus_Error // IP to Bus error response
// -- DO NOT EDIT ABOVE THIS LINE ------------------
); // user_logic
// -- ADD USER PARAMETERS BELOW THIS LINE ------------
// --USER parameters added here
// -- ADD USER PARAMETERS ABOVE THIS LINE ------------
// -- DO NOT EDIT BELOW THIS LINE --------------------
// -- Bus protocol parameters, do not add to or delete
parameter C_NUM_REG = 2;
parameter C_SLV_DWIDTH = 32;
// -- DO NOT EDIT ABOVE THIS LINE --------------------
// -- ADD USER PORTS BELOW THIS LINE -----------------
// --USER ports added here
// -- ADD USER PORTS ABOVE THIS LINE -----------------
input rxd;
output txd;
// -- DO NOT EDIT BELOW THIS LINE --------------------
// -- Bus protocol ports, do not add to or delete
input Bus2IP_Clk;
input Bus2IP_Resetn;
input [C_SLV_DWIDTH-1 : 0] Bus2IP_Data;
input [C_SLV_DWIDTH/8-1 : 0] Bus2IP_BE;
input [C_NUM_REG-1 : 0] Bus2IP_RdCE;
input [C_NUM_REG-1 : 0] Bus2IP_WrCE;
output [C_SLV_DWIDTH-1 : 0] IP2Bus_Data;
output IP2Bus_RdAck;
output IP2Bus_WrAck;
output IP2Bus_Error;
// -- DO NOT EDIT ABOVE THIS LINE --------------------
//----------------------------------------------------------------------------
// Implementation
//----------------------------------------------------------------------------
// --USER nets declarations added here, as needed for user logic
// Nets for user logic slave model s/w accessible register example
reg [C_SLV_DWIDTH-1 : 0] slv_reg0;
reg [C_SLV_DWIDTH-1 : 0] slv_reg1;
wire [1 : 0] slv_reg_write_sel;
wire [1 : 0] slv_reg_read_sel;
reg [C_SLV_DWIDTH-1 : 0] slv_ip2bus_data;
wire slv_read_ack;
wire slv_write_ack;
integer byte_index, bit_index;
// USER logic implementation added here
// user lines
wire [7:0] data_tx ;
wire trans_en;
wire [7:0] data_recieved;
wire rec_succ;
wire uart_busy;
wire error;
wire txd;
wire rxd;
assign data_tx = slv_reg1[7:0];
assign trans_en = slv_reg1[8];
uart_top uart_top_inst(
.clock(Bus2IP_Clk),
.reset_n(Bus2IP_Resetn),
.data_tx(data_tx),
.data_recieved(data_recieved),
.trans_en(trans_en),
.rec_succ(rec_succ),
.error(error),
.uart_busy(uart_busy),
.rxd(rxd),
.txd(txd)
);
// ------------------------------------------------------
// Example code to read/write user logic slave model s/w accessible registers
//
// Note:
// The example code presented here is to show you one way of reading/writing
// software accessible registers implemented in the user logic slave model.
// Each bit of the Bus2IP_WrCE/Bus2IP_RdCE signals is configured to correspond
// to one software accessible register by the top level template. For example,
// if you have four 32 bit software accessible registers in the user logic,
// you are basically operating on the following memory mapped registers:
//
// Bus2IP_WrCE/Bus2IP_RdCE Memory Mapped Register
// "1000" C_BASEADDR + 0x0
// "0100" C_BASEADDR + 0x4
// "0010" C_BASEADDR + 0x8
// "0001" C_BASEADDR + 0xC
//
// ------------------------------------------------------
assign
slv_reg_write_sel = Bus2IP_WrCE[1:0],
slv_reg_read_sel = Bus2IP_RdCE[1:0],
slv_write_ack = Bus2IP_WrCE[0] || Bus2IP_WrCE[1],
slv_read_ack = Bus2IP_RdCE[0] || Bus2IP_RdCE[1];
// implement slave model register(s)
always @( posedge Bus2IP_Clk )
begin
if ( Bus2IP_Resetn == 1'b0 )
begin
slv_reg0 <= 0;
slv_reg1 <= 0;
end
else
begin
slv_reg0[7:0] <= data_recieved;
slv_reg0[8] <= rec_succ;
slv_reg0[9] <= uart_busy;
slv_reg[10] <= error;
case ( slv_reg_write_sel )
2'b10 :
for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
if ( Bus2IP_BE[byte_index] == 1 )
slv_reg0[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
2'b01 :
for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
if ( Bus2IP_BE[byte_index] == 1 )
slv_reg1[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
default : begin
slv_reg0 <= slv_reg0;
slv_reg1 <= slv_reg1;
end
endcase
end
end // SLAVE_REG_WRITE_PROC
// implement slave model register read mux
always @( slv_reg_read_sel or slv_reg0 or slv_reg1 )
begin
case ( slv_reg_read_sel )
2'b10 : slv_ip2bus_data <= slv_reg0;
2'b01 : slv_ip2bus_data <= slv_reg1;
default : slv_ip2bus_data <= 0;
endcase
end // SLAVE_REG_READ_PROC
// ------------------------------------------------------------
// Example code to drive IP to Bus signals
// ------------------------------------------------------------
assign IP2Bus_Data = (slv_read_ack == 1'b1) ? slv_ip2bus_data : 0 ;
assign IP2Bus_WrAck = slv_write_ack;
assign IP2Bus_RdAck = slv_read_ack;
assign IP2Bus_Error = 0;
endmodule
Приложение 1. Создание проекта в Xilinx Platform Studio
1. Создание проекта в Xilinx Platform Studio
Запустите программу XPS
Из предложенных вариантов выберите «Create New Base System»
Укажите рабочую директорию для нового проекта. В качестве системной шины укажите «AXI System».
Укажите настройки ПЛИС, например:
Architecture: spartan6
Device: xc6slx45t
Package: fgg484
Speed Grade: -3
Reference Clock Frequency: 100 Mhz
Reset Polarity: Active High
Optimization Strategy: Area
Завершите создание проекта.
2. Добавление пользовательской периферии
Добавьте в проект пользовательскую периферию:
Следуйте указанием мастера создания периферии.
В качестве интерфейса выберите «AXI4-Lite»
Отметьте галочкой пункт «User logic software register»
Укажите необходимое количество адресуемых регистров.
Отметьте галочкой пункт «Generate BPM simulation platform»
Отметьте галочками все пункты (Создать проект ISE, Создать шаблон драйвера, Описывать пользовательскую логику на HDL Verilog)
Следуя указаниям мастера создания пользовательской периферии, завершите ее создание.