AXI4 Traffic Generator仿真研究与自定义IP(之五) - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki

AXI4 Traffic Generator仿真研究与自定义IP(之五)

1)目标

  • 将自定义的uart_tx/rx ip,用axi4_lite接口封装起来
  • 用ATG进行仿真,确认功能正确
  • 用mb写软件驱动,确认功能正确

2)uart_ip关键代码

AXI4_Lite封装代码

接口部分

		// Users to add ports here
        input wire rx,
        output wire tx,
		// User ports ends

信号定义部分,特别要注意,多位宽的wire型一定要定义才能使用,否则会出错。定义要放在开头部分。

    wire [7:0] po_data;
    wire pi_flag;
    wire po_flag;	

寄存器读写部分(只需要在寄存器写部分,增加相关逻辑即可)

	always @( posedge S_AXI_ACLK )
	begin
	  if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      slv_reg0 <= 0;
	      slv_reg1 <= 0;
	      slv_reg2 <= 0;
	      slv_reg3 <= 0;
	      slv_reg4 <= 0;
	      slv_reg5 <= 0;
	      slv_reg6 <= 0;
	      slv_reg7 <= 0;
	    end 
	  else if(po_flag) begin               //增加的部分
	      slv_reg1[7:0]<=po_data;          //增加的部分
	      slv_reg2[0]<=1;                  //增加的部分
	  end                                  //增加的部分
	  else begin
	    if (slv_reg_wren)

模块例化部分

	// Add user logic here
uart_rx uart_rx_inst(
    .sys_clk(S_AXI_ACLK),
    .sys_rst_n(S_AXI_ARESETN),
    .rx(rx),
    
    .po_data(po_data),
    .po_flag(po_flag)
);

uart_tx uart_tx_inst(
    .sys_clk(S_AXI_ACLK),
    .sys_rst_n(S_AXI_ARESETN),
    .pi_data(slv_reg0[7:0]),
    .pi_flag(pi_flag),
    
    .tx(tx)
);

/* tx_reg: reg0
   rx_reg: reg1
   rx_flag: re2
   */
assign pi_flag=(slv_reg_wren && axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]==2'h0)? 1:0;

3)系统设计,用ATG驱动

  • 当时出错了,通过这个仿真找到了错误。这个还是很实用的。
  • 另一个问题,不要在底层IP中使用ILA,会导致上层调用IP仿真的时候报错。如果要使用ILA,可以用mark_debug模式,不用修改代码,也能看到底层信号。

4)用microblaze控制

image image

引脚定义pin_local.xdc

set_property -dict {PACKAGE_PIN B20 IOSTANDARD LVCMOS33} [get_ports led]
set_property -dict {PACKAGE_PIN D20 IOSTANDARD LVCMOS33} [get_ports done_pulse]

set_property -dict {PACKAGE_PIN H18 IOSTANDARD LVCMOS33} [get_ports {start_pulse[0]}]
set_property -dict {PACKAGE_PIN F20 IOSTANDARD LVCMOS33} [get_ports {start_pulse[1]}]
set_property -dict {PACKAGE_PIN G20 IOSTANDARD LVCMOS33} [get_ports {start_pulse[2]}]
set_property -dict {PACKAGE_PIN H20 IOSTANDARD LVCMOS33} [get_ports {start_pulse[3]}]

# GPIO1-EDA_V3
set_property -dict {PACKAGE_PIN W14 IOSTANDARD LVCMOS33} [get_ports txd]
set_property -dict {PACKAGE_PIN Y14 IOSTANDARD LVCMOS33} [get_ports rxd]

程序设计

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"
#include "sleep.h"

#define UART_IP_BASEADDR XPAR_MY_UART_0_S00_AXI_BASEADDR

void test_wr()
{
    Xil_Out32(UART_IP_BASEADDR, 0x1);
    Xil_Out32(UART_IP_BASEADDR+0x4, 0xAA);
    Xil_Out32(UART_IP_BASEADDR+0x8, 0x55);
    xil_printf("%x\r\n", Xil_In32(UART_IP_BASEADDR));
    xil_printf("%x\r\n", Xil_In32(UART_IP_BASEADDR+0x4));
    xil_printf("%x\r\n", Xil_In32(UART_IP_BASEADDR+0x8));

    while(1);
}

void send_str(char *str)
{
	char *p=str;
	while(*p){
		Xil_Out8(UART_IP_BASEADDR+0x0, *p++);
		usleep(1000);
	}

}

void recv_char()
{
	u8 done=Xil_In8(UART_IP_BASEADDR+0x8);   //po_flag
	if(done){
		char c=Xil_In8(UART_IP_BASEADDR+0x4);
		Xil_Out8(UART_IP_BASEADDR+0x0, c);
		Xil_Out8(UART_IP_BASEADDR+0x8, 0);
	}
}



int main()
{
    init_platform();

    //test_wr();
	send_str("hello world!\r\n");
	send_str("hello world!\r\n");
	send_str("hello world!\r\n");
	sleep(1);

    while(1){
    	recv_char();
    }

    cleanup_platform();
    return 0;
}

5)运行结果

image

6)打开synthesized后的电路图,用mark_debug方式调用ILA,查看uart_tx/rx的底层信号

mark_debug会修改pin_local.xdc文件,添加很多语句。存在的问题,综合后一些信号找不到了。 image

7)更好的mark_debug方式,避免信号被优化

image image 为了避免综合后信号找不到,另一种更好的方式是,在接口定义前面加上(mark_debug="true")

image image 综合后,直接打开mark_debug界面,可见它自动找到所有我们mark_debug的信号,非常方便。

image 设置完后,所有mark的信号都显示为已分配。

image 调试结果

⚠️ **GitHub.com Fallback** ⚠️