前言:
在使用单片机的适合, Io口有寄存器,然后我们使用KEIL来编程,直接操作寄存器就可以实现操作IO的效果
在FPGA中,也可以这样做, SDK中直接操作地址,就可以实现操作IO口的效果, 相当于自己设计IO的寄存器
新建user_gpio.v
代码如下, 目的是为了把AXI总线和FPGA外部引脚联系起来
module user_gpio(
input wire gpio_input,
output wire [3:0] gpio_output,
output wire zynq_gpio_input,
input wire [3:0] zynq_gpio_output
);
assign zynq_gpio_input = gpio_input;
assign gpio_output[3:0]=zynq_gpio_output[3:0];
endmodule
然后下面就是打包
设置IP名称等
我们一共有一个IO口输入,一个IO输出, 所以需要2个就可以了, 但是最低是4个
就会生成一个新的工程, 我们编辑这个工程就可以
在user to add ports这里加入代码, 这里是填写对外接口
input wire gpio_input,
output wire [3:0] gpio_output,
内部的代码里面也添加这个代码,和上面的一样的
在最顶层实例化gpio
.gpio_input(gpio_input),
.gpio_output(gpio_output),
然后把112行的不用的寄存器去掉, 因为我们只用了2个,AXI总线读取数据用wire, 设置输出用reg,
所以 slv_reg0设置为reg, 代表输出, reg1设置wire 用于读取
注释掉227
屏蔽h1到default
注释掉default
屏蔽378 379
到这里AXI寄存器就处理完了
把之前的user_gpio添加到工程中
然后例化到user_gpio_in_output_v1_0_s00_axi中
wire zynq_gpio_input;
wire [3:0] zynq_gpio_output;
assign zynq_gpio_output[3:0]=slv_reg0;
assign slv_reg1=zynq_gpio_input;
user_gpio user_gpio_inst
(
.gpio_input(gpio_int),
.gpio_output(gpio_output),
.zynq_gpio_input(zynq_gpio_input),
.zynq_gpio_output(zynq_gpio_output)
);
然后完成之后关闭这个工程,打开以前的工程
就可以看到AXI perpheral 添加的东西了
把以前的user_gpio.v删除掉 ,创建bd文件 然后勾选串口
直接输入user 添加IP
如果在这里没看到gpio_output input,那就回去重新打包一下, 只是tools那个重新打包就可以了, 然后重新打开工程一下就有了
然后output和input上把信号引出来
最终如图
最后右边可以看寄存器地址
然后project manager生成2次文件, 管脚约束, 生成bit流就可以了
control+S 保存
编译
下载
最后在vitis中代码如下
#include
#include "platform.h"
#include "xil_printf.h"
#include "sleep.h"
#include "string.h"
#define IIC_BASE 0x43C00000
#define REG0_OFFSET 0
#define REG1_OFFSET 4
u32 gpio_input_value = 0;
char buf_print[64]={0};
int i = 0;
int main()
{
init_platform();
print("Hello World fpga packet\n\r");
while(1)
{
for(i=0;i<64;i++)
{
buf_print[i]=0;
}
gpio_input_value=Xil_In32(IIC_BASE + REG1_OFFSET);
sprintf(buf_print,"input gpio value:%d\r\n",gpio_input_value);
printf(buf_print);
Xil_Out32(IIC_BASE+REG0_OFFSET,0);
sleep(1);
Xil_Out32(IIC_BASE+REG0_OFFSET,0xffffffff);
sleep(1);
}
cleanup_platform();
return 0;
}