1:项目介绍
在本次寒假在家一起练中,我选择的是交通灯控制系统 - 图形化编程这个程序,本项目有在数码管上显示计时信息 ,蜂鸣器报警 ,接近传感器检测人员走近 ,环境光感知,自动点亮路灯这四点要求。具体实现方面我选择了方案二:第一个和第二个要求用图形化编程,第三个和第四个要求使用diamond实现,接下来介绍如何实现。
2:资源使用
本次使用的小脚丫核心板是一块操作简单的FPGA开发板,尤其是烧录方面可以直接导入JED文件编译,减轻了工作量,同时V4.0的拓展板也集成了相当多的功能,能很好的完成本次项目的要求,本次项目主要使用了:核心板上的两个八位数码管,拓展板上的蜂鸣器,拓展板上的环境光和距离感应芯片RPR—0521RS,核心板上的两个RGB小灯,核心板的八个LED。
3:方案框图和设计思路
webide的链接为https://www.stepfpga.com/project/16743/gui?type=top
webide图形化界面如下
diamond的图形化如下
可以看出使用diamond和使用webide的图形化编程最后的框图大同小异,根据项目要求分析,要实现红绿灯,首先要一个分频模块,用于将12M的系统时钟分成一个CLK1,频率为1HZ,然后写一个状态机,配合1HZ的时钟来实现四种状态的转移和RGB的发光,转移顺序为:红绿,红蓝,绿红,蓝红(因为没有黄色灯光,用蓝色代替)。然后需要一个蜂鸣器模块,该模块能接收状态机的目前状态,当黄灯的时候该模块驱动蜂鸣器发声。然后状态机根据计时信息,将对应的数字显示到数码管上,最后再写一个I2C的驱动模块,用来循环读取芯片的光强寄存器和距离寄存器,并且判断当前是否需要点亮路灯(LED1到LED4亮起),并且提示有人接近(LED5到LED8熄灭)。
4:软件流程和关键代码
软件流程:
module rgb(clk,rst,out,din,sck,rck,deep,led,
scl,sda,close
);
parameter onesed=24000000;
input clk;
input rst;
output scl;
inout sda;
output reg[5:0]out;
output din,sck,rck;
output deep;
output [3:0]led;
output [3:0]close;
wire clk1;
wire clk2;
wire ten;
wire [3:0] one;
wire[15:0]out1,out2;
wire[1:0] state;
wire i2c_sda;
wire sck_r,rck_r,din_r;
reg[25:0]cnt;
reg sda_r;
parameter led0=6'b101011,led1=6'b110011,led2=6'b011101,led3=6'b011110;
parameter s0=4'b00,s1=4'b01,s2=4'b10,s3=4'b11;
fenpin a1(.clk_i(clk),.rst(rst),.clk_o(clk1));//1秒
fenpin #(.n(500),.m(250))a2(.clk_i(clk),.rst(rst),.clk_o(clk2));//600分频
transfer b1(.clkh(clk1),.rst(rst),.state(state),.out1(out1),.out2(out2));
sound d1(.state(state),.clk(clk),.clk1(clk1),.deep(deep),.rst(rst));
i2c e1(.clk(clk),.rst_n(rst),.i2c_scl(scl),.i2c_sda(i2c_sda),.streelight(led),.le(close));
always@(posedge clk1 or negedge rst)
begin
if(!rst)
out=led0;
else begin
case(state)
s0:begin
out<=led0;
end
s1:begin
out<=led1;
end
s2:begin
out<=led2;
end
s3:begin
out<=led3;
end
endcase
end
end
assign sda=i2c_sda;
endmodule
由顶层设计rgb看软件流程,首先是基本的寄存器和线的定义,然后先例化分频子模块fenpin,然后例化状态机得到状态,最后例化I2C模块。
关键代码:本人认为,关键代码有如下两处,首先是状态机的转移代码,其中代码为标准的三段式转移代码,只给出第三段描述当前状态行为的代码
always@(posedge clkh or negedge rst)
begin
if(!rst) begin
timecount=tim0;
end
else begin
case(next_state)
s0:begin
if(timecount==1)
timecount<=tim0;
else
timecount<=timecount-1;
end
s1:begin
if(timecount==1)
timecount<=tim1;
else
timecount<=timecount-1;
end
s2:begin
if(timecount==1)
timecount<=tim2;
else
timecount<=timecount-1;
end
s3:begin
if(timecount==1)
timecount<=tim3;
else
timecount<=timecount-1;
end
endcase
end
end
第二段代码是I2C的通信代码,本部分代码参考了电子森林昵称为枫雪天的用户的基于FPGA实现的体感控制打砖块游戏中的I2C通信代码,在此基础上针对使用的芯片和要实现功能的不同,对他的代码进行了修改,其中最关键的部分如下。
MAIN:begin
if(cnt_main >= 4'd10) cnt_main <= 4'd0; //写完控制指令后循环读数据
else cnt_main <= cnt_main + 1'b1;
case(cnt_main)
4'd0: begin dev_addr <= 7'h38; reg_addr <= 8'h40; reg_data <= 8'hca; state <= MODE1; end //写入配置
4'd1: begin dev_addr <= 7'h38; reg_addr <= 8'h40; reg_data <= 8'h4a; state <= MODE1; end //写入配置
4'd2: begin dev_addr <= 7'h38; reg_addr <= 8'h41; reg_data <= 8'h89; state <= MODE1; end //写入配置
4'd3: begin dev_addr <= 7'h38; reg_addr <= 8'h42; reg_data <= 8'h02; state <= MODE1; end //写入配置
4'd4: begin state <= DELAY; num_delay <= 24'd60_000;data_valid <= 1'b0; end //120ms延时
4'd5: begin dev_addr <= 7'h38; reg_addr <= 8'h46; state <= MODE2; end //读取配置
4'd6: begin light<= {dat_h,dat_l}; streelight<=(light>dark)?4'hffff:4'h0000;end //读取数据
4'd7: begin dev_addr <= 7'h38; reg_addr <= 8'h41; reg_data <= 8'h49; state <= MODE1; end //写入配置
4'd8: begin state <= DELAY; num_delay <= 24'd60_000;data_valid <= 1'b0; end //120ms延时
4'd9: begin dev_addr <= 7'h38; reg_addr <= 8'h44; state <= MODE2; end //读取配置
4'd10: begin length<= {dat_h,dat_l}; le<=(length>close)?4'hffff:4'h0000;end //读取数据
default: state <= IDLE; //如果程序失控,进入IDLE自复位状态
endcase
其中7‘h38为从机的地址,首先写8’h40寄存器,触发restart,然后向8‘h41,8'h42寄存器中写入配置,将芯片设置为计算光线强度模式,然后从4'h46,4’h47中读取光强信息,和设置的常数比较,判断是否要开启路灯。接下来同理,判断是否要提示有人接近。
5:功能展示与说明
黑暗,且有物体接近时路灯(LED1到4)亮起,LED5到8熄灭,红绿灯为核心板上的两个RGB。
常态时路灯熄灭,感应灯亮起。
黑暗,无物体接近时路灯亮起,感应灯不熄灭。
要求一和二的倒计时和红绿灯
6:遇到的主要问题
小的问题确实遇到了很多,但是比较大的是I2C通信这一块,在最开始的时候自己写的I2C时序有些混乱,通信不稳定,最后参考了往届的开源代码,对自己的代码进行了修改和优化,达到了目的,并且在使用webide的过程中也遇到了图形化的一些问题,也在热心群友的回复下得到了解决。
7:心得体会
之前一直是在学校的实验课上开发FPGA,开发流程可以一步一步按照教科书上的来,这是第一次自己独立开发FPGA,在开发过程中遇到了很多问题,通过查阅资料,寻找参考的方式一步步解决了问题,最终实现了项目,收获的经验是丰富的,感谢硬禾科技给了我这个平台和机会。