2025寒假练——基于小脚丫FPGA实现交通灯控制系统
该项目使用了webIDE、diamond软件、verilog语言,实现了交通灯控制系统的设计,它的主要功能为:计时显示不同颜色红绿灯、蜂鸣器在黄灯时报警,人员靠近时亮灯,环境光检测,变暗时自动开灯。
标签
FPGA
数字逻辑
显示
凛北野
更新2025-03-21
华中科技大学
28

2025寒假一起练项目报告

【一、项目介绍】

       选择基于小脚丫FPGA STEP BaseBoard V4.0套件为硬件,完成项目一:交通灯控制系统——图形化编程

 


【二、硬件介绍】

小脚丫FPGA STEP BaseBoard V4.0套件是专为FPGA学习者设计的综合性实验平台,它集成了丰富的外设和接口,包括存储器、温湿度传感器、接近式传感器、矩阵键盘、旋转编码器、HDMI接口、RGB LCD液晶屏、7位数码管、蜂鸣器模块、UART通信模块、ADC模块、DAC模块和WiFi通信模块等。这些集成的组件使得该套件非常适合用于数字逻辑、微机原理、可编程逻辑语言以及EDA设计工具等课程的实验教学,为FPGA初学者提供了一个功能丰富、性能优秀的学习平台。

 


【三、方案框图与项目设计思路】

       1

用时钟分频器分别给倒计时和蜂鸣器分两个不同的频率,在状态机中,每隔一定的时间转换为下一个状态,三种状态分别是绿灯、黄灯、红灯,在黄灯状态下使能蜂鸣器,让蜂鸣器在给到的频率下振动发出声音

       2

用光传感器传回的数据在计算模块中进行一系列的处理,最后用得到的数据作为输出传给七段数码管和LED灯显示结果


【四、软件流程图和关键代码】

1task1-2:

all里面对整体进行了封装:

reg [8:0]num_n1;
reg [8:0]num_n2;
reg [8:0]seg[9:0];
reg [7:0]i,j,k;
reg [1:0]mode;
reg [2:0]light;
reg beep;
assign num1=num_n1;
assign num2=num_n2;
assign led=light;
assign beeper=beep;
initial begin
       seg[0] = 9'h3f; seg[1] = 9'h06; seg[2] = 9'h5b; seg[3] = 9'h4f;
       seg[4] = 9'h66; seg[5] = 9'h6d; seg[6] = 9'h7d; seg[7] = 9'h07;
       seg[8] = 9'h7f; seg[9] = 9'h6f; i=0;   j=0;   k=0;mode=0;beep=0;
       light=3'b111;//七段数码管显示赋值
end
always@(posedge clk or negedge rst)begin
    if(!rst) begin
    i=0;j=0;k=0;mode=0;beep=0;light=3'b111;
    end
    else begin
        case(mode)//三态状态机
            2'b00: begin
                if(i==31) begin
                i<=1'b0;
                j<=1'b0;
                k<=1'b0;
                mode<=2'b01;//状态改变
                end
                else begin
                    light<=3'b110;
                    i<=i+1'b1;
                    j<=j+1'b1;
                    if(j==9) begin
                    k<=k+1'b1;
                    j<=0;//逢十进一(由于webIDE的BUG,导致除法不能使用)
                    end
                    num_n1<=seg[k];
                    num_n2<=seg[i%10];
                    beep<=0;
                end
            end
            2'b01: begin
                if(i==4) begin
                i<=1'b0;
                j<=1'b0;
                k<=1'b0;
                mode<=2'b10;
                end
                else begin
                    light<=3'b100;
                    i<=i+1'b1;
                    j<=j+1'b1;
                    if(j==9) begin
                    k<=k+1'b1;
                    j<=0;
                    end
                    num_n1<=seg[k];
                    num_n2<=seg[i%10];
                    beep<=1;//状态二中对蜂鸣器使能
                end
            end
            2'b10: begin
                if(i==21) begin
                i<=1'b0;
                j<=1'b0;
                k<=1'b0;
                mode<=2'b00;
                end
                else begin
                    light<=3'b101;
                    i<=i+1'b1;
                    j<=j+1'b1;
                    if(j==9) begin
                    k<=k+1'b1;
                    j<=0;
                    end
                    num_n1<=seg[k];
                    num_n2<=seg[i%10];
                    beep<=0;
                end
            end
        endcase
    end
end

其中:

蜂鸣器的使能结果和另一个时钟的分频结果用与门连接作为输出,当使能为1时,蜂鸣器可以按照分频结果的频率发声

 

2task3-4

主要使用了提供的例程lab8中的模块,现对各模块的具体功能简要介绍

1rpr0521s_driver

这是一个与板间进行I2C通讯的光感应传感器,,可以传入三个数据ch0_datch1_datprox_dat与一个使能数据dat_valid,前两个是检测光强,后一个是检测是否接近,使能数据给下一个模块相连,当dat_valid1时,相连模块工作

2decoder

与上文的传感器模块相连,进行数据处理后并用二进制转BCD码得到32位的lux_data记录相对光强值,Y_out用以控制LED(这是例程中的原始模块,我在最终的代码中对Y_out稍加改动,使其只控制五个LED灯,其余的LED灯作为环境光检测的现象用)

3segment_scan

转换成的BCD码四位一组分别传入segment_scan模块中,输出可以让七段数码管显示对应数字(原理图中看出,七段数码管采用移位寄存器级联的方式进行显示,因此真正的数据传入端只需要一个,便可做到串行输入并行输出,让8个七段数码管同时显示互不影响,大大降低接线难度)

4)综合

module prox_detect(
              input                           clk,
              input                           rst_n,
             
              output                  i2c_scl,    //I2C
              inout                           i2c_sda,  //I2C
              output                  seg_rck,                // 74HC595RCK
              output                  seg_sck,                // 74HC595SCK
              output                  seg_din,                // 74HC595SER
             
              output    [5:0] led,         //led
             
              output [5:0]led_useless,
              output led_new,
              output beeper
       );
      
assign led_useless=6'b111111;
 
wire dat_valid;
wire [15:0] ch0_dat, ch1_dat, prox_dat;
wire [31:0] lux_data;
rpr0521rs_driver u1(
              .clk                (clk                ),     //
              .rst_n             (rst_n             ),     //
              .i2c_scl           (i2c_scl           ),     //I2CSCL
              .i2c_sda         (i2c_sda         ),     //I2CSDA
             
              .dat_valid       (dat_valid       ),     //
              .ch0_dat         (ch0_dat        ),     //ALS
              .ch1_dat         (ch1_dat        ),     //IR
              .prox_dat (prox_dat       )      //Prox
       );
 
decoder u2(
              .rst_n             (rst_n),
              .dat_valid       (dat_valid       ),
              .ch0_dat         (ch0_dat        ),
              .ch1_dat         (ch1_dat        ),
              .prox_dat (prox_dat       ),
              .lux_data (lux_data ),
              .Y_out            (led                )
       );
 
segment_scan u4(
              .clk(clk),                               // 12MHz
              .rst_n(rst_n),                        //
              .dat_1(lux_data[31:28]   ),     //SEG1
              .dat_2(lux_data[27:24]   ),     //SEG2
              .dat_3(lux_data[23:20]   ),     //SEG3
              .dat_4(lux_data[19:16]   ),     //SEG4
              .dat_5(lux_data[15:12]   ),     //SEG5
              .dat_6(lux_data[11:08]   ),     //SEG6
              .dat_7(lux_data[07:04]   ),     //SEG7
              .dat_8(lux_data[03:00]   ),     //SEG8
              .dat_en(8'b1111_1111  ),       //[MSB~LSB]=[SEG1~SEG8]
              .dot_en(8'b0000_0100  ),       //[MSB~LSB]=[SEG1~SEG8]
              .seg_rck(seg_rck           ),     //74HC595RCK
              .seg_sck(seg_sck           ),     //74HC595SCK
              .seg_din(seg_din           )      //74HC595SER
       );
 
my_code u6(
              .rst_n(rst_n),
              .clk(clk),
              .led_in(lux_data[19:16]),
              .beeper_in(led[2]),
              .led_new(led_new),
              .beeper(beeper)
);
Endmodule

在最后的my_code(我的自定义模块)中,对上述lux_data[19:16]位进行检测,当其为0时说明光强过小,控制开灯;对led[2]位检测,当其为低电平时,说明物体接近传感器,控制开灯

输出口新增led_useless,对不用的led口初始化防止对实验结果造成影响

 


【五、功能展示图】

 



【六、项目遇到的难题及解决方法】

       1、排线混乱不堪,难以调线与检查问题:一开始在图形化界面自定义了很多模块,一股脑连线后混乱不堪,调试时也不方便调试。解决:通过把状态机直接写在一个模块里解决了排线复杂的问题,并方便调试

       2、不熟悉webIDE的使用:使用webIDE时经常习惯性按到空格键导致自定义模块直接全部清零得从头再来。解决:通过控制住enter保存的手癖解决

       3webIDE引脚显示错误:由于自定义模块中的语法有误导致该存在的引脚无法约束。解决:修改语句

       4verilog与数电基础薄弱:由于处于大一初学阶段,对verilog与时序逻辑和组合逻辑知识了解极其有限。解决:多学多看多练

 


【七、对本次活动的心得体会】

在这个寒假,我有幸参加了硬禾学堂的一起练活动,这对我的个人成长和技术提升有着深远的影响。通过独立完成项目,我更加深刻地理解了FPGA的工作原理和应用场景。每个挑战都促使我深入研究,不断尝试,直到找到最佳解决方案。这个过程不仅锻炼了我的问题解决能力,也增强了我的自我学习能力。 在没有团队协作的情况下,我学会了如何独立规划项目进度,自我监督,并对自己的工作成果负责。这种自律和独立思考的能力对于我未来的学习和职业发展都是极其宝贵的。硬禾学堂提供的丰富资源和指导,让我在实践中学习,在学习中进步,我对电子设计和FPGA编程有了更加深入的认识和掌握。这段经历无疑将对我的技术生涯产生长远的积极影响。


【八、资源占用报告】

1、webIDE

image.png

2、diamond

aae07f7dea32ed6b05dc432e27cdddc.png


【注】WebIDE链接:https://www.stepfpga.com/project/17208/gui?type=top


附件下载
main.v
task1_2 webIDE
task3_4.zip
团队介绍
独立完成
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号