当前位置:   article > 正文

基于AXI-Lite实现PS-PL通信_axi pl到ps端通信

axi pl到ps端通信

最近在学axi4-lite协议,就简单记录一下。

实验概述:通过AXI-Lite实现PS与PL区之间的简单读写功能,其中PS端作为主机,PL端作为从机。PS向PL发送控制指令,以控制PS区LED呼吸灯的频率,实现写操作;PL端检测按键Key的情况,根据按键情况将不同的数据返回给PS端,实现读操作。(原本实验的读操作是读一个温度传感器的数据,但我这边没有器件就改更简单的按键了)

软件环境:Vivado 2020.1

硬件环境:Zynq UltraScale + MPSoC XCZU3EG

       实验主要分三部分:分别对应在Vivado软件上使用Verilog编程搭建Soc系统工程(FPGA开发)、在Vitis平台使用C语言搭建SDK工程(ARM)以及实验结果。

1、搭建Soc系统工程

        其中,axi_lite_slave和ps_wr_rd_ctrl模块是核心模块。axi_lite_slave是在官方IP代码基础上进行修改的,ps_wr_rd_ctrl模块是自己写的,用于解析指令,产生读写操作的信号。

(1)Axi_lite_slave

        Axi_lite从机模块,主要是基于官方IP代码稍作修改(修改不多)

  1. `timescale 1 ns / 1 ps
  2. module axi_lite_slave_v1_0_S00_AXI #
  3. (
  4. // Users to add parameters here
  5. // User parameters ends
  6. // Do not modify the parameters beyond this line
  7. // Width of S_AXI data bus
  8. parameter integer C_S_AXI_DATA_WIDTH = 32,
  9. // Width of S_AXI address bus
  10. parameter integer C_S_AXI_ADDR_WIDTH = 4
  11. )
  12. (
  13. // Users to add ports here
  14. output wr_en, //写使能,高表示写数据、写地址有效
  15. output [3:0] wr_addr, //写数据(PS->PL)
  16. output [31:0] wr_data, //写地址(PS->PL)
  17. output rd_en, //读使能,高表示读数据、读地址有效
  18. output [3:0] rd_addr, //读地址(PL->PS)
  19. input [31:0] rd_data, //读数据(PL->PS)
  20. // User ports ends
  21. // Do not modify the ports beyond this line
  22. // Global Clock Signal
  23. input wire S_AXI_ACLK,
  24. // Global Reset Signal. This Signal is Active LOW
  25. input wire S_AXI_ARESETN,
  26. // Write address (issued by master, acceped by Slave)
  27. input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR,
  28. // Write channel Protection type. This signal indicates the
  29. // privilege and security level of the transaction, and whether
  30. // the transaction is a data access or an instruction access.
  31. input wire [2 : 0] S_AXI_AWPROT,
  32. // Write address valid. This signal indicates that the master signaling
  33. // valid write address and control information.
  34. input wire S_AXI_AWVALID,
  35. // Write address ready. This signal indicates that the slave is ready
  36. // to accept an address and associated control signals.
  37. output wire S_AXI_AWREADY,
  38. // Write data (issued by master, acceped by Slave)
  39. input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA,
  40. // Write strobes. This signal indicates which byte lanes hold
  41. // valid data. There is one write strobe bit for each eight
  42. // bits of the write data bus.
  43. input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB,
  44. // Write valid. This signal indicates that valid write
  45. // data and strobes are available.
  46. input wire S_AXI_WVALID,
  47. // Write ready. This signal indicates that the slave
  48. // can accept the write data.
  49. output wire S_AXI_WREADY,
  50. // Write response. This signal indicates the status
  51. // of the write transaction.
  52. output wire [1 : 0] S_AXI_BRESP,
  53. // Write response valid. This signal indicates that the channel
  54. // is signaling a valid write response.
  55. output wire S_AXI_BVALID,
  56. // Response ready. This signal indicates that the master
  57. // can accept a write response.
  58. input wire S_AXI_BREADY,
  59. // Read address (issued by master, acceped by Slave)
  60. input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR,
  61. // Protection type. This signal indicates the privilege
  62. // and security level of the transaction, and whether the
  63. // transaction is a data access or an instruction access.
  64. input wire [2 : 0] S_AXI_ARPROT,
  65. // Read address valid. This signal indicates that the channel
  66. // is signaling valid read address and control information.
  67. input wire S_AXI_ARVALID,
  68. // Read address ready. This signal indicates that the slave is
  69. // ready to accept an address and associated control signals.
  70. output wire S_AXI_ARREADY,
  71. // Read data (issued by slave)
  72. output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA,
  73. // Read response. This signal indicates the status of the
  74. // read transfer.
  75. output wire [1 : 0] S_AXI_RRESP,
  76. // Read valid. This signal indicates that the channel is
  77. // signaling the required read data.
  78. output wire S_AXI_RVALID,
  79. // Read ready. This signal indicates that the master can
  80. // accept the read data and response information.
  81. input wire S_AXI_RREADY
  82. );
  83. // AXI4LITE signals
  84. reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_awaddr;
  85. reg axi_awready;
  86. reg axi_wready;
  87. reg [1 : 0] axi_bresp;
  88. reg axi_bvalid;
  89. reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_araddr;
  90. reg axi_arready;
  91. reg [C_S_AXI_DATA_WIDTH-1 : 0] axi_rdata;
  92. reg [1 : 0] axi_rresp;
  93. reg axi_rvalid;
  94. // Example-specific design signals
  95. // local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH
  96. // ADDR_LSB is used for addressing 32/64 bit registers/memories
  97. // ADDR_LSB = 2 for 32 bits (n downto 2)
  98. // ADDR_LSB = 3 for 64 bits (n downto 3)
  99. localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1;
  100. localparam integer OPT_MEM_ADDR_BITS = 1;
  101. //----------------------------------------------
  102. //-- Signals for user logic register space example
  103. //------------------------------------------------
  104. //-- Number of Slave Registers 4
  105. reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg0;
  106. reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg1;
  107. reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg2;
  108. reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg3;
  109. wire slv_reg_rden;
  110. wire slv_reg_wren;
  111. reg [C_S_AXI_DATA_WIDTH-1:0] reg_data_out;
  112. integer byte_index;
  113. reg aw_en;
  114. // I/O Connections assignments
  115. assign S_AXI_AWREADY = axi_awready;
  116. assign S_AXI_WREADY = axi_wready;
  117. assign S_AXI_BRESP = axi_bresp;
  118. assign S_AXI_BVALID = axi_bvalid;
  119. assign S_AXI_ARREADY = axi_arready;
  120. assign S_AXI_RDATA = axi_rdata;
  121. assign S_AXI_RRESP = axi_rresp;
  122. assign S_AXI_RVALID = axi_rvalid;
  123. // Implement axi_awready generation
  124. // axi_awready is asserted for one S_AXI_ACLK clock cycle when both
  125. // S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is
  126. // de-asserted when reset is low.
  127. always @( posedge S_AXI_ACLK )
  128. begin
  129. if ( S_AXI_ARESETN == 1'b0 )
  130. begin
  131. axi_awready <= 1'b0;
  132. aw_en <= 1'b1;
  133. end
  134. else
  135. begin
  136. if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
  137. begin
  138. // slave is ready to accept write address when
  139. // there is a valid write address and write data
  140. // on the write address and data bus. This design
  141. // expects no outstanding transactions.
  142. axi_awready <= 1'b1;
  143. aw_en <= 1'b0;
  144. end
  145. else if (S_AXI_BREADY && axi_bvalid)
  146. begin
  147. aw_en <= 1'b1;
  148. axi_awready <= 1'b0;
  149. end
  150. else
  151. begin
  152. axi_awready <= 1'b0;
  153. end
  154. end
  155. end
  156. // Implement axi_awaddr latching
  157. // This process is used to latch the address when both
  158. // S_AXI_AWVALID and S_AXI_WVALID are valid.
  159. always @( posedge S_AXI_ACLK )
  160. begin
  161. if ( S_AXI_ARESETN == 1'b0 )
  162. begin
  163. axi_awaddr <= 0;
  164. end
  165. else
  166. begin
  167. if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
  168. begin
  169. // Write Address latching
  170. axi_awaddr <= S_AXI_AWADDR;
  171. end
  172. end
  173. end
  174. // Implement axi_wready generation
  175. // axi_wready is asserted for one S_AXI_ACLK clock cycle when both
  176. // S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is
  177. // de-asserted when reset is low.
  178. always @( posedge S_AXI_ACLK )
  179. begin
  180. if ( S_AXI_ARESETN == 1'b0 )
  181. begin
  182. axi_wready <= 1'b0;
  183. end
  184. else
  185. begin
  186. if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID && aw_en )
  187. begin
  188. // slave is ready to accept write data when
  189. // there is a valid write address and write data
  190. // on the write address and data bus. This design
  191. // expects no outstanding transactions.
  192. axi_wready <= 1'b1;
  193. end
  194. else
  195. begin
  196. axi_wready <= 1'b0;
  197. end
  198. end
  199. end
  200. // Implement memory mapped register select and write logic generation
  201. // The write data is accepted and written to memory mapped registers when
  202. // axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to
  203. // select byte enables of slave registers while writing.
  204. // These registers are cleared when reset (active low) is applied.
  205. // Slave register write enable is asserted when valid address and data are available
  206. // and the slave is ready to accept the write address and write data.
  207. assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;
  208. /*always @( posedge S_AXI_ACLK )
  209. begin
  210. if ( S_AXI_ARESETN == 1'b0 )
  211. begin
  212. slv_reg0 <= 0;
  213. slv_reg1 <= 0;
  214. slv_reg2 <= 0;
  215. slv_reg3 <= 0;
  216. end
  217. else begin
  218. if (slv_reg_wren)
  219. begin
  220. case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
  221. 2'h0:
  222. for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
  223. if ( S_AXI_WSTRB[byte_index] == 1 ) begin
  224. // Respective byte enables are asserted as per write strobes
  225. // Slave register 0
  226. slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
  227. end
  228. 2'h1:
  229. for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
  230. if ( S_AXI_WSTRB[byte_index] == 1 ) begin
  231. // Respective byte enables are asserted as per write strobes
  232. // Slave register 1
  233. slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
  234. end
  235. 2'h2:
  236. for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
  237. if ( S_AXI_WSTRB[byte_index] == 1 ) begin
  238. // Respective byte enables are asserted as per write strobes
  239. // Slave register 2
  240. slv_reg2[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
  241. end
  242. 2'h3:
  243. for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
  244. if ( S_AXI_WSTRB[byte_index] == 1 ) begin
  245. // Respective byte enables are asserted as per write strobes
  246. // Slave register 3
  247. slv_reg3[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
  248. end
  249. default : begin
  250. slv_reg0 <= slv_reg0;
  251. slv_reg1 <= slv_reg1;
  252. slv_reg2 <= slv_reg2;
  253. slv_reg3 <= slv_reg3;
  254. end
  255. endcase
  256. end
  257. end
  258. end */
  259. // Implement write response logic generation
  260. // The write response and response valid signals are asserted by the slave
  261. // when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted.
  262. // This marks the acceptance of address and indicates the status of
  263. // write transaction.
  264. always @( posedge S_AXI_ACLK )
  265. begin
  266. if ( S_AXI_ARESETN == 1'b0 )
  267. begin
  268. axi_bvalid <= 0;
  269. axi_bresp <= 2'b0;
  270. end
  271. else
  272. begin
  273. if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID)
  274. begin
  275. // indicates a valid write response is available
  276. axi_bvalid <= 1'b1;
  277. axi_bresp <= 2'b0; // 'OKAY' response
  278. end // work error responses in future
  279. else
  280. begin
  281. if (S_AXI_BREADY && axi_bvalid)
  282. //check if bready is asserted while bvalid is high)
  283. //(there is a possibility that bready is always asserted high)
  284. begin
  285. axi_bvalid <= 1'b0;
  286. end
  287. end
  288. end
  289. end
  290. // Implement axi_arready generation
  291. // axi_arready is asserted for one S_AXI_ACLK clock cycle when
  292. // S_AXI_ARVALID is asserted. axi_awready is
  293. // de-asserted when reset (active low) is asserted.
  294. // The read address is also latched when S_AXI_ARVALID is
  295. // asserted. axi_araddr is reset to zero on reset assertion.
  296. always @( posedge S_AXI_ACLK )
  297. begin
  298. if ( S_AXI_ARESETN == 1'b0 )
  299. begin
  300. axi_arready <= 1'b0;
  301. axi_araddr <= 32'b0;
  302. end
  303. else
  304. begin
  305. if (~axi_arready && S_AXI_ARVALID)
  306. begin
  307. // indicates that the slave has acceped the valid read address
  308. axi_arready <= 1'b1;
  309. // Read address latching
  310. axi_araddr <= S_AXI_ARADDR;
  311. end
  312. else
  313. begin
  314. axi_arready <= 1'b0;
  315. end
  316. end
  317. end
  318. // Implement axi_arvalid generation
  319. // axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both
  320. // S_AXI_ARVALID and axi_arready are asserted. The slave registers
  321. // data are available on the axi_rdata bus at this instance. The
  322. // assertion of axi_rvalid marks the validity of read data on the
  323. // bus and axi_rresp indicates the status of read transaction.axi_rvalid
  324. // is deasserted on reset (active low). axi_rresp and axi_rdata are
  325. // cleared to zero on reset (active low).
  326. always @( posedge S_AXI_ACLK )
  327. begin
  328. if ( S_AXI_ARESETN == 1'b0 )
  329. begin
  330. axi_rvalid <= 0;
  331. axi_rresp <= 0;
  332. end
  333. else
  334. begin
  335. if (axi_arready && S_AXI_ARVALID && ~axi_rvalid)
  336. begin
  337. // Valid read data is available at the read data bus
  338. axi_rvalid <= 1'b1;
  339. axi_rresp <= 2'b0; // 'OKAY' response
  340. end
  341. else if (axi_rvalid && S_AXI_RREADY)
  342. begin
  343. // Read data is accepted by the master
  344. axi_rvalid <= 1'b0;
  345. end
  346. end
  347. end
  348. // Implement memory mapped register select and read logic generation
  349. // Slave register read enable is asserted when valid address is available
  350. // and the slave is ready to accept the read address.
  351. assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;
  352. /*always @(*)
  353. begin
  354. // Address decoding for reading registers
  355. case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
  356. 2'h0 : reg_data_out <= slv_reg0;
  357. 2'h1 : reg_data_out <= slv_reg1;
  358. 2'h2 : reg_data_out <= slv_reg2;
  359. 2'h3 : reg_data_out <= slv_reg3;
  360. default : reg_data_out <= 0;
  361. endcase
  362. end
  363. // Output register or memory read data
  364. always @( posedge S_AXI_ACLK )
  365. begin
  366. if ( S_AXI_ARESETN == 1'b0 )
  367. begin
  368. axi_rdata <= 0;
  369. end
  370. else
  371. begin
  372. // When there is a valid read address (S_AXI_ARVALID) with
  373. // acceptance of read address by the slave (axi_arready),
  374. // output the read dada
  375. if (slv_reg_rden)
  376. begin
  377. axi_rdata <= reg_data_out; // register read data
  378. end
  379. end
  380. end */
  381. // Add user logic here
  382. assign wr_en = slv_reg_wren;
  383. assign wr_addr = axi_awaddr;
  384. assign wr_data = S_AXI_WDATA;
  385. assign rd_en = slv_reg_rden;
  386. assign rd_addr = axi_araddr;
  387. assign S_AXI_RDATA = rd_data;
  388. // User logic ends
  389. endmodule

然后是顶层模块,记得例化也要加上 新定义的信号。

(2)ps_wr_rd_ctrl

  1. module ps_wr_rd_ctrl(
  2. input sys_clk,
  3. input sys_rst_n,
  4. // connect to module"axi_lite_slave"
  5. input wr_en,
  6. input [31:0] wr_data,
  7. input [3:0] wr_addr,
  8. input rd_en,
  9. input [3:0] rd_addr,
  10. output reg [31:0] rd_data,
  11. input temp_sign,
  12. input [6:0] temp_data_reg,
  13. output sw_ctrl,
  14. output set_en,
  15. output [9:0] set_freq_step
  16. );
  17. reg sw_ctrl_reg;
  18. reg [31:0] set_en_and_step_reg;
  19. assign sw_ctrl = sw_ctrl_reg;
  20. assign set_en = set_en_and_step_reg[0];
  21. assign set_freq_step = set_en_and_step_reg[17:8];
  22. // receive data form ps
  23. always @(posedge sys_clk or negedge sys_rst_n) begin
  24. if (!sys_rst_n) begin
  25. sw_ctrl_reg <= 1'b0;
  26. set_en_and_step_reg <= 'd0;
  27. end
  28. else if (wr_en) begin
  29. case(wr_addr)
  30. 0 : sw_ctrl_reg <= wr_data[0];
  31. 4 : set_en_and_step_reg <= wr_data;
  32. default : ;
  33. endcase
  34. end
  35. else begin
  36. sw_ctrl_reg <= sw_ctrl_reg;
  37. set_en_and_step_reg <= 'd0;
  38. end
  39. end
  40. // send data to ps
  41. always @(posedge sys_clk or negedge sys_rst_n) begin
  42. if (!sys_rst_n) begin
  43. rd_data <= 'd0;
  44. end
  45. else if (rd_en) begin
  46. case(rd_addr)
  47. 0 : rd_data[0] <= temp_sign;
  48. 4 : rd_data[6:0] <= temp_data_reg;
  49. default : ;
  50. endcase
  51. end
  52. else begin
  53. rd_data <= 'd0;
  54. end
  55. end
  56. endmodule

(3)breath_led

  1. module breath_led(
  2. input wire sys_clk,
  3. input wire sys_rst_n,
  4. input wire sw_ctrl, //呼吸灯开关控制信号,10
  5. input wire set_en, //设置呼吸灯频率的设置使能信号,1设置有效 0无效
  6. input [9:0] set_freq_step, //设置呼吸灯频率变化步长
  7. output wire led
  8. );
  9. parameter START_FREQ_STEP = 10'd100; //设置频率步长初始值
  10. reg [15:0] period_cnt; //周期计数器
  11. reg [15:0] duty_cycle; //高电平占空比的计数器
  12. reg [9:0] freq_step; //呼吸灯频率间隔步长
  13. reg inc_dec_flag; //为1时表示占空比递减,为0时表示占空比递增
  14. wire led_t;
  15. assign led_t = (period_cnt <= duty_cycle) ? 1'b1 : 1'b0;
  16. assign led = led_t & sw_ctrl;
  17. //period_cnt:0-50_000
  18. always@(posedge sys_clk or negedge sys_rst_n) begin
  19. if((!sys_rst_n) || (!sw_ctrl))
  20. period_cnt <= 16'b0;
  21. else if(period_cnt == 16'd50_000)
  22. period_cnt <= 16'b0;
  23. else
  24. period_cnt <= period_cnt + 1'b1;
  25. end
  26. //设置频率间隔freq_step(0-1000),通过输入信号set_freq_step和set_en控制
  27. always@(posedge sys_clk or negedge sys_rst_n) begin
  28. if(!sys_rst_n)
  29. freq_step <= START_FREQ_STEP;
  30. else if(set_en) begin
  31. if(set_freq_step == 1'b0)
  32. freq_step <=10'd1;
  33. else begin
  34. if(set_freq_step >= 10'd1000)
  35. freq_step <= 10'd1000;
  36. else
  37. freq_step <= set_freq_step;
  38. end
  39. end
  40. end
  41. //调节高电平占空比的计数值duty_cycle
  42. always@(posedge sys_clk or negedge sys_rst_n) begin
  43. if((!sys_rst_n) || (!sw_ctrl)) begin
  44. duty_cycle <= 16'd0;
  45. inc_dec_flag <= 1'b0;
  46. end
  47. //每次计数完一个周期(0-50_000),就调节占空比计数值duty_cycle
  48. else if(period_cnt == 16'd50_000) begin
  49. if(inc_dec_flag) begin //占空比递减
  50. if(duty_cycle == 16'd0)
  51. inc_dec_flag <= 1'b0;
  52. else if(duty_cycle < freq_step)
  53. duty_cycle <= 16'd0;
  54. else
  55. duty_cycle <= duty_cycle - freq_step;
  56. end
  57. else begin //占空比递增(也正是默认状态)
  58. if(duty_cycle >= 16'd50_000)
  59. inc_dec_flag <= 1'b1;
  60. else
  61. duty_cycle <= duty_cycle + freq_step;
  62. end
  63. end
  64. else //duty_cycle未计完一个周期,占空比保持不变
  65. duty_cycle <= duty_cycle;
  66. end
  67. endmodule

(4)key_NumGen

  1. module key_NumGen(
  2. input clk,
  3. input rst_n,
  4. input Key,
  5. output reg temp_sign, //表示按下的状态
  6. output reg [6:0] temp_data_reg //数据
  7. );
  8. always@(posedge clk or negedge rst_n) begin
  9. if(!rst_n) begin
  10. temp_sign <= 1'b0;
  11. temp_data_reg <= 7'b0;
  12. end
  13. else begin
  14. if(Key) begin //未按下
  15. temp_sign <=1'b0;
  16. temp_data_reg <= 7'b1111111;
  17. end
  18. else begin //按下
  19. temp_sign <= 1'b1;
  20. temp_data_reg <= 7'b1000001;
  21. end
  22. end
  23. end
  24. endmodule

(5)ZYNQ_ultrascale+MPSoc

       也就是PS端的ARM,进行的配置主要有:

 2、搭建Vitis-sdk工程

        PS端的C语言实现比较容易,有一点需要注意的是使用Xil_In/Out函数时的地址要和Vivado里分配的地址相匹配。代码就简单贴出来:

3、实验结果

        打开串口终端,结果表明:当KEY没被按下时会收到data=127,当KEY被按下时data=65。PS读取PL数据成功。

        此外,板子上的LED呼吸灯闪烁,说明PS向PL写入数据成功。(忘记拍照片了)

 参考:FPGA:基于AXI4_Lite的PS与PL交互项目、[3-4]程序设计、ZYNQ PS与PL交互专题_哔哩哔哩_bilibili

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/412124
推荐阅读
相关标签
  

闽ICP备14008679号