chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

利用開源uart2axi4實現(xiàn)串口訪問axi總線

FPGA設(shè)計論壇 ? 來源:CSDN技術(shù)社區(qū) ? 2025-12-02 10:05 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

1,引言

d523b792-cb63-11f0-8c8f-92fbcf53809c.png

圖 1 axi4-lite總線系統(tǒng)

如圖 1所示,《如何簡化axi4-lite slave接口開發(fā)》+《開源axi4_lite_interconnect介紹》介紹了axi4_lite_slave和axi4_lite_interconnect的內(nèi)部結(jié)構(gòu)和原理以及實現(xiàn)方法,這次我們介紹axi4_lite_master主機(jī)uart2axi4,這樣對整個axi4_lite系統(tǒng)框架構(gòu)成和實現(xiàn)就會有個系統(tǒng)性的認(rèn)識。

microblaze和jtag-to-axi(jtag2axi)雖然也提供了訪問axi總線的能力,但是依賴于xilinx平臺。而uart-to-axi(uart2axi4)橋接器并不依賴任何平臺,可以實現(xiàn)跨fpga平臺使用。利用uart2axi4我們可以通過python,輕松訪問axi4_lite_slave寄存器,大大方便fpga工程師進(jìn)行系統(tǒng)調(diào)試和定位bug。

2,uart2axi4

2.1 設(shè)計框架

d57edc26-cb63-11f0-8c8f-92fbcf53809c.png

圖 2 邏輯設(shè)計框架圖

如果想自己設(shè)計可以采樣上面的框架進(jìn)行設(shè)計:

PC端首先需要通過python進(jìn)行封包,請求包(PC→FPGA)采用TLV(type+len+value)格式進(jìn)行封包,type指示讀/寫操作,len指示讀/寫長度,value為寫數(shù)據(jù)。應(yīng)答包(FPGA→PC),寫應(yīng)答包指示FPGA寫操作完成,讀應(yīng)答包返回讀數(shù)據(jù)指示讀操作完成。

FPGA端uart2axi4需要包含的模塊:uart模塊完成串口數(shù)據(jù)接收和發(fā)送,tx_fifo和rx_fifo完成串口數(shù)據(jù)緩存,uart_parse模塊完成PC封包數(shù)據(jù)的解析,解析出完整一包后通過axi4_timing_gen模塊完成axi4時序產(chǎn)生。

2.2 開源uart2axi4介紹

開源網(wǎng)址:https://github.com/ultraembedded/core_dbg_bridge,該IP的內(nèi)部框圖可以參考圖 2。uart橋接出來的是axi4_full master接口,但是讀,寫突發(fā)長度固定為1,意味著如果寫8個字節(jié),就會發(fā)起2次突發(fā),由于uart速度本來就慢,所以這種設(shè)計也是沒有問題的。

數(shù)據(jù)包格式如下:

write操作

write_cmd(0x10) + len(byte為單位,寫數(shù)據(jù)長度) + addr[31:24] + addr[23:16] + addr[15:8] + addr[7:0] + d0[7:0] + d0[15:8] + d0[23:16] + d0[31:24]+ d1[7:0] + d1[15:8] + d1[23:16] + d1[31:24] + ...

注:如果len不是4的整數(shù)倍,則最后一拍會通過strb的mask操作寫入,地址是MSB→LSB,而數(shù)據(jù)是LSB→ MSB,寫操作沒有應(yīng)答包

read操作

read_cmd(0x11) + len(byte為單位,讀數(shù)據(jù)長度) + addr[31:24] + addr[23:16] + addr[15:8] + addr[7:0]

注:返回的數(shù)據(jù)格式為:d0[7:0] + d0[15:8] + d0[23:16] + d0[31:24] + d1[7:0] + d1[15:8] + d1[23:16] + d1[31:24] + ...

該項目還自帶了python程序,可以參考項目給的例子程序進(jìn)行驗證,并且可以很方面的進(jìn)行移植。

d5d80670-cb63-11f0-8c8f-92fbcf53809c.png

圖 3 python例子

2.3 如何使用

為了方便vivado打包時識別成axi接口,dbg_bridge.v修改如下:

//-----------------------------------------------------------------
// UART -> AXI Debug Bridge
// V1.0
// Ultra-Embedded.com
// Copyright 2017-2019
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------

//-----------------------------------------------------------------
// Generated File
//-----------------------------------------------------------------

module dbg_bridge
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
#(
parameter CLK_FREQ = 100_000_000
,parameter UART_SPEED = 115200
//,parameter AXI_ID = 4'd0
,parameter GPIO_ADDRESS = 32'hf0000000
,parameter STS_ADDRESS = 32'hf0000004
)
//-----------------------------------------------------------------
// Ports
//-----------------------------------------------------------------
(
input uart_rxd_i
,output uart_txd_o
,input [ 31:0] gpio_inputs_i
,output [ 31:0] gpio_outputs_o

,input m_axi_aclk
,input m_axi_aresetn

// write cmd
,input m_axi_awready
,output m_axi_awvalid
,output [ 31:0] m_axi_awaddr
,output [ 7:0] m_axi_awlen
//,output [ 3:0] mem_awid_o
,output [ 1:0] m_axi_awburst
// add by user
,output [ 2:0] m_axi_awsize
,output [ 2:0] m_axi_awprot
,output [ 3:0] m_axi_awcache
// write dat
,input m_axi_wready
,output m_axi_wvalid
,output [ 31:0] m_axi_wdata
,output [ 3:0] m_axi_wstrb
,output m_axi_wlast
// write bresp
,output m_axi_bready
,input m_axi_bvalid
,input [ 1:0] m_axi_bresp
//,input [ 3:0] mem_bid_i

// read dat
,input m_axi_rvalid
,output m_axi_rready
,input [ 31:0] m_axi_rdata
,input [ 1:0] m_axi_rresp
//,input [ 3:0] mem_rid_i
,input m_axi_rlast

// read cmd
,input m_axi_arready
,output m_axi_arvalid
,output [ 31:0] m_axi_araddr
//,output [ 3:0] mem_arid_o
,output [ 7:0] m_axi_arlen
,output [ 1:0] m_axi_arburst
// add by user
,output [ 2:0] m_axi_arsize
,output [ 2:0] m_axi_arprot
,output [ 3:0] m_axi_arcache
);

//-----------------------------------------------------------------
// Defines
//-----------------------------------------------------------------
localparam REQ_WRITE = 8'h10;
localparam REQ_READ = 8'h11;

`define STATE_W 4
`define STATE_R 3:0
localparam STATE_IDLE = 4'd0;
localparam STATE_LEN = 4'd2;
localparam STATE_ADDR0 = 4'd3;
localparam STATE_ADDR1 = 4'd4;
localparam STATE_ADDR2 = 4'd5;
localparam STATE_ADDR3 = 4'd6;
localparam STATE_WRITE = 4'd7;
localparam STATE_READ = 4'd8;
localparam STATE_DATA0 = 4'd9;
localparam STATE_DATA1 = 4'd10;
localparam STATE_DATA2 = 4'd11;
localparam STATE_DATA3 = 4'd12;

//-----------------------------------------------------------------
// Wires / Regs
//-----------------------------------------------------------------
wire uart_wr_w;
wire [7:0] uart_wr_data_w;
wire uart_wr_busy_w;

wire uart_rd_w;
wire [7:0] uart_rd_data_w;
wire uart_rd_valid_w;

wire uart_rx_error_w;

wire tx_valid_w;
wire [7:0] tx_data_w;
wire tx_accept_w;
wire read_skip_w;

wire rx_valid_w;
wire [7:0] rx_data_w;
wire rx_accept_w;

reg [31:0] mem_addr_q;
reg mem_busy_q;
reg mem_wr_q;

reg [7:0] len_q;

// Byte Index
reg [1:0] data_idx_q;

// Word storage
reg [31:0] data_q;

wire magic_addr_w = (mem_addr_q == GPIO_ADDRESS || mem_addr_q == STS_ADDRESS);

// add by user
wire clk_i;
wire rst_i;

assign clk_i = m_axi_aclk;
assign rst_i = ~m_axi_aresetn;

//-----------------------------------------------------------------
// UART core
//-----------------------------------------------------------------
dbg_bridge_uart
#( .UART_DIVISOR_W(32) )
u_uart
(
.clk_i(clk_i),
.rst_i(rst_i),

// Control
.bit_div_i((CLK_FREQ / UART_SPEED) - 1),
.stop_bits_i(1'b0), // 0 = 1, 1 = 2

// Transmit
.wr_i(uart_wr_w),
.data_i(uart_wr_data_w),
.tx_busy_o(uart_wr_busy_w),

// Receive
.rd_i(uart_rd_w),
.data_o(uart_rd_data_w),
.rx_ready_o(uart_rd_valid_w),

.rx_err_o(uart_rx_error_w),

// UART pins
.rxd_i(uart_rxd_i),
.txd_o(uart_txd_o)
);

//-----------------------------------------------------------------
// Output FIFO
//-----------------------------------------------------------------
wire uart_tx_pop_w = ~uart_wr_busy_w;

dbg_bridge_fifo
#(
.WIDTH(8),
.DEPTH(8),
.ADDR_W(3)
)
u_fifo_tx
(
.clk_i(clk_i),
.rst_i(rst_i),

// In
.push_i(tx_valid_w),
.data_in_i(tx_data_w),
.accept_o(tx_accept_w),

// Out
.pop_i(uart_tx_pop_w),
.data_out_o(uart_wr_data_w),
.valid_o(uart_wr_w)
);

//-----------------------------------------------------------------
// Input FIFO
//-----------------------------------------------------------------
dbg_bridge_fifo
#(
.WIDTH(8),
.DEPTH(8),
.ADDR_W(3)
)
u_fifo_rx
(
.clk_i(clk_i),
.rst_i(rst_i),

// In
.push_i(uart_rd_valid_w),
.data_in_i(uart_rd_data_w),
.accept_o(uart_rd_w),

// Out
.pop_i(rx_accept_w),
.data_out_o(rx_data_w),
.valid_o(rx_valid_w)
);

//-----------------------------------------------------------------
// States
//-----------------------------------------------------------------
reg [`STATE_R] state_q;
reg [`STATE_R] next_state_r;

always @ *
begin
next_state_r = state_q;

case (next_state_r)
//-------------------------------------------------------------
// IDLE:
//-------------------------------------------------------------
STATE_IDLE:
begin
if (rx_valid_w)
begin
case (rx_data_w)
REQ_WRITE,
REQ_READ:
next_state_r = STATE_LEN;
default:
;
endcase
end
end
//-----------------------------------------
// STATE_LEN
//-----------------------------------------
STATE_LEN :
begin
if (rx_valid_w)
next_state_r = STATE_ADDR0;
end
//-----------------------------------------
// STATE_ADDR
//-----------------------------------------
STATE_ADDR0 : if (rx_valid_w) next_state_r = STATE_ADDR1;
STATE_ADDR1 : if (rx_valid_w) next_state_r = STATE_ADDR2;
STATE_ADDR2 : if (rx_valid_w) next_state_r = STATE_ADDR3;
STATE_ADDR3 :
begin
if (rx_valid_w && mem_wr_q)
next_state_r = STATE_WRITE;
else if (rx_valid_w)
next_state_r = STATE_READ;
end
//-----------------------------------------
// STATE_WRITE
//-----------------------------------------
STATE_WRITE :
begin
if (len_q == 8'b0 && (m_axi_bvalid || magic_addr_w))
next_state_r = STATE_IDLE;
else
next_state_r = STATE_WRITE;
end
//-----------------------------------------
// STATE_READ
//-----------------------------------------
STATE_READ :
begin
// Data ready
if (m_axi_rvalid || magic_addr_w)
next_state_r = STATE_DATA0;
end
//-----------------------------------------
// STATE_DATA
//-----------------------------------------
STATE_DATA0 :
begin
if (read_skip_w)
next_state_r = STATE_DATA1;
else if (tx_accept_w && (len_q == 8'b0))
next_state_r = STATE_IDLE;
else if (tx_accept_w)
next_state_r = STATE_DATA1;
end
STATE_DATA1 :
begin
if (read_skip_w)
next_state_r = STATE_DATA2;
else if (tx_accept_w && (len_q == 8'b0))
next_state_r = STATE_IDLE;
else if (tx_accept_w)
next_state_r = STATE_DATA2;
end
STATE_DATA2 :
begin
if (read_skip_w)
next_state_r = STATE_DATA3;
else if (tx_accept_w && (len_q == 8'b0))
next_state_r = STATE_IDLE;
else if (tx_accept_w)
next_state_r = STATE_DATA3;
end
STATE_DATA3 :
begin
if (tx_accept_w && (len_q != 8'b0))
next_state_r = STATE_READ;
else if (tx_accept_w)
next_state_r = STATE_IDLE;
end
default:
;
endcase
end

// State storage
always @ (posedge clk_i or posedge rst_i)
if (rst_i)
state_q <= STATE_IDLE;
else
state_q <= next_state_r;

//-----------------------------------------------------------------
// RD/WR to and from UART
//-----------------------------------------------------------------

// Write to UART Tx buffer in the following states
assign tx_valid_w = ((state_q == STATE_DATA0) |
(state_q == STATE_DATA1) |
(state_q == STATE_DATA2) |
(state_q == STATE_DATA3)) && !read_skip_w;

// Accept data in the following states
assign rx_accept_w = (state_q == STATE_IDLE) |
(state_q == STATE_LEN) |
(state_q == STATE_ADDR0) |
(state_q == STATE_ADDR1) |
(state_q == STATE_ADDR2) |
(state_q == STATE_ADDR3) |
(state_q == STATE_WRITE && !mem_busy_q);

//-----------------------------------------------------------------
// Capture length
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
if (rst_i)
len_q <= 8'd0;
else if (state_q == STATE_LEN && rx_valid_w)
len_q[7:0] <= rx_data_w;
else if (state_q == STATE_WRITE && rx_valid_w && !mem_busy_q)
len_q <= len_q - 8'd1;
else if (state_q == STATE_READ && ((mem_busy_q && m_axi_rvalid) || magic_addr_w))
len_q <= len_q - 8'd1;
else if (((state_q == STATE_DATA0) || (state_q == STATE_DATA1) || (state_q == STATE_DATA2)) && (tx_accept_w && !read_skip_w))
len_q <= len_q - 8'd1;

//-----------------------------------------------------------------
// Capture addr
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
if (rst_i)
mem_addr_q <= 'd0;
else if (state_q == STATE_ADDR0 && rx_valid_w)
mem_addr_q[31:24] <= rx_data_w;
else if (state_q == STATE_ADDR1 && rx_valid_w)
mem_addr_q[23:16] <= rx_data_w;
else if (state_q == STATE_ADDR2 && rx_valid_w)
mem_addr_q[15:8] <= rx_data_w;
else if (state_q == STATE_ADDR3 && rx_valid_w)
mem_addr_q[7:0] <= rx_data_w;
// Address increment on every access issued
else if (state_q == STATE_WRITE && (mem_busy_q && m_axi_bvalid))
mem_addr_q <= {mem_addr_q[31:2], 2'b0} + 'd4;
else if (state_q == STATE_READ && (mem_busy_q && m_axi_rvalid))
mem_addr_q <= {mem_addr_q[31:2], 2'b0} + 'd4;

//-----------------------------------------------------------------
// Data Index
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
if (rst_i)
data_idx_q <= 2'b0;
else if (state_q == STATE_ADDR3)
data_idx_q <= rx_data_w[1:0];
else if (state_q == STATE_WRITE && rx_valid_w && !mem_busy_q)
data_idx_q <= data_idx_q + 2'd1;
else if (((state_q == STATE_DATA0) || (state_q == STATE_DATA1) || (state_q == STATE_DATA2)) && tx_accept_w && (data_idx_q != 2'b0))
data_idx_q <= data_idx_q - 2'd1;

assign read_skip_w = (data_idx_q != 2'b0);

//-----------------------------------------------------------------
// Data Sample
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
if (rst_i)
data_q <= 32'b0;
// Write to memory
else if (state_q == STATE_WRITE && rx_valid_w && !mem_busy_q)
begin
case (data_idx_q)
2'd0: data_q[7:0] <= rx_data_w;
2'd1: data_q[15:8] <= rx_data_w;
2'd2: data_q[23:16] <= rx_data_w;
2'd3: data_q[31:24] <= rx_data_w;
endcase
end
// Read from GPIO Input?
else if (state_q == STATE_READ && mem_addr_q == GPIO_ADDRESS)
begin
data_q <= {{(32-32){1'b0}}, gpio_inputs_i};
end
// Read from status register?
else if (state_q == STATE_READ && mem_addr_q == STS_ADDRESS)
data_q <= {16'hcafe, 15'd0, mem_busy_q};
// Read from memory
else if (state_q == STATE_READ && m_axi_rvalid)
data_q <= m_axi_rdata;
// Shift data out (read response -> UART)
else if (((state_q == STATE_DATA0) || (state_q == STATE_DATA1) || (state_q == STATE_DATA2)) && (tx_accept_w || read_skip_w))
data_q <= {8'b0, data_q[31:8]};

assign tx_data_w = data_q[7:0];

assign m_axi_wdata = data_q;

//-----------------------------------------------------------------
// AXI: Write Request
//-----------------------------------------------------------------
reg mem_awvalid_q;
reg mem_awvalid_r;

reg mem_wvalid_q;
reg mem_wvalid_r;

always @ *
begin
mem_awvalid_r = 1'b0;
mem_wvalid_r = 1'b0;

// Hold
if (m_axi_awvalid && !m_axi_awready)
mem_awvalid_r = mem_awvalid_q;
else if (m_axi_awvalid)
mem_awvalid_r = 1'b0;
// Every 4th byte, issue bus access
else if (state_q == STATE_WRITE && rx_valid_w && (data_idx_q == 2'd3 || len_q == 1))
mem_awvalid_r = !magic_addr_w;

// Hold
if (m_axi_wvalid && !m_axi_wready)
mem_wvalid_r = mem_wvalid_q;
else if (m_axi_wvalid)
mem_wvalid_r = 1'b0;
// Every 4th byte, issue bus access
else if (state_q == STATE_WRITE && rx_valid_w && (data_idx_q == 2'd3 || len_q == 1))
mem_wvalid_r = !magic_addr_w;
end

always @ (posedge clk_i or posedge rst_i)
if (rst_i)
begin
mem_awvalid_q <= 1'b0;
mem_wvalid_q <= 1'b0;
end
else
begin
mem_awvalid_q <= mem_awvalid_r;
mem_wvalid_q <= mem_wvalid_r;
end

assign m_axi_awvalid = mem_awvalid_q;
assign m_axi_wvalid = mem_wvalid_q;
assign m_axi_awaddr = {mem_addr_q[31:2], 2'b0};
//assign mem_awid_o = AXI_ID;
assign m_axi_awlen = 8'b0;
assign m_axi_awburst = 2'b01;
assign m_axi_wlast = 1'b1;

assign m_axi_bready = 1'b1;

// add by user
assign m_axi_awsize = 3'b010; // 000:1Byte 001:2Bytes 010:4Bytes 011:8Bytes 100:16Byte 101:32Bytes 110:64Bytes 111:128Bytes
assign m_axi_awprot = 3'b000; // 常規(guī)安全數(shù)據(jù)訪問
assign m_axi_awcache = 4'b0011; // 傳輸屬性

//-----------------------------------------------------------------
// AXI: Read Request
//-----------------------------------------------------------------
reg mem_arvalid_q;
reg mem_arvalid_r;

always @ *
begin
mem_arvalid_r = 1'b0;

// Hold
if (m_axi_arvalid && !m_axi_arready)
mem_arvalid_r = mem_arvalid_q;
else if (m_axi_arvalid)
mem_arvalid_r = 1'b0;
else if (state_q == STATE_READ && !mem_busy_q)
mem_arvalid_r = !magic_addr_w;
end

always @ (posedge clk_i or posedge rst_i)
if (rst_i)
mem_arvalid_q <= 1'b0;
else
mem_arvalid_q <= mem_arvalid_r;

assign m_axi_arvalid = mem_arvalid_q;
assign m_axi_araddr = {mem_addr_q[31:2], 2'b0};
//assign mem_arid_o = AXI_ID;
assign m_axi_arlen = 8'b0;
assign m_axi_arburst = 2'b01;

assign m_axi_rready = 1'b1;

// add by user
assign m_axi_arprot = 3'b000; // 常規(guī)安全數(shù)據(jù)訪問
assign m_axi_arcache = 4'b0011; // 傳輸屬性
assign m_axi_arsize = 3'b010; // 000:1Byte 001:2Bytes 010:4Bytes 011:8Bytes 100:16Byte 101:32Bytes 110:64Bytes 111:128Bytes


//-----------------------------------------------------------------
// Write mask
//-----------------------------------------------------------------
reg [3:0] mem_sel_q;
reg [3:0] mem_sel_r;

always @ *
begin
mem_sel_r = 4'b1111;

case (data_idx_q)
2'd0: mem_sel_r = 4'b0001;
2'd1: mem_sel_r = 4'b0011;
2'd2: mem_sel_r = 4'b0111;
2'd3: mem_sel_r = 4'b1111;
endcase

case (mem_addr_q[1:0])
2'd0: mem_sel_r = mem_sel_r & 4'b1111;
2'd1: mem_sel_r = mem_sel_r & 4'b1110;
2'd2: mem_sel_r = mem_sel_r & 4'b1100;
2'd3: mem_sel_r = mem_sel_r & 4'b1000;
endcase
end

always @ (posedge clk_i or posedge rst_i)
if (rst_i)
mem_sel_q <= 4'b0;
// Idle - reset for read requests
else if (state_q == STATE_IDLE)
mem_sel_q <= 4'b1111;
// Every 4th byte, issue bus access
else if (state_q == STATE_WRITE && rx_valid_w && (data_idx_q == 2'd3 || len_q == 8'd1))
mem_sel_q <= mem_sel_r;

assign m_axi_wstrb = mem_sel_q;

//-----------------------------------------------------------------
// Write enable
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
if (rst_i)
mem_wr_q <= 1'b0;
else if (state_q == STATE_IDLE && rx_valid_w)
mem_wr_q <= (rx_data_w == REQ_WRITE);

//-----------------------------------------------------------------
// Access in progress
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
if (rst_i == 1'b1)
mem_busy_q <= 1'b0;
else if (m_axi_arvalid || m_axi_awvalid)
mem_busy_q <= 1'b1;
else if (m_axi_bvalid || m_axi_rvalid)
mem_busy_q <= 1'b0;

//-----------------------------------------------------------------
// GPIO Outputs
//-----------------------------------------------------------------
reg gpio_wr_q;
reg [31:0] gpio_output_q;

always @ (posedge clk_i or posedge rst_i)
if (rst_i)
gpio_wr_q <= 1'b0;
else if (mem_addr_q == GPIO_ADDRESS && state_q == STATE_WRITE && rx_valid_w && (data_idx_q == 2'd3 || len_q == 1))
gpio_wr_q <= 1'b1;
else
gpio_wr_q <= 1'b0;

always @ (posedge clk_i or posedge rst_i)
if (rst_i)
gpio_output_q <= 32'h0;
else if (gpio_wr_q)
gpio_output_q <= data_q[31:0];

assign gpio_outputs_o = gpio_output_q;

endmodule

為了方便vivado打包時識別成axi接口,dbg_bridge.v修改如下

//-----------------------------------------------------------------
// UART -> AXI Debug Bridge
// V1.0
// Ultra-Embedded.com
// Copyright 2017-2019
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------

//-----------------------------------------------------------------
// Generated File
//-----------------------------------------------------------------

module dbg_bridge
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
#(
parameter CLK_FREQ = 100_000_000
,parameter UART_SPEED = 115200
//,parameter AXI_ID = 4'd0
,parameter GPIO_ADDRESS = 32'hf0000000
,parameter STS_ADDRESS = 32'hf0000004
)
//-----------------------------------------------------------------
// Ports
//-----------------------------------------------------------------
(
input uart_rxd_i
,output uart_txd_o
,input [ 31:0] gpio_inputs_i
,output [ 31:0] gpio_outputs_o

,input m_axi_aclk
,input m_axi_aresetn

// write cmd
,input m_axi_awready
,output m_axi_awvalid
,output [ 31:0] m_axi_awaddr
,output [ 7:0] m_axi_awlen
//,output [ 3:0] mem_awid_o
,output [ 1:0] m_axi_awburst
// add by user
,output [ 2:0] m_axi_awsize
,output [ 2:0] m_axi_awprot
,output [ 3:0] m_axi_awcache
// write dat
,input m_axi_wready
,output m_axi_wvalid
,output [ 31:0] m_axi_wdata
,output [ 3:0] m_axi_wstrb
,output m_axi_wlast
// write bresp
,output m_axi_bready
,input m_axi_bvalid
,input [ 1:0] m_axi_bresp
//,input [ 3:0] mem_bid_i

// read dat
,input m_axi_rvalid
,output m_axi_rready
,input [ 31:0] m_axi_rdata
,input [ 1:0] m_axi_rresp
//,input [ 3:0] mem_rid_i
,input m_axi_rlast

// read cmd
,input m_axi_arready
,output m_axi_arvalid
,output [ 31:0] m_axi_araddr
//,output [ 3:0] mem_arid_o
,output [ 7:0] m_axi_arlen
,output [ 1:0] m_axi_arburst
// add by user
,output [ 2:0] m_axi_arsize
,output [ 2:0] m_axi_arprot
,output [ 3:0] m_axi_arcache
);

//-----------------------------------------------------------------
// Defines
//-----------------------------------------------------------------
localparam REQ_WRITE = 8'h10;
localparam REQ_READ = 8'h11;

`define STATE_W 4
`define STATE_R 3:0
localparam STATE_IDLE = 4'd0;
localparam STATE_LEN = 4'd2;
localparam STATE_ADDR0 = 4'd3;
localparam STATE_ADDR1 = 4'd4;
localparam STATE_ADDR2 = 4'd5;
localparam STATE_ADDR3 = 4'd6;
localparam STATE_WRITE = 4'd7;
localparam STATE_READ = 4'd8;
localparam STATE_DATA0 = 4'd9;
localparam STATE_DATA1 = 4'd10;
localparam STATE_DATA2 = 4'd11;
localparam STATE_DATA3 = 4'd12;

//-----------------------------------------------------------------
// Wires / Regs
//-----------------------------------------------------------------
wire uart_wr_w;
wire [7:0] uart_wr_data_w;
wire uart_wr_busy_w;

wire uart_rd_w;
wire [7:0] uart_rd_data_w;
wire uart_rd_valid_w;

wire uart_rx_error_w;

wire tx_valid_w;
wire [7:0] tx_data_w;
wire tx_accept_w;
wire read_skip_w;

wire rx_valid_w;
wire [7:0] rx_data_w;
wire rx_accept_w;

reg [31:0] mem_addr_q;
reg mem_busy_q;
reg mem_wr_q;

reg [7:0] len_q;

// Byte Index
reg [1:0] data_idx_q;

// Word storage
reg [31:0] data_q;

wire magic_addr_w = (mem_addr_q == GPIO_ADDRESS || mem_addr_q == STS_ADDRESS);

// add by user
wire clk_i;
wire rst_i;

assign clk_i = m_axi_aclk;
assign rst_i = ~m_axi_aresetn;

//-----------------------------------------------------------------
// UART core
//-----------------------------------------------------------------
dbg_bridge_uart
#( .UART_DIVISOR_W(32) )
u_uart
(
.clk_i(clk_i),
.rst_i(rst_i),

// Control
.bit_div_i((CLK_FREQ / UART_SPEED) - 1),
.stop_bits_i(1'b0), // 0 = 1, 1 = 2

// Transmit
.wr_i(uart_wr_w),
.data_i(uart_wr_data_w),
.tx_busy_o(uart_wr_busy_w),

// Receive
.rd_i(uart_rd_w),
.data_o(uart_rd_data_w),
.rx_ready_o(uart_rd_valid_w),

.rx_err_o(uart_rx_error_w),

// UART pins
.rxd_i(uart_rxd_i),
.txd_o(uart_txd_o)
);

//-----------------------------------------------------------------
// Output FIFO
//-----------------------------------------------------------------
wire uart_tx_pop_w = ~uart_wr_busy_w;

dbg_bridge_fifo
#(
.WIDTH(8),
.DEPTH(8),
.ADDR_W(3)
)
u_fifo_tx
(
.clk_i(clk_i),
.rst_i(rst_i),

// In
.push_i(tx_valid_w),
.data_in_i(tx_data_w),
.accept_o(tx_accept_w),

// Out
.pop_i(uart_tx_pop_w),
.data_out_o(uart_wr_data_w),
.valid_o(uart_wr_w)
);

//-----------------------------------------------------------------
// Input FIFO
//-----------------------------------------------------------------
dbg_bridge_fifo
#(
.WIDTH(8),
.DEPTH(8),
.ADDR_W(3)
)
u_fifo_rx
(
.clk_i(clk_i),
.rst_i(rst_i),

// In
.push_i(uart_rd_valid_w),
.data_in_i(uart_rd_data_w),
.accept_o(uart_rd_w),

// Out
.pop_i(rx_accept_w),
.data_out_o(rx_data_w),
.valid_o(rx_valid_w)
);

//-----------------------------------------------------------------
// States
//-----------------------------------------------------------------
reg [`STATE_R] state_q;
reg [`STATE_R] next_state_r;

always @ *
begin
next_state_r = state_q;

case (next_state_r)
//-------------------------------------------------------------
// IDLE:
//-------------------------------------------------------------
STATE_IDLE:
begin
if (rx_valid_w)
begin
case (rx_data_w)
REQ_WRITE,
REQ_READ:
next_state_r = STATE_LEN;
default:
;
endcase
end
end
//-----------------------------------------
// STATE_LEN
//-----------------------------------------
STATE_LEN :
begin
if (rx_valid_w)
next_state_r = STATE_ADDR0;
end
//-----------------------------------------
// STATE_ADDR
//-----------------------------------------
STATE_ADDR0 : if (rx_valid_w) next_state_r = STATE_ADDR1;
STATE_ADDR1 : if (rx_valid_w) next_state_r = STATE_ADDR2;
STATE_ADDR2 : if (rx_valid_w) next_state_r = STATE_ADDR3;
STATE_ADDR3 :
begin
if (rx_valid_w && mem_wr_q)
next_state_r = STATE_WRITE;
else if (rx_valid_w)
next_state_r = STATE_READ;
end
//-----------------------------------------
// STATE_WRITE
//-----------------------------------------
STATE_WRITE :
begin
if (len_q == 8'b0 && (m_axi_bvalid || magic_addr_w))
next_state_r = STATE_IDLE;
else
next_state_r = STATE_WRITE;
end
//-----------------------------------------
// STATE_READ
//-----------------------------------------
STATE_READ :
begin
// Data ready
if (m_axi_rvalid || magic_addr_w)
next_state_r = STATE_DATA0;
end
//-----------------------------------------
// STATE_DATA
//-----------------------------------------
STATE_DATA0 :
begin
if (read_skip_w)
next_state_r = STATE_DATA1;
else if (tx_accept_w && (len_q == 8'b0))
next_state_r = STATE_IDLE;
else if (tx_accept_w)
next_state_r = STATE_DATA1;
end
STATE_DATA1 :
begin
if (read_skip_w)
next_state_r = STATE_DATA2;
else if (tx_accept_w && (len_q == 8'b0))
next_state_r = STATE_IDLE;
else if (tx_accept_w)
next_state_r = STATE_DATA2;
end
STATE_DATA2 :
begin
if (read_skip_w)
next_state_r = STATE_DATA3;
else if (tx_accept_w && (len_q == 8'b0))
next_state_r = STATE_IDLE;
else if (tx_accept_w)
next_state_r = STATE_DATA3;
end
STATE_DATA3 :
begin
if (tx_accept_w && (len_q != 8'b0))
next_state_r = STATE_READ;
else if (tx_accept_w)
next_state_r = STATE_IDLE;
end
default:
;
endcase
end

// State storage
always @ (posedge clk_i or posedge rst_i)
if (rst_i)
state_q <= STATE_IDLE;
else
state_q <= next_state_r;

//-----------------------------------------------------------------
// RD/WR to and from UART
//-----------------------------------------------------------------

// Write to UART Tx buffer in the following states
assign tx_valid_w = ((state_q == STATE_DATA0) |
(state_q == STATE_DATA1) |
(state_q == STATE_DATA2) |
(state_q == STATE_DATA3)) && !read_skip_w;

// Accept data in the following states
assign rx_accept_w = (state_q == STATE_IDLE) |
(state_q == STATE_LEN) |
(state_q == STATE_ADDR0) |
(state_q == STATE_ADDR1) |
(state_q == STATE_ADDR2) |
(state_q == STATE_ADDR3) |
(state_q == STATE_WRITE && !mem_busy_q);

//-----------------------------------------------------------------
// Capture length
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
if (rst_i)
len_q <= 8'd0;
else if (state_q == STATE_LEN && rx_valid_w)
len_q[7:0] <= rx_data_w;
else if (state_q == STATE_WRITE && rx_valid_w && !mem_busy_q)
len_q <= len_q - 8'd1;
else if (state_q == STATE_READ && ((mem_busy_q && m_axi_rvalid) || magic_addr_w))
len_q <= len_q - 8'd1;
else if (((state_q == STATE_DATA0) || (state_q == STATE_DATA1) || (state_q == STATE_DATA2)) && (tx_accept_w && !read_skip_w))
len_q <= len_q - 8'd1;

//-----------------------------------------------------------------
// Capture addr
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
if (rst_i)
mem_addr_q <= 'd0;
else if (state_q == STATE_ADDR0 && rx_valid_w)
mem_addr_q[31:24] <= rx_data_w;
else if (state_q == STATE_ADDR1 && rx_valid_w)
mem_addr_q[23:16] <= rx_data_w;
else if (state_q == STATE_ADDR2 && rx_valid_w)
mem_addr_q[15:8] <= rx_data_w;
else if (state_q == STATE_ADDR3 && rx_valid_w)
mem_addr_q[7:0] <= rx_data_w;
// Address increment on every access issued
else if (state_q == STATE_WRITE && (mem_busy_q && m_axi_bvalid))
mem_addr_q <= {mem_addr_q[31:2], 2'b0} + 'd4;
else if (state_q == STATE_READ && (mem_busy_q && m_axi_rvalid))
mem_addr_q <= {mem_addr_q[31:2], 2'b0} + 'd4;

//-----------------------------------------------------------------
// Data Index
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
if (rst_i)
data_idx_q <= 2'b0;
else if (state_q == STATE_ADDR3)
data_idx_q <= rx_data_w[1:0];
else if (state_q == STATE_WRITE && rx_valid_w && !mem_busy_q)
data_idx_q <= data_idx_q + 2'd1;
else if (((state_q == STATE_DATA0) || (state_q == STATE_DATA1) || (state_q == STATE_DATA2)) && tx_accept_w && (data_idx_q != 2'b0))
data_idx_q <= data_idx_q - 2'd1;

assign read_skip_w = (data_idx_q != 2'b0);

//-----------------------------------------------------------------
// Data Sample
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
if (rst_i)
data_q <= 32'b0;
// Write to memory
else if (state_q == STATE_WRITE && rx_valid_w && !mem_busy_q)
begin
case (data_idx_q)
2'd0: data_q[7:0] <= rx_data_w;
2'd1: data_q[15:8] <= rx_data_w;
2'd2: data_q[23:16] <= rx_data_w;
2'd3: data_q[31:24] <= rx_data_w;
endcase
end
// Read from GPIO Input?
else if (state_q == STATE_READ && mem_addr_q == GPIO_ADDRESS)
begin
data_q <= {{(32-32){1'b0}}, gpio_inputs_i};
end
// Read from status register?
else if (state_q == STATE_READ && mem_addr_q == STS_ADDRESS)
data_q <= {16'hcafe, 15'd0, mem_busy_q};
// Read from memory
else if (state_q == STATE_READ && m_axi_rvalid)
data_q <= m_axi_rdata;
// Shift data out (read response -> UART)
else if (((state_q == STATE_DATA0) || (state_q == STATE_DATA1) || (state_q == STATE_DATA2)) && (tx_accept_w || read_skip_w))
data_q <= {8'b0, data_q[31:8]};

assign tx_data_w = data_q[7:0];

assign m_axi_wdata = data_q;

//-----------------------------------------------------------------
// AXI: Write Request
//-----------------------------------------------------------------
reg mem_awvalid_q;
reg mem_awvalid_r;

reg mem_wvalid_q;
reg mem_wvalid_r;

always @ *
begin
mem_awvalid_r = 1'b0;
mem_wvalid_r = 1'b0;

// Hold
if (m_axi_awvalid && !m_axi_awready)
mem_awvalid_r = mem_awvalid_q;
else if (m_axi_awvalid)
mem_awvalid_r = 1'b0;
// Every 4th byte, issue bus access
else if (state_q == STATE_WRITE && rx_valid_w && (data_idx_q == 2'd3 || len_q == 1))
mem_awvalid_r = !magic_addr_w;

// Hold
if (m_axi_wvalid && !m_axi_wready)
mem_wvalid_r = mem_wvalid_q;
else if (m_axi_wvalid)
mem_wvalid_r = 1'b0;
// Every 4th byte, issue bus access
else if (state_q == STATE_WRITE && rx_valid_w && (data_idx_q == 2'd3 || len_q == 1))
mem_wvalid_r = !magic_addr_w;
end

always @ (posedge clk_i or posedge rst_i)
if (rst_i)
begin
mem_awvalid_q <= 1'b0;
mem_wvalid_q <= 1'b0;
end
else
begin
mem_awvalid_q <= mem_awvalid_r;
mem_wvalid_q <= mem_wvalid_r;
end

assign m_axi_awvalid = mem_awvalid_q;
assign m_axi_wvalid = mem_wvalid_q;
assign m_axi_awaddr = {mem_addr_q[31:2], 2'b0};
//assign mem_awid_o = AXI_ID;
assign m_axi_awlen = 8'b0;
assign m_axi_awburst = 2'b01;
assign m_axi_wlast = 1'b1;

assign m_axi_bready = 1'b1;

// add by user
assign m_axi_awsize = 3'b010; // 000:1Byte 001:2Bytes 010:4Bytes 011:8Bytes 100:16Byte 101:32Bytes 110:64Bytes 111:128Bytes
assign m_axi_awprot = 3'b000; // 常規(guī)安全數(shù)據(jù)訪問
assign m_axi_awcache = 4'b0011; // 傳輸屬性

//-----------------------------------------------------------------
// AXI: Read Request
//-----------------------------------------------------------------
reg mem_arvalid_q;
reg mem_arvalid_r;

always @ *
begin
mem_arvalid_r = 1'b0;

// Hold
if (m_axi_arvalid && !m_axi_arready)
mem_arvalid_r = mem_arvalid_q;
else if (m_axi_arvalid)
mem_arvalid_r = 1'b0;
else if (state_q == STATE_READ && !mem_busy_q)
mem_arvalid_r = !magic_addr_w;
end

always @ (posedge clk_i or posedge rst_i)
if (rst_i)
mem_arvalid_q <= 1'b0;
else
mem_arvalid_q <= mem_arvalid_r;

assign m_axi_arvalid = mem_arvalid_q;
assign m_axi_araddr = {mem_addr_q[31:2], 2'b0};
//assign mem_arid_o = AXI_ID;
assign m_axi_arlen = 8'b0;
assign m_axi_arburst = 2'b01;

assign m_axi_rready = 1'b1;

// add by user
assign m_axi_arprot = 3'b000; // 常規(guī)安全數(shù)據(jù)訪問
assign m_axi_arcache = 4'b0011; // 傳輸屬性
assign m_axi_arsize = 3'b010; // 000:1Byte 001:2Bytes 010:4Bytes 011:8Bytes 100:16Byte 101:32Bytes 110:64Bytes 111:128Bytes


//-----------------------------------------------------------------
// Write mask
//-----------------------------------------------------------------
reg [3:0] mem_sel_q;
reg [3:0] mem_sel_r;

always @ *
begin
mem_sel_r = 4'b1111;

case (data_idx_q)
2'd0: mem_sel_r = 4'b0001;
2'd1: mem_sel_r = 4'b0011;
2'd2: mem_sel_r = 4'b0111;
2'd3: mem_sel_r = 4'b1111;
endcase

case (mem_addr_q[1:0])
2'd0: mem_sel_r = mem_sel_r & 4'b1111;
2'd1: mem_sel_r = mem_sel_r & 4'b1110;
2'd2: mem_sel_r = mem_sel_r & 4'b1100;
2'd3: mem_sel_r = mem_sel_r & 4'b1000;
endcase
end

always @ (posedge clk_i or posedge rst_i)
if (rst_i)
mem_sel_q <= 4'b0;
// Idle - reset for read requests
else if (state_q == STATE_IDLE)
mem_sel_q <= 4'b1111;
// Every 4th byte, issue bus access
else if (state_q == STATE_WRITE && rx_valid_w && (data_idx_q == 2'd3 || len_q == 8'd1))
mem_sel_q <= mem_sel_r;

assign m_axi_wstrb = mem_sel_q;

//-----------------------------------------------------------------
// Write enable
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
if (rst_i)
mem_wr_q <= 1'b0;
else if (state_q == STATE_IDLE && rx_valid_w)
mem_wr_q <= (rx_data_w == REQ_WRITE);

//-----------------------------------------------------------------
// Access in progress
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
if (rst_i == 1'b1)
mem_busy_q <= 1'b0;
else if (m_axi_arvalid || m_axi_awvalid)
mem_busy_q <= 1'b1;
else if (m_axi_bvalid || m_axi_rvalid)
mem_busy_q <= 1'b0;

//-----------------------------------------------------------------
// GPIO Outputs
//-----------------------------------------------------------------
reg gpio_wr_q;
reg [31:0] gpio_output_q;

always @ (posedge clk_i or posedge rst_i)
if (rst_i)
gpio_wr_q <= 1'b0;
else if (mem_addr_q == GPIO_ADDRESS && state_q == STATE_WRITE && rx_valid_w && (data_idx_q == 2'd3 || len_q == 1))
gpio_wr_q <= 1'b1;
else
gpio_wr_q <= 1'b0;

always @ (posedge clk_i or posedge rst_i)
if (rst_i)
gpio_output_q <= 32'h0;
else if (gpio_wr_q)
gpio_output_q <= data_q[31:0];

assign gpio_outputs_o = gpio_output_q;

endmodule

為了方便仿真,dbg_bridge_uart.v修改如下:

//-----------------------------------------------------------------
// UART Tx Pin (change by user :下面的代碼仿真有問題,進(jìn)行了修改)
//-----------------------------------------------------------------
/*reg txd_r;

always @ *
begin
txd_r = 1'b1;

if (tx_busy_q)
begin
// Start bit (TXD = L)
if (tx_bits_q == START_BIT)
txd_r = 1'b0;
// Stop bits (TXD = H)
else if (tx_bits_q == STOP_BIT0 || tx_bits_q == STOP_BIT1)
txd_r = 1'b1;
// Data bits
else
txd_r = tx_shift_reg_q[0];
end

end*/

always @ (posedge clk_i or posedge rst_i)
if (rst_i)
txd_q <= 1'b1;
else
begin
if (tx_busy_q)
begin
// Start bit (TXD = L)
if (tx_bits_q == START_BIT)
txd_q <= 1'b0;
// Stop bits (TXD = H)
else if (tx_bits_q == STOP_BIT0 || tx_bits_q == STOP_BIT1)
txd_q <= 1'b1;
// Data bits
else
txd_q <= tx_shift_reg_q[0];
end
else
txd_q <= 1'b1; ? ??
end

由于IP轉(zhuǎn)換出來的是axi4_full接口,如果是用vivado環(huán)境,可以直接連接到xilinx的axi interconnect,前面文檔介紹過xilinx的互聯(lián)具有協(xié)議轉(zhuǎn)換功能,可以自動轉(zhuǎn)換成axi4_lite接口。如果是非xilinx平臺,我們也是有辦法的,該IP的axi4_full接口,由于設(shè)計突發(fā)長度為1,我們也可以很方便的連接axi4_lite_slave,只需要用到axi4_lite相關(guān)信號,如下圖所示:

d62eb61e-cb63-11f0-8c8f-92fbcf53809c.png

圖 4 axi4_lite接口例化示意

python也是很方便的進(jìn)行移植,控制axi_lite_slave寄存器,例子如下:

d68956a0-cb63-11f0-8c8f-92fbcf53809c.png

圖 5 python操作axi_lite_slave寄存器

3,總結(jié)

本文主要介紹axi4_lite_master主機(jī)uart2axi4,利用開源uart2axi4我們可以通過python,輕松訪問axi4_lite_slave寄存器,大大方便fpga工程師進(jìn)行系統(tǒng)調(diào)試和定位bug。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5588

    瀏覽量

    128994
  • 接口
    +關(guān)注

    關(guān)注

    33

    文章

    9441

    瀏覽量

    156076
  • 串口
    +關(guān)注

    關(guān)注

    15

    文章

    1606

    瀏覽量

    81875
  • AXI總線
    +關(guān)注

    關(guān)注

    0

    文章

    68

    瀏覽量

    14713

原文標(biāo)題:利用開源uart2axi4實現(xiàn)串口訪問axi總線

文章出處:【微信號:gh_9d70b445f494,微信公眾號:FPGA設(shè)計論壇】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    Zynq中AXI4-Lite和AXI-Stream功能介紹

    。AXI4-Lite接口的特性如下: 1) 突發(fā)長度為1。 2) 所有訪問數(shù)據(jù)的寬度和數(shù)據(jù)總線寬度相同。 3) 支持?jǐn)?shù)據(jù)總線寬度為32位或6
    的頭像 發(fā)表于 09-27 11:33 ?9751次閱讀
    Zynq中<b class='flag-5'>AXI4</b>-Lite和<b class='flag-5'>AXI</b>-Stream功能介紹

    Xilinx zynq AXI總線全面解讀

    AXI (Advanced eXtensible Interface) 本是由ARM公司提出的一種總線協(xié)議, Xilinx從 6 系列的 FPGA 開始對 AXI 總線提供支持,目前使
    的頭像 發(fā)表于 12-04 12:22 ?8956次閱讀
     Xilinx zynq <b class='flag-5'>AXI</b><b class='flag-5'>總線</b>全面解讀

    看看在SpinalHDL中AXI4總線互聯(lián)IP的設(shè)計

    不做過多的講解(小伙伴可以自行下載AMBA總線協(xié)議規(guī)范或者翻看網(wǎng)絡(luò)上AXI4總線協(xié)議相關(guān)文章)。在SpinalHDL中,關(guān)于Axi4總線,包
    發(fā)表于 08-02 14:28

    AMBA AXI總線學(xué)習(xí)筆記

    AMBA AXI 總線學(xué)習(xí)筆記,非常詳細(xì)的AXI總線操作說明
    發(fā)表于 11-11 16:49 ?12次下載

    AXI 總線和引腳的介紹

    1、AXI 總線通道,總線和引腳的介紹 AXI接口具有五個獨(dú)立的通道: (1)寫地址通道(AW):write address channel (2
    發(fā)表于 01-05 08:13 ?1.1w次閱讀
    <b class='flag-5'>AXI</b> <b class='flag-5'>總線</b>和引腳的介紹

    一文詳解ZYNQ中的DMA與AXI4總線

    在ZYNQ中,支持AXI-Lite,AXI4AXI-Stream三種總線,但PS與PL之間的接口卻只支持前兩種,AXI-Stream只能在
    的頭像 發(fā)表于 09-24 09:50 ?7054次閱讀
    一文詳解ZYNQ中的DMA與<b class='flag-5'>AXI4</b><b class='flag-5'>總線</b>

    ZYNQ中DMA與AXI4總線

    和接口的構(gòu)架 在ZYNQ中,支持AXI-Lite,AXI4AXI-Stream三種總線,但PS與PL之間的接口卻只支持前兩種,AXI-St
    的頭像 發(fā)表于 11-02 11:27 ?4964次閱讀
    ZYNQ中DMA與<b class='flag-5'>AXI4</b><b class='flag-5'>總線</b>

    深入AXI4總線一握手機(jī)制

    本系列我想深入探尋 AXI4 總線。不過事情總是這樣,不能我說想深入就深入。當(dāng)前我對 AXI總線的理解尚談不上深入。但我希望通過一系列文章,讓讀者能和我一起深入探尋
    發(fā)表于 03-17 21:40 ?25次下載
    深入<b class='flag-5'>AXI4</b><b class='flag-5'>總線</b>一握手機(jī)制

    AMBA 3.0 AXI總線接口協(xié)議的研究與應(yīng)用

    本文介紹了AMBA 3.0 AXI的結(jié)構(gòu)和特點(diǎn),分析了新的AMBA 3.0 AXI協(xié)議相對于AMBA 2. 0的優(yōu)點(diǎn)。它將革新未來高性能SOC總線互連技術(shù),其特點(diǎn)使它更加適合未來的高性
    發(fā)表于 04-12 15:47 ?28次下載

    串口轉(zhuǎn)axi主機(jī)總線接口

    uart2axi_master_intf程序源碼:/**************************************************** Module Name
    發(fā)表于 12-28 20:04 ?14次下載
    <b class='flag-5'>串口</b>轉(zhuǎn)<b class='flag-5'>axi</b>主機(jī)<b class='flag-5'>總線</b>接口

    AXI4AXI4-Lite 、AXI4-Stream接口

    AXI4 是一種高性能memory-mapped總線AXI4-Lite是一只簡單的、低通量的memory-mapped 總線,而 AXI4
    的頭像 發(fā)表于 07-04 09:40 ?1w次閱讀

    Xilinx FPGA AXI4總線(一)介紹【AXI4】【AXI4-Lite】【AXI-Stream】

    從 FPGA 應(yīng)用角度看看 AMBA 總線中的 AXI4 總線。
    發(fā)表于 06-21 15:21 ?3026次閱讀
    Xilinx FPGA <b class='flag-5'>AXI4</b><b class='flag-5'>總線</b>(一)介紹【<b class='flag-5'>AXI4</b>】【<b class='flag-5'>AXI4</b>-Lite】【<b class='flag-5'>AXI</b>-Stream】

    AXI實戰(zhàn)(二)-AXI-Lite的Slave實現(xiàn)介紹

    可以看到,在AXIUART中,是通過寄存器和FIFO進(jìn)行中介的。因為從AXI總線往里看,其控制的是就是地址上所映射的寄存器。
    的頭像 發(fā)表于 06-27 10:12 ?7573次閱讀
    <b class='flag-5'>AXI</b>實戰(zhàn)(二)-<b class='flag-5'>AXI</b>-Lite的Slave<b class='flag-5'>實現(xiàn)</b>介紹

    基于AXI總線的DDR3讀寫測試

    本文開源一個FPGA項目:基于AXI總線的DDR3讀寫。之前的一篇文章介紹了DDR3簡單用戶接口的讀寫方式:《DDR3讀寫測試》,如果在某些項目中,我們需要把DDR掛載到AXI
    的頭像 發(fā)表于 09-01 16:20 ?7062次閱讀
    基于<b class='flag-5'>AXI</b><b class='flag-5'>總線</b>的DDR3讀寫測試

    FPGA通過AXI總線讀寫DDR3實現(xiàn)方式

    AXI總線由一些核心組成,包括AXI主處理器接口(AXI4)、AXI處理器到協(xié)處理器接口(AXI4
    發(fā)表于 04-18 11:41 ?2385次閱讀