ZYNQ 不用DMA的HP总线使用

一,vivado工程配置

1,ZYNQ7 Processing System 中,HP Slave AXI Interface --> S AXI HP0 Interface,勾选 S AXI HP0 Interface 并且在展开的 AXI HP0 DATA WIDTH 后面选择数据位宽是 64(位宽可以配置为 32bit 或者64bit)。

 2,按照如图引出来

3,Address Editor 中,由于新增加的 AXI_HP0 总线地址还未做映射,所以如图所示,点击左侧的 Auto Assign Address 进行自动地址分配。完成地址映射后,如图所示,AXI_HP0 默认分配了偏移地址(Offset Address0x0 开始 1G 内存空间,这 1G 的地址空间是 AXI_HP0 可访问的地址空间。DDR3 也会默认映射到这一段地址空间中。通过 AXI_HP0 就可以实现 DDR3 的读写了。

 二,PL端HP总线设置

上面配置是在PS端进行配置的,PL端也需要verilog HP总线进行数据读写

1,AXI HP总线,PL到PS端进行数据写设置:

`timescale  1 ns/10ps

module axi_hp0_wr(
				//系统信号
			input				rst_n,                   
				//写入DDR3的数据         
			input				i_clk,
			input 				i_data_rst_n,			
			input				i_data_en,
			input[15:0]	       	i_data,
			input[31:0] 		i_ddr3_saddr, 
				//AXI总线时钟
			input				AXI_clk,
				//AXI写地址通道
			(*mark_debug = "true"*) output reg[31:0]	AXI_awaddr,	
			output[3:0] 		AXI_awlen,
			output[2:0] 		AXI_awsize,
			output[1:0] 		AXI_awburst,
			output[1:0]			AXI_awlock,
			output[3:0] 		AXI_awcache,
			output[2:0] 		AXI_awprot,
			output[3:0] 		AXI_awqos,
			(*mark_debug = "true"*) output reg			AXI_awvalid,	
			(*mark_debug = "true"*) input 				AXI_awready,	
				//AXI写数据通道
			(*mark_debug = "true"*) output[63:0] AXI_wdata,
			output[7:0] 		AXI_wstrb,	
			(*mark_debug = "true"*) output reg			AXI_wlast,
			(*mark_debug = "true"*) output reg			AXI_wvalid,	
			(*mark_debug = "true"*) input 				AXI_wready,	
				//AXI写响应通道
			input[5:0] 		AXI_bid,
			(*mark_debug = "true"*) input[1:0] 			AXI_bresp,
			(*mark_debug = "true"*) input 				AXI_bvalid,	
			(*mark_debug = "true"*) output 				AXI_bready
		);
//内部信号申明
reg  		fifo_rd_en;
wire[7:0]	fifo_data_count;					
reg[7:0] 	wrdata_num;
reg[3:0]    cstate,nstate;

parameter AXI_BURST_LEN	= 16;
parameter STATE_RST  = 4'h0;	
parameter STATE_IDLE = 4'h1; 
parameter STATE_WADD = 4'h2;
parameter STATE_WDAT = 4'h3; 	 
parameter WRITE_DONE = 4'h4;    

//------------------------------------------------------------------------------------
//将i_data_rst_n在AXI_clk时钟域打一拍
reg w_data_rst_n;

always @(posedge AXI_clk)
	w_data_rst_n <= i_data_rst_n; 		

//-------------------------------------------------------------------------------
//FIFO缓存写入DDR3数据

fifo_generator_0 	uut_fifo_generator_0 (
  .rst(~rst_n || ~w_data_rst_n),  // input wire rst
  .wr_clk(i_clk),                // input wire wr_clk
  .rd_clk(AXI_clk),                // input wire rd_clk
  .din(i_data),                      // input wire [15 : 0] din
  .wr_en(i_data_en),                  // input wire wr_en
  .rd_en(fifo_rd_en),                  // input wire rd_en
  .dout({AXI_wdata[15:0],AXI_wdata[31:16],AXI_wdata[47:32],AXI_wdata[63:48]}),                    // output wire [63 : 0] dout
  .full(),                    // output wire full
  .empty(),                  // output wire empty
  .rd_data_count(fifo_data_count)  // output wire [7 : 0] rd_data_count
);

//-------------------------------------------------------------------------------
//AXI写状态机

always @(posedge AXI_clk or negedge rst_n)begin
	if(~rst_n)begin
		cstate <= STATE_RST;
	end
	else begin
		cstate <= nstate;
	end
end 
                                                     																										
always @( * )begin
	case(cstate)
    STATE_RST: begin
        if(w_data_rst_n) nstate = STATE_IDLE;
        else nstate = STATE_RST;
    end
    STATE_IDLE: begin
		if(!w_data_rst_n) nstate = STATE_RST;
		else if(fifo_data_count >= AXI_BURST_LEN) nstate = STATE_WADD;
        else nstate = STATE_IDLE;
    end
	
	STATE_WADD: begin
		if(AXI_awvalid && AXI_awready) nstate = STATE_WDAT;
		else nstate = STATE_WADD;
	end    
    
	STATE_WDAT: begin
		if(wrdata_num >= (AXI_BURST_LEN+1)) nstate = WRITE_DONE;
        else nstate = STATE_WDAT;
    end
	
	WRITE_DONE: begin
		if(AXI_bvalid) nstate = STATE_IDLE;
		else nstate = WRITE_DONE;
	end
    
    default: begin
        nstate = STATE_RST;
    end
endcase
end

	//1个burst写入数据的个数计数
always @(posedge AXI_clk) begin                                                                
	if (!rst_n) wrdata_num <= 'b0;                                                           
	else if(cstate == STATE_WDAT) begin 
		if(wrdata_num == 8'd0) wrdata_num <= wrdata_num + 1'b1; 
		else if((wrdata_num <= AXI_BURST_LEN) && AXI_wready && AXI_wvalid) wrdata_num <= wrdata_num + 1'b1;              
		else wrdata_num <= wrdata_num;
	end                                                              
	else wrdata_num <= 'b0;                                               
end 
	
//-------------------------------------------------------------------------------
//FIFO读取时能信号产生

always @(*) begin                                                                
	if (cstate == STATE_WDAT) begin
		if(wrdata_num == 8'd0) fifo_rd_en <= 1'b1;
		else if((wrdata_num >= 8'd1) && (wrdata_num < AXI_BURST_LEN) && AXI_wready && AXI_wvalid) fifo_rd_en <= 1'b1;
		else fifo_rd_en <= 1'b0;
	end
	else fifo_rd_en <= 1'b0;                                 
end

//-------------------------------------------------------------------------------
//AXI总线写数据时序产生

	//写地址产生
always @(posedge AXI_clk)begin
	if(!w_data_rst_n) AXI_awaddr <= i_ddr3_saddr; 
	else if(AXI_awvalid && AXI_awready) AXI_awaddr <= AXI_awaddr + AXI_BURST_LEN * 8; 
end

	//写地址有效信号产生
always @(posedge AXI_clk) begin                                                                
	if (!rst_n) AXI_awvalid <= 1'b0;                                                               
	else if(cstate == STATE_WADD) begin
		if(AXI_awvalid && AXI_awready) AXI_awvalid <= 1'b0;                                                        
		else AXI_awvalid <= 1'b1;
	end
	else AXI_awvalid <= 1'b0;                                 
end    

	//写数据有效信号产生
always @(posedge AXI_clk) begin                                                                
	if (!rst_n) AXI_wvalid <= 1'b0;
	else if((wrdata_num >= 8'd1) && (wrdata_num < AXI_BURST_LEN)) AXI_wvalid <= 1'b1; 
	else if((wrdata_num == AXI_BURST_LEN) && !AXI_wready) AXI_wvalid <= 1'b1;
	else AXI_wvalid <= 1'b0;                                 
end

	//写最后一个数据有效信号产生
always @(posedge AXI_clk) begin                                                                
	if (!rst_n) AXI_wlast <= 1'b0;                                                               
	else if((wrdata_num == (AXI_BURST_LEN - 1)) && AXI_wready && AXI_wvalid) AXI_wlast <= 1'b1;  
	else if((wrdata_num == AXI_BURST_LEN) && !AXI_wready) AXI_wlast <= 1'b1;
	else AXI_wlast <= 1'b0;                                 
end

assign AXI_awsize	= 3'b011;	//8 Bytes per burst
assign AXI_awburst	= 2'b01;
assign AXI_awlock	= 2'b00;
assign AXI_awcache	= 4'b0010;
assign AXI_awprot	= 3'h0;
assign AXI_awqos	= 4'h0;
assign AXI_wstrb	= 8'hff;
assign AXI_bready 	= 1'b1;
assign AXI_awlen 	= AXI_BURST_LEN - 1; 
endmodule

其中fifo配置:

fifo_generator_0     uut_fifo_generator_0 (
  .rst(~rst_n || ~w_data_rst_n),   // input wire rst
  .wr_clk(i_clk),                // input wire wr_clk
  .rd_clk(AXI_clk),                // input wire rd_clk
  .din(i_data),                      // input wire [15 : 0] din
  .wr_en(i_data_en),                  // input wire wr_en
  .rd_en(fifo_rd_en),                  // input wire rd_en
  .dout({AXI_wdata[15:0],AXI_wdata[31:16],AXI_wdata[47:32],AXI_wdata[63:48]}),
  .full(),                    // output wire full
  .empty(),                  // output wire empty
  .rd_data_count(fifo_data_count)  // output wire [7 : 0] rd_data_count
);

2,AXI HP总线读取数据

`timescale  1 ns/10ps

module axi_hp0_rd(
				//系统信号
			input				rst_n,                   
				//写入DDR3的数据         
			input				i_clk,
			input 				o_data_rst_n,
			input				o_data_en,
			input[31:0]			o_ddr3_saddr,
				//AXI总线时钟
			input				AXI_clk,
				//AXI读地址通道
			(*mark_debug = "true"*) output[31:0]AXI_araddr,
			output[1:0]		AXI_arburst,
			output[3:0]		AXI_arcache,			
			output[3:0]		AXI_arlen,
			output[1:0]		AXI_arlock,
			output[2:0]		AXI_arprot,
			output[3:0]		AXI_arqos,
			(*mark_debug = "true"*) input				AXI_arready,
			output[2:0]		AXI_arsize,
			(*mark_debug = "true"*) output 				AXI_arvalid,
				//AXI读数据通道
			(*mark_debug = "true"*) input[63:0]			AXI_rdata,
			input[5:0]		AXI_rid,
			(*mark_debug = "true"*) input 				AXI_rlast,
			(*mark_debug = "true"*) output 				AXI_rready,
			(*mark_debug = "true"*) input[1:0]			AXI_rresp,
			(*mark_debug = "true"*) input 				AXI_rvalid			
		);
 
parameter AXI_BURST_LEN	= 16;
assign AXI_araddr = o_ddr3_saddr;
assign AXI_arvalid = o_data_en;
assign AXI_arsize	= 3'b011;	//8 Bytes per burst
assign AXI_arburst	= 2'b01;
assign AXI_arlock	= 2'b00;
assign AXI_arcache	= 4'b0010;
assign AXI_arprot	= 3'h0;
assign AXI_arqos	= 4'h0;
assign AXI_rready 	= 1'b1;
assign AXI_arlen 	= AXI_BURST_LEN - 1; 
endmodule

 3,数据控制

`timescale  1 ns/10ps

module axi_hp0_source(
				//系统信号
			input			rst_n,                     
			input			clk,
			//读出DDR3的数据
			output 			o_data_rst_n,
			output reg		o_data_en,
			output [31:0]		o_ddr3_saddr,
				//写入DDR3的数据     			
			output 		    i_data_rst_n,			
			output reg	    i_data_en,
			output reg[15:0]    i_data,
			output[31:0] 	    i_ddr3_saddr
		);
 
parameter MAX_CNT_1S = 32'd100_000_000-1; 	//1s计数最大值,时钟为100MHz(10ns)
//1s定时
reg[31:0] cnt;
always @(posedge clk or negedge rst_n)
	if(!rst_n) cnt <= 32'd0;
	else if(cnt < MAX_CNT_1S) cnt <= cnt+1'b1;
	else cnt <= 32'd0;

wire timer_wr_en = (cnt >= MAX_CNT_1S-1000) & (cnt < MAX_CNT_1S-1000+64);
assign i_data_rst_n = ~((cnt >= MAX_CNT_1S-10_000) & (cnt < MAX_CNT_1S-10_000+64));
wire timer_rd_en = (cnt == MAX_CNT_1S-10);
//------------------------------------------------------------------------------------
//产生定时数据写入

always @(posedge clk or negedge rst_n)
	if(!rst_n) i_data_en <= 1'b0;
	else i_data_en <= timer_wr_en;

always @(posedge clk or negedge rst_n)
	if(!rst_n) i_data <= 16'd0;
	else if(!i_data_rst_n) i_data <= 16'h0000;
	else if(timer_wr_en) i_data <= i_data+1'b1;

assign i_ddr3_saddr = 32'h0100_0000;	

//------------------------------------------------------------------------------------
//产生定时数据读取

always @(posedge clk or negedge rst_n)
	if(!rst_n) o_data_en <= 1'b0;
	else o_data_en <= timer_rd_en;

assign o_data_rst_n = i_data_rst_n;

assign o_ddr3_saddr = 32'h0100_0000;	
	
endmodule

三,SDK下载触发验证和信号抓取:

 

 

猜你喜欢

转载自blog.csdn.net/wangjie36/article/details/119297947