学习实战篇---通用卷积神经网络加速器的verilog实现(二)---axi-gpio实验
手写axi-gpio,arm控制pl端4个led实现流水灯
·
一.axi-gpio模块设计(通过ps端控制4个led,实现流水灯实验)
在之前已经介绍了axi-lite的5个通道,分别是读地址,读数据,写地址,写数据,写响应,本模块AXI-GPIO相对于主机arm上的axi-master接口,要做一个与之对应的axi-slave接口,然后就是时钟,复位,右端就是双向的gpio
1.AR channel &Rd channel
//Rd channel
assign S_AXI_ARREADY=1'b1;
assign S_AXI_RRESP=2'b0;//设定读永远没有错
reg [32-1:0]rdata;
assign S_AXI_RDATA=rdata;
reg rvalid;
assign S_AXI_RVALID=rvalid;
always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN)
if(~S_AXI_ARESETN)
begin rvalid<=1'b0;rdata<=32'b0;end
else
if(S_AXI_ARVALID&S_AXI_ARREADY)
begin
rvalid<=1'b1;
case(S_AXI_ARADDR[3:2])
2'd0:rdata<={28'b0,reg0};
2'd1:rdata<={28'b0,reg1};
2'd2:rdata<={28'b0,reg2};
2'd3:rdata<=0;
endcase
end
else
if(S_AXI_RVALID&S_AXI_RREADY)
rvalid<=1'b0;
2.Wr channel
//Wr channel 接收数据不可以早于接收地址通道,也就是主机发送地址过来,要当前周期或者之后周期才可以接收数据
reg wphase; //该寄存器表示是否有收到写地址,0:没有收到/写完成;1:收到了地址
always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN)
if(~S_AXI_ARESETN)
wphase<=0;
else
if(S_AXI_AWVALID&S_AXI_AWREADY)
wphase<=1;
else
if(S_AXI_WVALID&S_AXI_WREADY)
wphase<=0;
assign S_AXI_WREADY=wphase;
//主机只能访问reg0和reg1,访问的是高两位,如果写reg0就写0,如果写reg1就写4
always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN)
if(~S_AXI_ARESETN)
begin
reg0<=0;
reg1<=0;
end
else
if(S_AXI_WVALID&S_AXI_WREADY)
case(addr_word_w_comb)
2'd0:begin if(S_AXI_WSTRB[0]) reg0<=S_AXI_WDATA[3:0];end//写的是reg0,如果写的低4bit有效,就把写数据(32bit)的低4bit写到reg0
2'd1:begin if(S_AXI_WSTRB[0]) reg1<=S_AXI_WDATA[3:0];end//写的是reg1,如果写的低4bit有效,就把写数据(32bit)的低4bit写到reg1
endcase
3.AW channel
//AW channel 这里有一个问题是写数据和写地址同时到的情况,addr_word_w表示的是寄存器暂存的值
reg [1:0]addr_word_w;
wire [1:0]addr_word_w_comb; //这里的addr_word_w_comb解决的是-是否写命令和数据同时来
always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN)
if(~S_AXI_ARESETN)
addr_word_w<=0;
else
if(S_AXI_AWVALID&S_AXI_AWREADY)
addr_word_w<=S_AXI_AWADDR[3:2];
assign addr_word_w_comb=(S_AXI_AWVALID&S_AXI_AWREADY)?S_AXI_AWADDR[3:2]:addr_word_w;
assign S_AXI_AWREADY=1'b1;
4.Wr Resp
//Wr Resp
assign S_AXI_BRESP=2'b0;//主机写了之后,从机要给主机返回一个结果,这里表示写成功的
reg axi_bvalid; //当主机写成功了,就把bvalid拉高,当从机收到响应就拉低
assign S_AXI_BVALID=axi_bvalid;
always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN)
if(~S_AXI_ARESETN)
axi_bvalid<=1'b0;
else
if(S_AXI_WVALID&S_AXI_WREADY)
axi_bvalid<=1'b1;
else
if(S_AXI_BREADY)
axi_bvalid<=1'b0;
5.sdk 代码
#include <stdio.h>
#include platform.h
#include xil_printf.h
#include xparameters.h
#include sleep.h
int main()
{
init_platform();
print(Hello World\n\r);
//设置输入输出模式
(unsigned int)(XPAR_AXI_GPIO_MY_1_BASEADDR+4)=0xF; //dev1.REG1 输出
int i = 1;
while(1){
*(unsigned int*)(XPAR_AXI_GPIO_MY_1_BASEADDR+0)=i; //dev1.REG0 写数据
i = i <<1;
if(i==0x10) i = 1;
sleep(1);
}
cleanup_platform();
return 0;
}
二.上板演示
更多推荐
已为社区贡献3条内容
所有评论(0)