基于FPGA的循迹小车,控制器:Xilinx-Ego1

记录FPGA(Xilinx-Ego1)学习调试时遇到的坑和Bug解决方法,以及Vivado开发FPGA的代码编写技巧,为之后复习留个底子。通篇文章均用单片机的开发思路去开发FPGA,只为帮助读者能快速上手,开发语言为最常用的Verilog。

关于如何使用Vivado创建一个工程见Ego1使用说明文档,很详细,详细见 依元素 官网:EGO1 (e-elements.com)

点击资源,然后注册邮箱,下载资料包,里面有很多例程:

源码或者现成的工程见 3c-EGo1配置实验vivado2017.2_v1.2 文件夹里的source与project文件夹

学习了基础操作后,教你怎么写代码,先对整个代码有个宏观认识:

         这是一个工程的文件夹,里面只有lab5_uart.srcs文件夹里的代码是自己写或者创建的,其余是你在仿真综合时,vivado自动生成的;代码分两大部分:约束文件(.xdc)和源文件(.v)

       讲解一下我对Vivado编写FPGA工程的认识:

        源文件(.v)文件编写逻辑为分层(top层和模块层)编写,将你需要用到的硬件的驱动代码设计成一个模块,模块即有输入和输出,比方说我要让一个数码管按一定的频率亮,那就需要定时器,就设计一个时钟作为输入,当然,你想复位的话,还可以设计一个按键(rst)作为输入,然后输出呢就是数码管的8个段(8段LED),设计好输入输出后就是你的逻辑编写,即你什么时候让数码管亮,比如我1s让数码管亮一次,1s后再灭一次,就写相应的逻辑,当然写逻辑就要用到相关的语法,语法就去菜鸟教程看verilog语言教程就行;然后是需要即需要定义一个top层,将你所有模块的输入和输出在这个模块进行例化(相当于单片机的引脚初始化)。top层是在你设计的功能模块在2个及以上时编写,这样你看起来也比较方便,系统所有的输入输出都在top层,也方便你查看。

        约束文件的作用相当于在使用单片机时对引脚进行定义,这里是将你源文件的top文件里设计的输入和输出约束到相关的引脚上,虽然像时钟,数码管这样的输入输出你看不见引脚,但你可以这样去理解,就是使用FPGA驱动硬件的逻辑就是:你设计输入和输出,然后将他们约束到相关硬件上或者引脚上,然后引脚再去接硬件。

        那么我这个工程呢就是关于Ego1的循迹小车,所有硬件驱动代码都由ego1写成他具备以下功能:

       基础功能:能用Ego1输出PWM波控制直流编码器电机和舵机转动,能用Ego1读取红外循迹模块的循迹反馈信号,能用Ego1的输入捕获采集编码器的信号实现电机转速测量,能用Ego1输出特定频率的方波驱动无缘蜂鸣器播放音乐,能用Ego1的数码管显示车速。

        终极功能:小车上电后能在赛道上一边播放车载音乐一边进行自动循迹。

系统硬件配置设计

(根据实验的需要,论述平台的系统硬件配置,包括硬件选择、硬件配套、网络连接和参数配置等

(1)控制器:Xilinx-Ego1(FPGA)

(2)执行元件:舵机

(3)执行元件:编码器电机

(4)执行元件:无源蜂鸣器

(5)测量元件:循迹模块(5路红外传感器)

(6)电机驱动:tb6612fng

(7)功率放大单元:L298N

(8)稳压模块:

其中舵机和电机模块的代码展示如下:(因为都是PWM,所以写在一起了)

时钟主频:clk约束到了P17,具体是50MHz还是100MHz我忘了

`timescale 1ns / 1ps

module  pwm_cont(
				clk,
				sw7,
				rst_n,
				da_in,
				pwm_out,
				pwm_outz,
				hw_in,
				djfz1,
				djfz2,
				djfy1,
				djfy2,
				pwm_outy
);

input					clk;
input					rst_n;
input					sw7;
input   [6:0]   	da_in;

output	reg		djfz1;
output	reg		djfz2;
output	reg		djfy1;
output	reg		djfy2;

output	reg		pwm_out;
output	reg		pwm_outz;
output	reg		pwm_outy;
input   [4:0]   	hw_in;
parameter          s=1000_000,//20ms-----min:s4(左偏)   max:s7(右偏)   中间:s1
                    
                    s7=190_000,//4ms----右满
                    //s6=190_000,//3.5ms----270
                    s5=185_000,//3ms----225
					s0=175_000,//2.5ms----右
					s1=150_000,//2ms---中间
					s2=125_000,//1.5ms----90
					s3=95_000,//1ms-----45 100_000
					s4=80_000;//0.5ms---0 左满
					
reg	[31:0]   cnt_r;	
reg	[31:0]	cnt;				

reg	[31:0]   cnt_r1;	
reg	[31:0]	cnt1;
reg biaoqian;
reg wr_reg,wr_up,wr_down;


always@(posedge clk or posedge rst_n)    begin
	if(rst_n)
	begin
	    wr_reg		<=		1'b0;
		wr_up		<=		1'b0;
		wr_down		<=		1'b0;      
		cnt_r1 <= s1;
    end
	else
		begin
		wr_reg		<=		sw7;
		wr_up		<=		sw7&(~wr_reg);//sw1上升沿检测,选择循迹模式
		wr_down		<=		~sw7&wr_reg;
		if(wr_up)
		biaoqian=1;
		if(wr_down)
		biaoqian=0;
		
		if(biaoqian==1)
		begin
		  djfz1=0;
		  djfz2=1;
		  djfy1=0;
		  djfy2=1;
			case(hw_in)
			    5'b00000: 
			    begin
			    //cnt_r1 <= s1;//中间
			    biaoqian<=0;
			    end
			    //5'b11111: cnt_r1 <= s1;//中间
			   
			    5'b11000: cnt_r1 <= s7;//右转s7满
			    5'b11110: cnt_r1 <= s7;//右转s7满
			    5'b11100: cnt_r1 <= s5;//左转
			    5'b11101: cnt_r1 <= s0;//左转
			    5'b11001: cnt_r1 <= s1;//中间
			    5'b11011: cnt_r1 <= s1;//中间
			    5'b10011: cnt_r1 <= s1;//中间
			    5'b10111: cnt_r1 <= s2;//右转			    
			    5'b00111: cnt_r1 <= s3;//右转
			    5'b01111: cnt_r1 <= s4;//左转s4满
			    5'b00011: cnt_r1 <= s4;//右转
			    
			endcase
		end
		if(!biaoqian)
		begin
		  djfz1=0;
		  djfz2=0;
		  djfy1=0;
		  djfy2=0;
		end
		end
end

//速度选择
always@(posedge clk or posedge rst_n)begin
	if(rst_n)
	    begin
		cnt_r <= 31'd0;
		end
	else
		begin
//			case(da_in)//速度选择
//			    7'b0000001: cnt_r <= s/20;//90
//				//8'b00000011: cnt_r <= s4;//0
//				7'b0000010: cnt_r <= s/15;//45
//				7'b0000100: cnt_r <= s/10;//90
//				7'b0001000: cnt_r <= s/8;//135
//				7'b0010000: cnt_r <= s/4;//180
//				7'b0100000: cnt_r <= s/2;//225
//				7'b1000000: cnt_r <= s;//满速
				case(hw_in)
				5'b11000: cnt_r <= s/8;//右转s7满
			    5'b11110: cnt_r <= s/7;//右转s7满
			    5'b11100: cnt_r <= s/7;//左转
			    5'b11101: cnt_r <= s/7;//左转
			    5'b11001: cnt_r <= s/5;//中间
			    5'b11011: cnt_r <= s/5;//中间
			    5'b11111: cnt_r <= s/5;//中间
			    5'b10011: cnt_r <= s/5;//中间
			    5'b10111: cnt_r <= s/7;//右转			    
			    5'b00111: cnt_r <= s/7;//右转
			    5'b01111: cnt_r <= s/7;//左转s4满
			    5'b00011: cnt_r <= s/7;//右转
			    5'b00000: cnt_r <= 0;//停止
				default: cnt_r <= s/8;//停止
			endcase
		end
end

always@(posedge clk or negedge rst_n)begin
	if(rst_n)
	begin
		cnt <= 31'd0;
		cnt1 <= 31'd0;
	end
	else if(cnt >= s)
	begin
		cnt <= 31'd0;
		cnt1 <= 31'd0;
	end
	else
	begin
		cnt <= cnt + 1'b1;
		cnt1 <= cnt1 + 1'b1;
	end
end

always@(posedge clk or negedge rst_n)begin
	if(rst_n)
	begin
		pwm_outz <= 1'b0;
		pwm_outy <= 1'b0;
    end
	else if(cnt <= cnt_r)
	begin   
		pwm_outz <= 1'b1;
		pwm_outy <= 1'b1;
		if(wr_down)
	    begin
		  pwm_outz <= 1'b0;
		  pwm_outy <= 1'b0;
		end
	end
	else
	begin
		pwm_outz <= 1'b0;
		pwm_outy <= 1'b0;
	end
end

always@(posedge clk or negedge rst_n)begin
	if(rst_n)
	begin
	    //pwm_out<= s1;//中间
		pwm_out <= 1'b0;
    end
	else if(cnt1 <= cnt_r1)
	begin
		pwm_out <= 1'b1;
	end
	else
	begin
		pwm_out <= 1'b0;
	end
end
endmodule

代码写好了之后需要生成bit流,当然这还不够,我们需要让小车不连接电脑去跑这就需要将代码固化到Ego1里面,下面是代码固化的方法:(13条消息) vivado纯verilog代码固化程序_Kiss丶小坏-CSDN博客

简单步骤:当然你直接生成bit流之后

选择Tools——>Generate Memory Configuration File,也可以打开hardware之后右键找到。

注:这一步是产生mcs文件进行程序加载,同时也会产生prm文件(也可以不需要,例如直接在生成bit文件时,勾选bin文件,最后一步时直接加载bin文件)。详情看文档去。

在这里插入图片描述

配置:

在这里插入图片描述 如果报错就将Interface改成报错要求的值

之后是Add Configuration Memory Device。三种方法:

方法1.

在这里插入图片描述

方法2.

在这里插入图片描述

方法3.

在这里插入图片描述

接下来,出现如下界面,选择flash芯片。

在这里插入图片描述

如果报错就选择n25q64-3.3v-spi-xi_x2_x4

最后一步,在选择芯片之后会出现如下界面,也就是加载Flash,固化程序。在这里插入图片描述 

整个工程见如下链接:

Xilinx-Ego1(FPGA)寻迹小车-硬件开发文档类资源-CSDN文库

  • 11
    点赞
  • 88
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
基于FPGA循迹小车是一种基于硬件实现的智能小车,它可以通过感知环境中的线路来进行自主导航。下面是一个简单的基于FPGA循迹小车代码讲解: 1. 硬件设计: - 使用FPGA开发板,如Xilinx或Altera等。 - 连接电机驱动模块,用于控制小车的运动。 - 连接红外传感器模块,用于检测地面上的黑线。 2. 软件设计: - 使用HDL语言(如Verilog或VHDL)进行硬件描述。 - 设计顶层模块,包括输入输出端口和各个子模块的实例化。 - 子模块包括: - 电机控制模块:根据传感器信号控制电机的转动方向和速度。 - 红外传感器模块:检测地面上的黑线,并将信号传递给电机控制模块。 - 控制逻辑模块:根据传感器信号决定小车的运动策略。 3. 控制逻辑设计: - 根据传感器信号判断小车当前位置相对于黑线的位置关系。 - 根据位置关系决定小车的运动策略,如直行、左转、右转等。 - 使用状态机或其他逻辑结构实现控制逻辑。 4. 代码实现: - 根据硬件设计和控制逻辑设计,编写相应的Verilog或VHDL代码。 - 实例化各个子模块,并连接输入输出端口。 - 进行综合、布局和时序优化等步骤,生成最终的比特流文件。 以上是基于FPGA循迹小车代码的简单讲解。具体的实现细节和代码实现可能因具体的项目而有所不同。如果你有具体的问题或需要更详细的讲解,请提供更多信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

只待花开

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值