<XILINX> AXI4-Lite(三) Master接口时序分析

目录

01 axi4_lite_master写事务代码分析

写事务开始信号边沿检测

AWVALID时序控制代码分析

WVALID时序控制代码分析

BREADY时序控制代码分析

02 axi4_lite_master读事务代码分析

读事务开始信号边沿检测

ARVALID时序控制代码分析

RREADY时序控制代码分析

RDATA寄存控制

03 文章总结


大家好,这里是程序员杰克。一名平平无奇的嵌入式软件工程师。

上篇主要是对axi4-lite_slave接口信号的时序代码进行分析,在本篇推送中,杰克将继续对axi4-Lite总线协议的master接口信号的时序代码进行分析。

Xilinx 提供了axi4-lite_master的模板,对于初学者而言,是一个很好的学习资料,但杰克认为其接口信号的时序代码并不是最优解,因此杰克重新编写和封装了一个axi4-lite_master,并以此作为本次master接口的代码分析内容。


下面正式进入本章推送的内容。

01 axi4_lite_master写事务代码分析

上篇推送对Xilinx提供的slave模板分析中我们知道:写地址通道、写数据通道同时握手成功才执行写事务传输。那么axi4-lite_master接口也必须配合slave接口对信号进行设计。axi4-lite_master接口写事务主要是实现如下时序:

  • 写地址通道握手信号AWVALID的时序控制
  • 写数据通道握手信号WVALID的时序控制
  • 写响应通道BREADY信号的时序控制

AXI4-Lite 写事务仿真逻辑时序如下图所示:

图片


写事务开始信号边沿检测

前面有提过,杰克重新封装了一个axi4-lite_master,该接口以开始信号作为驱动,因此杰克这里对开始信号边沿进行了检测,检测代码如下:

input  wire    write_start;...//write_start edge detected logicreg write_start_tmp1;reg write_start_tmp2;wire write_start_rise = write_start_tmp2 & (~write_start_tmp1);always @(posedge M_AXI_ACLK) begin  if(M_AXI_ARESETN == 1'b0) begin    write_start_tmp1 <= 1'b0;    write_start_tmp2 <= 1'b0;  end  else begin    write_start_tmp1 <= write_start_tmp2;    write_start_tmp2 <= write_start;  endend
关注信号描述
write_start外部驱动输入信号,用于表征写事务开始.

write_start_rise

(默认为0)

对write_start上升沿打一拍的信号,作为axi4-lite_master写事务真正开始信号.

AWVALID时序控制代码分析

reg axi_awvalid;assign M_AXI_AWVALID  = axi_awvalid;...//M_AXI_AWVALID signnal control logicalways @(posedge M_AXI_ACLK) begin  if(M_AXI_ARESETN == 1'b0) begin    axi_awvalid <= 1'b0;  end  else begin    if(write_start_rise) begin      axi_awvalid <= 1'b1;    end    else if(M_AXI_AWREADY && axi_awvalid) begin      axi_awvalid <= 1'b0;    end    else begin      axi_awvalid  <= axi_awvalid;    end  endend
关注信号条件描述

axi_awvalid

(默认为0)

置高当wirte_start_rise为高,该信号置高,表示写事务开始,与axi_wvalid同时置高,即写地址通道、写数据通道同时握手
置低当M_AXI_AWREADY&&本身为高时,置低,即说明axi_awvalid在传输过程中是一个脉冲信号

WVALID时序控制代码分析

reg axi_wvalid;assign M_AXI_WVALID    = axi_wvalid;...//M_AXI_WVALID signnal control logicalways @(posedge M_AXI_ACLK) begin  if(M_AXI_ARESETN == 1'b0) begin    axi_wvalid <= 1'b0;  end  else begin    if(write_start_rise) begin      axi_wvalid <= 1'b1;    end    else if(M_AXI_WREADY && axi_wvalid) begin      axi_wvalid <= 1'b0;    end    else begin      axi_wvalid  <= axi_wvalid;    end  endend
关注信号条件描述

axi_wvalid

(默认为0)

置高当wirte_start_rise为高,该信号置高;与axi_awvalid同时置高,即写地址通道、写数据通道同时握手
置低当M_AXI_WREADY&&本身为高时,置低,即说明axi_wvalid在传输过程中是一个脉冲信号

BREADY时序控制代码分析

reg axi_bready;assign M_AXI_BREADY    = axi_bready;...//M_AXI_BREADY signnal control logicalways @(posedge M_AXI_ACLK) begin  if(M_AXI_ARESETN == 1'b0) begin    axi_bready <= 1'b0;  end  else if(axi_awvalid && ~axi_bready) begin    axi_bready <= 1'b1;  end  else if(M_AXI_BVALID) begin    axi_bready <= 1'b0;  end  else begin    axi_bready <= axi_bready;  endend
关注信号条件描述

axi_bready

(默认为0)

置高当axi_awvalid为高、信号本身为低时,置高;该信号保持高,一直到slave的M_AXI_BVALID响应;表征当传输开始后,master一直等待slave写响应.
置低当slave写响应通道信号M_AXI_BVALID为高时,握手成功后置低.

02 axi4_lite_master读事务代码分析

对于AXI4-Lite总线读事务而言,axi4-lite_master接口主要是实现如下时序:

  • 读地址通道握手信号ARVALID的时序控制
  • 读数据通道握手信号RREADY的时序控制
  • 读数据通道RDATA的寄存控制

AXI4-Lite读事务仿真逻辑时序如下图所示:


图片


读事务开始信号边沿检测

前面有提过,杰克重新封装了一个axi4-lite_master,该接口以开始信号作为驱动,因此杰克这里对开始信号边沿进行了检测,检测代码如下:

input  wire  read_start;...//read_start edge detected logicreg read_start_tmp1;reg read_start_tmp2;wire read_start_rise = read_start_tmp2 & (~read_start_tmp1);always @(posedge M_AXI_ACLK) begin  if(M_AXI_ARESETN == 1'b0) begin    read_start_tmp1 <= 1'b0;    read_start_tmp2 <= 1'b0;  end  else begin    read_start_tmp1 <= read_start_tmp2;    read_start_tmp2 <= read_start;  endend
关注信号描述
read_start外部驱动输入信号,用于表征读事务开始.

read_start_rise

(默认为0)

对read_start上升沿打一拍的信号,作为axi4-lite_master读事务真正开始信号.

ARVALID时序控制代码分析

reg axi_arvalid;assign M_AXI_ARVALID  = axi_arvalid;...//M_AXI_ARVALID signnal control logicalways @(posedge M_AXI_ACLK) begin  if(M_AXI_ARESETN == 1'b0) begin    axi_arvalid <= 1'b0;  end  else begin    if(read_start_rise) begin      axi_arvalid <= 1'b1;    end    else if(M_AXI_ARREADY && axi_arvalid) begin      axi_arvalid <= 1'b0;    end    else begin      axi_arvalid  <= axi_arvalid;    end  endend
关注信号条件描述

axi_arvalid

(默认为0)

置高当read_start_rise为高,该信号置高,表示读事务开始,写地址通道握手开始.
置低当M_AXI_AREADY&&本身为高时,置低,即说明axi_arvalid在传输过程中是一个脉冲信号

RREADY时序控制代码分析

reg axi_rready;assign M_AXI_RREADY    = axi_rready;...//M_AXI_RREADY signnal control logicalways @(posedge M_AXI_ACLK) begin  if(M_AXI_ARESETN == 1'b0) begin    axi_rready <= 1'b0;  end  else if(axi_arvalid && ~axi_rready) begin    axi_rready <= 1'b1;  end  else if(M_AXI_RVALID) begin    axi_rready <= 1'b0;  end  else begin    axi_rready <= axi_rready;  endend
关注信号条件描述

axi_rready

(默认为0)

置高当axi_arvalid为高、信号本身为低时,置高;该信号保持高,一直到slave的M_AXI_RVALID响应;表征当读传输开始后,master一直等待slave写响应.
置低当M_AXI_BVALID为高时,握手成功后置低.

RDATA寄存控制

parameter integer C_M_AXI_DATA_WIDTH  = 32;output  wire  [C_M_AXI_DATA_WIDTH-1 : 0]    rdata;...assign rdata = (M_AXI_RVALID && axi_rready) ? M_AXI_RDATA : rdata;
关注信号描述
rdataM_AXI_RVALID、axi_rready同时为高时,此时M_AXI_RDATA的数据便是要读取的数据.

03 文章总结

axi4-lite总线接口时序算比较简单,对于PL与PS一些寄存器操作,axi4-lite有着占用逻辑小、效率高的特点。axi4-lite是axi4-full总线协议的精简,学习axi4-lite对于理解axi4-full总线有一定的帮助。

当然,因为篇幅、个人理解不一致,对于学习axi4-lite总线而言,可以借鉴别人的思想,但最终还是得自己下功夫去啃,毕竟啃下来的才是自己收获的。

axi4-lite总线协议以及master/slave接口总结分享到此就结束了。从下篇开始,开始总结分享axi4-full总线的内容。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
以下是一个简单的基于Xilinx AXI4-Lite接口的SPI控制器的Verilog代码: ```verilog module axi_spi_controller ( input wire clk, input wire rst, input wire [31:0] axi_awaddr, input wire [2:0] axi_awprot, input wire axi_awvalid, output reg axi_awready, input wire [31:0] axi_wdata, input wire [3:0] axi_wstrb, input wire axi_wvalid, output reg axi_wready, output reg [31:0] axi_bresp, output reg axi_bvalid, input wire axi_bready, input wire [31:0] axi_araddr, input wire [2:0] axi_arprot, input wire axi_arvalid, output reg axi_arready, output reg [31:0] axi_rdata, output reg [1:0] axi_rresp, output reg axi_rvalid, input wire axi_rready, output reg spi_cs, output reg spi_clk, output reg spi_mosi, input wire spi_miso ); // AXI4-Lite read/write registers reg [31:0] control_reg; reg [31:0] status_reg; reg [31:0] data_reg; // SPI controller state machine reg [3:0] spi_state; localparam IDLE = 4'b0000; localparam WRITE = 4'b0001; localparam READ = 4'b0010; // SPI controller shift register reg [7:0] spi_shift_reg; reg [3:0] spi_shift_count; // AXI4-Lite read/write logic always @(posedge clk) begin if (rst) begin axi_awready <= 1'b0; axi_wready <= 1'b0; axi_bresp <= 2'b00; axi_bvalid <= 1'b0; axi_arready <= 1'b0; axi_rdata <= 32'h0; axi_rresp <= 2'b00; axi_rvalid <= 1'b0; end else begin // Write address if (axi_awvalid && !axi_awready) begin axi_awready <= 1'b1; axi_wready <= 1'b1; control_reg <= axi_wdata; end else if (axi_wvalid && !axi_wready) begin axi_wready <= 1'b1; case (axi_awaddr[1:0]) 2'b00: data_reg[7:0] <= axi_wdata[7:0]; 2'b01: data_reg[15:8] <= axi_wdata[7:0]; 2'b10: data_reg[23:16] <= axi_wdata[7:0]; 2'b11: data_reg[31:24] <= axi_wdata[7:0]; endcase end else if (axi_wvalid && axi_wready) begin axi_wready <= 1'b0; axi_bresp <= 2'b00; axi_bvalid <= 1'b1; end else begin axi_awready <= 1'b0; axi_wready <= 1'b0; axi_bresp <= 2'b00; axi_bvalid <= 1'b0; end // Read address if (axi_arvalid && !axi_arready) begin axi_arready <= 1'b1; case (axi_araddr[1:0]) 2'b00: axi_rdata <= control_reg; 2'b01: axi_rdata <= status_reg; 2'b10: axi_rdata <= data_reg; 2'b11: axi_rdata <= 32'h0; endcase axi_rresp <= 2'b00; axi_rvalid <= 1'b1; end else if (axi_rvalid && !axi_rready) begin axi_rvalid <= 1'b0; end else if (!axi_arvalid) begin axi_arready <= 1'b0; end end end // SPI controller state machine logic always @(posedge clk) begin if (rst) begin spi_cs <= 1'b1; spi_clk <= 1'b0; spi_mosi <= 1'b0; spi_state <= IDLE; spi_shift_reg <= 8'h0; spi_shift_count <= 4'h0; end else begin case (spi_state) IDLE: begin spi_cs <= 1'b1; spi_clk <= 1'b0; if (control_reg[0]) begin spi_state <= WRITE; spi_shift_reg <= data_reg[7:0]; spi_shift_count <= 4'h8; spi_cs <= 1'b0; end else if (control_reg[1]) begin spi_state <= READ; spi_shift_reg <= 8'h0; spi_shift_count <= 4'h0; spi_cs <= 1'b0; end end WRITE: begin spi_cs <= 1'b0; spi_clk <= ~spi_clk; if (spi_clk) begin spi_mosi <= spi_shift_reg[7]; spi_shift_reg <= {spi_shift_reg[6:0], 1'b0}; spi_shift_count <= spi_shift_count - 1; end if (!spi_clk && spi_shift_count == 0) begin spi_state <= IDLE; spi_cs <= 1'b1; end end READ: begin spi_cs <= 1'b0; spi_clk <= ~spi_clk; if (spi_clk) begin spi_shift_reg <= {spi_shift_reg[6:0], spi_miso}; spi_shift_count <= spi_shift_count + 1; end if (!spi_clk && spi_shift_count == 8) begin spi_state <= IDLE; spi_cs <= 1'b1; status_reg <= {24'h0, spi_shift_reg[7:0]}; end end endcase end end endmodule ``` 这个控制器将AXI4-Lite接口与SPI总线接口连接起来,并且支持读写控制寄存器和数据寄存器,可以进行SPI读写操作。在这个实现中,控制器的状态机负责管理SPI操作,包括写操作和读操作。 需要注意的是,这个实现只是一个简单的例子,可能需要根据具体的设计需求进行修改和扩展。在实际的设计中,还需要考虑时序约束、接口协议等方面的细节。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杰克拉力船长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值