2025寒假练 - 基于小脚Y FPGA STEP BaseBoard V4.0套件实现交通灯控制系统
该项目使用了小脚Y FPGA STEP BaseBoard V4.0,实现了交通灯控制系统的设计,它的主要功能为:交通灯控制,读取接近传感器,控制蜂鸣器报警, 读取环境光数据,同时控制一个补光灯。
标签
FPGA
数字逻辑
开发板
WebIDE
GGboy
更新2025-03-17
34

项目需求

完全使用WebIDE的图形化编程,使用常规的74系列的元器件,构建一个交通灯控制系统:

  • 在数码管上显示计时信息 - 图形化
  • 蜂鸣器报警 - 图形化
  • 接近传感器检测人员走近 -Verilog
  • 环境光感知,自动点亮路灯(小脚丫核心板上的单色LED)- Verilog

需求分析

本项目要求使用FPGA实现一个交通灯控制系统,主要功能有交通灯控制功能,蜂鸣器报警以及传感器数据读取。项目具体内容已在项目需求中清晰表述,此处不再赘述。根据项目需求,我们可以确定,我们需要实现数码管控制,蜂鸣器控制,以及 IIC的使用方法。本项目的核心重点在于围绕图形化的实现上述功能。

系统设计

我们要完成记数码管上的显示以及计时,首先我们要查看我们的数码管是共阴极还是共阳极,然后我们需要产生一个一秒的计时,那么我们就明确的知道了我们当前的计时信息,以及如何去控制我们的数码管。


我们将外部的时钟进行分频,产生1HZ的信号,作为我们整个数码管计时控制器的时钟输入,加入复位引脚方便我们复位这个模块,同时我们还要引入三个常量,方便我们随时控制红黄绿三色灯的显示时间。输出的部分我们输出了红黄绿三个led的控制,以及倒计时的10位和个位数字,方便我们进行数码管显示。


软件介绍


具体代码如下:

reg rl,gl,bl;

reg [3:0] LEDS;
reg [3:0] LEDG;

assign RLED = rl;
assign GLED = gl;
assign BLED = bl;
assign TS = LEDS;
assign TG = LEDG;


localparam GMODE = 4'd0;
localparam YMODE = 4'd2;
localparam RMODE = 4'd4;



reg [7:0] CNUM;
reg [3:0] LEDMODE;


reg [3:0] CNT;
reg [7:0] CNTIME;

always@(posedge clk or negedge rst) begin
if(!rst) begin //如果按键复位,将相关数据初始化
LEDMODE<=4'd0;
CNUM<=8'd0;
end else begin
CNUM<=CNUM+1'b1;
case(LEDMODE)
GMODE:begin
CNTIME=G-CNUM;
if(CNUM==G)begin
CNUM<=8'd0;
LEDMODE<=YMODE;
end
else begin
rl<=1'b1;
gl<=1'b0;
bl<=1'b1;
end
end
YMODE:begin
CNTIME=Y-CNUM;
if(CNUM==Y)begin
CNUM<=8'd0;
LEDMODE<=RMODE;
end
else begin

rl<=1'b0;
gl<=1'b0;
bl<=1'b1;
end
end
RMODE:begin
CNTIME=R-CNUM;
if(CNUM==R)begin
CNUM<=8'd0;
LEDMODE<=GMODE;
end
else begin
rl<=1'b0;
gl<=1'b1;
bl<=1'b1;
end
end
default:;
endcase
LEDS=0;
for (CNT = 0; CNT < 10; CNT = CNT + 1)begin
if (CNTIME >= 10) begin
CNTIME = CNTIME - 10;
LEDS = LEDS + 1;
end
end
LEDG=CNTIME;
end
end

从代码中可以看到,这个模块我们通过计数值和我们设定的红黄绿三个灯的显示值进行比较。然后去切换红黄绿三个灯的显示状态,同时也输出了倒计时的十位和个位,方便我们进行数码管显示。


数码管显示代码如下:

wire 	[3:0] a ;
reg [7:0] q ;
reg mo;

assign a = num;
assign DIG = q;
assign SEG = mo;

always@(a)
begin
if(!rst)begin
q <= 8'b0000_0000;
mo <= 1;
end
else
begin
mo <= 0;
case(a)
4'b0000: q <= 8'b1111_1100;
4'b0001: q <= 8'b0110_0000;
4'b0010: q <= 8'b1101_1010;
4'b0011: q <= 8'b1111_0010;
4'b0100: q <= 8'b0110_0110;
4'b0101: q <= 8'b1011_0110;
4'b0110: q <= 8'b1011_1110;
4'b0111: q <= 8'b1110_0000;
4'b1000: q <= 8'b1111_1110;
4'b1001: q <= 8'b1110_0110;
default:q <= 8'b0000_0000;
endcase
if(D)q<=q+1;
end
end

在数码管显示的模块里,我们除了一个数据的输入信号,还引入了模块的复位信号,以及一个常量。这个常量的作用是控制我们数码管上的小数点是否进行显示,方便我们以后进行拓展。在输出上,实现对一个数码管共阴极以及八段的控制信号。


接下来我们要完成对一个IIC器件的内部数据读取以及配置。IIC 总线由两条线组成,一条是串行数据线(SDA),用于传输数据;另一条是串行时钟线(SCL),用于同步数据传输。总线上可以连接多个设备,每个设备都有一个唯一的地址,通过这个地址可以对设备进行寻址。在fpta中,对IIC的理解更加深刻。在每一个时钟脉冲来临时,我们要通过考虑IIC的通信协议,来完成SCL和SDA的高低电平切换。我们要通过看这个器件的数据手册,才能知道它可以支持的最大通信速率,以及它的通信地址是什么。


该模块的具体实现代码如下:

reg	[15:0]	ch0;		//JJ数据
reg [15:0] ch1; //GZ数据

reg scl,sda;

assign i2c_scl = scl; //对SCL端口赋值
assign i2c_sda = sda; //对SDA端口赋值

assign JJ = ch0;
assign GZ = ch1;

localparam IDLE = 4'd0;
localparam MAIN = 4'd1;
localparam MODE1 = 4'd2;
localparam MODE2 = 4'd3;
localparam START = 4'd4;
localparam WRITE = 4'd5;
localparam READ = 4'd6;
localparam STOP = 4'd7;
localparam DELAY = 4'd8;

localparam ACK = 1'b0;
localparam NACK = 1'b1;

reg ack,ack_flag;
reg [3:0] cnt, cnt_main, cnt_mode1, cnt_mode2, cnt_start, cnt_write, cnt_read, cnt_stop;
reg [7:0] data_wr, dev_addr, reg_addr, reg_data, data_r, dat_l, dat_h;
reg [23:0] cnt_delay, num_delay;
reg [3:0] state, state_back;

always@(posedge clk or negedge rst) begin
if(!rst) begin //如果按键复位,将相关数据初始化
scl <= 1'd1; sda <= 1'd1; ack <= ACK; ack_flag <= 1'b0; cnt <= 1'b0;
cnt_main <= 1'b0; cnt_mode1 <= 1'b0; cnt_mode2 <= 1'b0;
cnt_start <= 1'b0; cnt_write <= 1'b0; cnt_read <= 1'b0; cnt_stop <= 1'b0;
cnt_delay <= 1'b0; num_delay <= 24'd4800;
state <= IDLE; state_back <= IDLE;
end else begin
case(state)
IDLE:begin //软件自复位,主要用于程序跑飞后的处理
scl <= 1'd1; sda <= 1'd1; ack <= ACK; ack_flag <= 1'b0; cnt <= 1'b0;
cnt_main <= 1'b0; cnt_mode1 <= 1'b0; cnt_mode2 <= 1'b0;
cnt_start <= 1'b0; cnt_write <= 1'b0; cnt_read <= 1'b0; cnt_stop <= 1'b0;
cnt_delay <= 1'b0; num_delay <= 24'd4800;
state <= MAIN; state_back <= IDLE;
end
MAIN:begin
if(cnt_main >= 4'd9) cnt_main <= 4'd4; //写完控制指令后循环读数据
else cnt_main <= cnt_main + 1'b1;
case(cnt_main)
4'd0: begin dev_addr <= 7'h38; reg_addr <= 8'h40; reg_data <= 8'h0a; state <= MODE1; end //写入配置
4'd1: begin dev_addr <= 7'h38; reg_addr <= 8'h41; reg_data <= 8'hc6; state <= MODE1; end //写入配置
4'd2: begin dev_addr <= 7'h38; reg_addr <= 8'h42; reg_data <= 8'h02; state <= MODE1; end //写入配置
4'd3: begin dev_addr <= 7'h38; reg_addr <= 8'h43; reg_data <= 8'h01; state <= MODE1; end //写入配置
4'd4: begin state <= DELAY; end //12ms延时
4'd5: begin dev_addr <= 7'h38; reg_addr <= 8'h44; state <= MODE2; end //读取配置
4'd6: begin ch0<= {dat_h,dat_l}; end //读取数据
4'd7: begin dev_addr <= 7'h38; reg_addr <= 8'h46; state <= MODE2; end //读取配置
4'd8: begin ch1 <= {dat_h,dat_l}; end //读取数据
4'd9: begin state <= DELAY; end //读取数据
default: state <= IDLE; //如果程序失控,进入IDLE自复位状态
endcase
end
MODE1:begin //单次写操作
if(cnt_mode1 >= 4'd5) cnt_mode1 <= 1'b0; //对START中的子状态执行控制cnt_start
else cnt_mode1 <= cnt_mode1 + 1'b1;
state_back <= MODE1;
case(cnt_mode1)
4'd0: begin state <= START; end //I2C通信时序中的START
4'd1: begin data_wr <= dev_addr<<1; state <= WRITE; end //设备地址
4'd2: begin data_wr <= reg_addr; state <= WRITE; end //寄存器地址
4'd3: begin data_wr <= reg_data; state <= WRITE; end //写入数据
4'd4: begin state <= STOP; end //I2C通信时序中的STOP
4'd5: begin state <= MAIN; end //返回MAIN
default: state <= IDLE; //如果程序失控,进入IDLE自复位状态
endcase
end
MODE2:begin //两次读操作
if(cnt_mode2 >= 4'd10) cnt_mode2 <= 1'b0; //对START中的子状态执行控制cnt_start
else cnt_mode2 <= cnt_mode2 + 1'b1;
state_back <= MODE2;
case(cnt_mode2)
4'd0: begin state <= START; end //I2C通信时序中的START
4'd1: begin data_wr <= dev_addr<<1; state <= WRITE; end //设备地址
4'd2: begin data_wr <= reg_addr; state <= WRITE; end //寄存器地址
4'd3: begin state <= START; end //I2C通信时序中的START
4'd4: begin data_wr <= (dev_addr<<1)|8'h01; state <= WRITE; end //设备地址
4'd5: begin ack <= ACK; state <= READ; end //读寄存器数据
4'd6: begin dat_l <= data_r; end
4'd7: begin ack <= NACK; state <= READ; end //读寄存器数据
4'd8: begin dat_h <= data_r; end
4'd9: begin state <= STOP; end //I2C通信时序中的STOP
4'd10: begin state <= MAIN; end //返回MAIN
default: state <= IDLE; //如果程序失控,进入IDLE自复位状态
endcase
end
START:begin //I2C通信时序中的起始START
if(cnt_start >= 3'd5) cnt_start <= 1'b0; //对START中的子状态执行控制cnt_start
else cnt_start <= cnt_start + 1'b1;
case(cnt_start)
3'd0: begin sda <= 1'b1; scl <= 1'b1; end //将SCL和SDA拉高,保持4.7us以上
3'd1: begin sda <= 1'b1; scl <= 1'b1; end //clk_400khz每个周期2.5us,需要两个周期
3'd2: begin sda <= 1'b0; end //SDA拉低到SCL拉低,保持4.0us以上
3'd3: begin sda <= 1'b0; end //clk_400khz每个周期2.5us,需要两个周期
3'd4: begin scl <= 1'b0; end //SCL拉低,保持4.7us以上
3'd5: begin scl <= 1'b0; state <= state_back; end //clk_400khz每个周期2.5us,需要两个周期,返回MAIN
default: state <= IDLE; //如果程序失控,进入IDLE自复位状态
endcase
end
WRITE:begin //I2C通信时序中的写操作WRITE和相应判断操作ACK
if(cnt <= 3'd6) begin //共需要发送8bit的数据,这里控制循环的次数
if(cnt_write >= 3'd3) begin cnt_write <= 1'b0; cnt <= cnt + 1'b1; end
else begin cnt_write <= cnt_write + 1'b1; cnt <= cnt; end
end else begin
if(cnt_write >= 3'd7) begin cnt_write <= 1'b0; cnt <= 1'b0; end //两个变量都恢复初值
else begin cnt_write <= cnt_write + 1'b1; cnt <= cnt; end
end
case(cnt_write)
//按照I2C的时序传输数据
3'd0: begin scl <= 1'b0; sda <= data_wr[7-cnt]; end //SCL拉低,并控制SDA输出对应的位
3'd1: begin scl <= 1'b1; end //SCL拉高,保持4.0us以上
3'd2: begin scl <= 1'b1; end //clk_400khz每个周期2.5us,需要两个周期
3'd3: begin scl <= 1'b0; end //SCL拉低,准备发送下1bit的数据
//获取从设备的响应信号并判断
3'd4: begin sda <= 1'bz; end //释放SDA线,准备接收从设备的响应信号
3'd5: begin scl <= 1'b1; end //SCL拉高,保持4.0us以上
3'd6: begin ack_flag <= i2c_sda; end //获取从设备的响应信号并判断
3'd7: begin scl <= 1'b0; if(ack_flag)state <= state; else state <= state_back; end //SCL拉低,如果不应答循环写
default: state <= IDLE; //如果程序失控,进入IDLE自复位状态
endcase
end
READ:begin //I2C通信时序中的读操作READ和返回ACK的操作
if(cnt <= 3'd6) begin //共需要接收8bit的数据,这里控制循环的次数
if(cnt_read >= 3'd3) begin cnt_read <= 1'b0; cnt <= cnt + 1'b1; end
else begin cnt_read <= cnt_read + 1'b1; cnt <= cnt; end
end else begin
if(cnt_read >= 3'd7) begin cnt_read <= 1'b0; cnt <= 1'b0; end //两个变量都恢复初值
else begin cnt_read <= cnt_read + 1'b1; cnt <= cnt; end
end
case(cnt_read)
//按照I2C的时序接收数据
3'd0: begin scl <= 1'b0; sda <= 1'bz; end //SCL拉低,释放SDA线,准备接收从设备数据
3'd1: begin scl <= 1'b1; end //SCL拉高,保持4.0us以上
3'd2: begin data_r[7-cnt] <= i2c_sda; end //读取从设备返回的数据
3'd3: begin scl <= 1'b0; end //SCL拉低,准备接收下1bit的数据
//向从设备发送响应信号
3'd4: begin sda <= ack; end //发送响应信号,将前面接收的数据锁存
3'd5: begin scl <= 1'b1; end //SCL拉高,保持4.0us以上
3'd6: begin scl <= 1'b1; end //SCL拉高,保持4.0us以上
3'd7: begin scl <= 1'b0; state <= state_back; end //SCL拉低,返回MAIN状态
default: state <= IDLE; //如果程序失控,进入IDLE自复位状态
endcase
end
STOP:begin //I2C通信时序中的结束STOP
if(cnt_stop >= 3'd5) cnt_stop <= 1'b0; //对STOP中的子状态执行控制cnt_stop
else cnt_stop <= cnt_stop + 1'b1;
case(cnt_stop)
3'd0: begin sda <= 1'b0; end //SDA拉低,准备STOP
3'd1: begin sda <= 1'b0; end //SDA拉低,准备STOP
3'd2: begin scl <= 1'b1; end //SCL提前SDA拉高4.0us
3'd3: begin scl <= 1'b1; end //SCL提前SDA拉高4.0us
3'd4: begin sda <= 1'b1; end //SDA拉高
3'd5: begin sda <= 1'b1; state <= state_back; end //完成STOP操作,返回MAIN状态
default: state <= IDLE; //如果程序失控,进入IDLE自复位状态
endcase
end
DELAY:begin //12ms延时
if(cnt_delay >= num_delay) begin
cnt_delay <= 1'b0;
state <= MAIN;
end else cnt_delay <= cnt_delay + 1'b1;
end
default:;
endcase
end
end


在这个模块中,我们输入信号有时中信号和复位信号,而我们的输出是数据线,时钟线以及光照数据和接近传感器的数据。

接下来我们通过一个简单的分频器去驱动我们的蜂鸣器。将我们刚才的接近传感器的数据和一个常量进行比较,也就是我们设定的阈值,我们的输出信号可以直接接到蜂鸣器的复位上,这样我们就实现了接近报警。

我们的光照传感器数据同样也是和一个常量进行比较,然后输出接一个led,我们就实现了当光照低时打开led,当光照高时关闭led。


经过以上所有的流程,我们就完成了本次活动所给的任务要求,同时本次项目要求用74系列的器件完成一段代码,我们就利用开发板上的595去驱动上面的数码,可以显示交通灯的计时值,或者接近传感器,光照传感器的数据。

595的驱动控制代码如下:

wire	[3:0]	dat_1;		//SEG1 显示的数据输入
wire [3:0] dat_2; //SEG2 显示的数据输入
wire [3:0] dat_3; //SEG3 显示的数据输入
wire [3:0] dat_4; //SEG4 显示的数据输入
wire [3:0] dat_5; //SEG5 显示的数据输入
wire [3:0] dat_6; //SEG6 显示的数据输入
wire [3:0] dat_7; //SEG7 显示的数据输入
wire [3:0] dat_8; //SEG8 显示的数据输入
wire [7:0] dat_en; //数码管数据位显示使能,[MSB~LSB]=[SEG1~SEG8]
wire [7:0] dot_en; //数码管小数点位显示使能,[MSB~LSB]=[SEG1~SEG8]
reg seg_rck; //74HC595的RCK管脚
reg seg_sck; //74HC595的SCK管脚
reg seg_din; //74HC595的SER管脚



assign dat_1=SE1;
assign dat_2=SE2;
assign dat_3=SE3;
assign dat_4=SE4;
assign dat_5=SE5;
assign dat_6=SE6;
assign dat_7=SE7;
assign dat_8=SE8;

assign dat_en=DAT;
assign dot_en=DOT;

assign RCK=seg_rck;
assign SCK=seg_sck;
assign DIN=seg_din;



localparam CNT_40KHz = 300; //分频系数

localparam IDLE = 3'd0;
localparam MAIN = 3'd1;
localparam WRITE = 3'd2;
localparam LOW = 1'b0;
localparam HIGH = 1'b1;

//创建数码管的字库,字库数据依段码顺序有关
//这里字库数据[MSB~LSB]={G,F,E,D,C,B,A}
reg[6:0] seg [15:0];
always @(negedge rst) begin
seg[0] = 7'h3f; // 0
seg[1] = 7'h06; // 1
seg[2] = 7'h5b; // 2
seg[3] = 7'h4f; // 3
seg[4] = 7'h66; // 4
seg[5] = 7'h6d; // 5
seg[6] = 7'h7d; // 6
seg[7] = 7'h07; // 7
seg[8] = 7'h7f; // 8
seg[9] = 7'h6f; // 9
seg[10] = 7'h77; // A
seg[11] = 7'h7c; // b
seg[12] = 7'h39; // C
seg[13] = 7'h5e; // d
seg[14] = 7'h79; // E
seg[15] = 7'h71; // F
end

//计数器对系统时钟信号进行计数
reg [9:0] cnt = 1'b0;
always@(posedge clk or negedge rst) begin
if(!rst) cnt <= 1'b0;
else if(cnt>=(CNT_40KHz-1)) cnt <= 1'b0;
else cnt <= cnt + 1'b1;
end

//根据计数器计数的周期产生分频的脉冲信号
reg clk_40khz = 1'b0;
always@(posedge clk or negedge rst) begin
if(!rst) clk_40khz <= 1'b0;
else if(cnt<(CNT_40KHz>>1)) clk_40khz <= 1'b0;
else clk_40khz <= 1'b1;
end

//使用状态机完成数码管的扫描和74HC595时序的实现
reg [15:0] data;
reg [2:0] cnt_main;
reg [5:0] cnt_write;
reg [2:0] state = IDLE;
always@(posedge clk_40khz or negedge rst) begin
if(!rst) begin //复位状态下,各寄存器置初值
state <= IDLE;
cnt_main <= 3'd0; cnt_write <= 6'd0;
seg_din <= 1'b0; seg_sck <= LOW; seg_rck <= LOW;
end else begin
case(state)
IDLE:begin //IDLE作为第一个状态,相当于软复位
state <= MAIN;
cnt_main <= 3'd0; cnt_write <= 6'd0;
seg_din <= 1'b0; seg_sck <= LOW; seg_rck <= LOW;
end
MAIN:begin
cnt_main <= cnt_main + 1'b1;
state <= WRITE; //在配置完发给74HC595的数据同时跳转至WRITE状态,完成串行时序
case(cnt_main)
//对8位数码管逐位扫描
//data [15:8]为段选, [7:0]为位选
3'd0: data <= {{dot_en[7],seg[dat_1]},dat_en[7]?8'hfe:8'hff};
3'd1: data <= {{dot_en[6],seg[dat_2]},dat_en[6]?8'hfd:8'hff};
3'd2: data <= {{dot_en[5],seg[dat_3]},dat_en[5]?8'hfb:8'hff};
3'd3: data <= {{dot_en[4],seg[dat_4]},dat_en[4]?8'hf7:8'hff};
3'd4: data <= {{dot_en[3],seg[dat_5]},dat_en[3]?8'hef:8'hff};
3'd5: data <= {{dot_en[2],seg[dat_6]},dat_en[2]?8'hdf:8'hff};
3'd6: data <= {{dot_en[1],seg[dat_7]},dat_en[1]?8'hbf:8'hff};
3'd7: data <= {{dot_en[0],seg[dat_8]},dat_en[0]?8'h7f:8'hff};
default: data <= {8'h00,8'hff};
endcase
end
WRITE:begin
if(cnt_write >= 6'd33) cnt_write <= 1'b0;
else cnt_write <= cnt_write + 1'b1;
case(cnt_write)
//74HC595是串行转并行的芯片,3路输入可产生8路输出,而且可以级联使用
//74HC595的时序实现,参考74HC595的芯片手册
6'd0: begin seg_sck <= LOW; seg_din <= data[15]; end //SCK下降沿时SER更新数据
6'd1: begin seg_sck <= HIGH; end //SCK上升沿时SER数据稳定
6'd2: begin seg_sck <= LOW; seg_din <= data[14]; end
6'd3: begin seg_sck <= HIGH; end
6'd4: begin seg_sck <= LOW; seg_din <= data[13]; end
6'd5: begin seg_sck <= HIGH; end
6'd6: begin seg_sck <= LOW; seg_din <= data[12]; end
6'd7: begin seg_sck <= HIGH; end
6'd8: begin seg_sck <= LOW; seg_din <= data[11]; end
6'd9: begin seg_sck <= HIGH; end
6'd10: begin seg_sck <= LOW; seg_din <= data[10]; end
6'd11: begin seg_sck <= HIGH; end
6'd12: begin seg_sck <= LOW; seg_din <= data[9]; end
6'd13: begin seg_sck <= HIGH; end
6'd14: begin seg_sck <= LOW; seg_din <= data[8]; end
6'd15: begin seg_sck <= HIGH; end
6'd16: begin seg_sck <= LOW; seg_din <= data[7]; end
6'd17: begin seg_sck <= HIGH; end
6'd18: begin seg_sck <= LOW; seg_din <= data[6]; end
6'd19: begin seg_sck <= HIGH; end
6'd20: begin seg_sck <= LOW; seg_din <= data[5]; end
6'd21: begin seg_sck <= HIGH; end
6'd22: begin seg_sck <= LOW; seg_din <= data[4]; end
6'd23: begin seg_sck <= HIGH; end
6'd24: begin seg_sck <= LOW; seg_din <= data[3]; end
6'd25: begin seg_sck <= HIGH; end
6'd26: begin seg_sck <= LOW; seg_din <= data[2]; end
6'd27: begin seg_sck <= HIGH; end
6'd28: begin seg_sck <= LOW; seg_din <= data[1]; end
6'd29: begin seg_sck <= HIGH; end
6'd30: begin seg_sck <= LOW; seg_din <= data[0]; end
6'd31: begin seg_sck <= HIGH; end
6'd32: begin seg_rck <= HIGH; end //当16位数据传送完成后RCK拉高,输出生效
6'd33: begin seg_rck <= LOW; state <= MAIN; end
default: ;
endcase
end
default: state <= IDLE;
endcase
end
end


以上所有代码都是基于图形化实现。


结果展示

项目遇到的难题和解决办法

1.webide使用困难,使用有很多BUG,发现了保存错误以及命名会导致模块无法正常运行的BUG,希望能竟快修复。

2.对FPGA的编程思路不清晰,总是用嵌入式开发的一些想法去考虑问题,导致很多思路上的问题,多看一些其他FPGA的编程项目。

由于本人是做嵌入式开发的,学习内容比较杂乱,软件硬件都学,而且之前接触过一次FPGA,所以实际接受度还是比较高的,在这个任务上没有遇到很大的阻碍,webide的命名问题是我看了官方给出的74系列的模块代码发现并解决的,只要改为简单的命名就不会有问题,因为排除了其他问题所以才以这样的方式解决了这个问题,相信很多小伙伴都没有在WEBIDE上完整实现这个项目,在群里我也发过这个问题,希望能尽快改正吧。

虽然这次WEBIDE的使用体验不是很好,但是我之前尝试过很多图形化编程,也做过很多。成熟的图形化编程就好比积木一样,使用简单。FPGA这种器件感觉本身就和图形化很契合,我相信当拥有庞大的社区后,WEBIDE会完善的越来越好。


项目资源占用报告

本次项目的WBEIDE工程:https://www.stepfpga.com/project/16731/gui?type=top 希望有需要的小伙伴可以参考借鉴,一同来使用和完善WEBIDE的功能。


附件下载
implement.jed
编译好的文件
archive.zip
代码源文件
团队介绍
个人
评论
0 / 100
查看更多
猜你喜欢
2025寒假练 - 基于小脚丫FPGA STEP BaseBoard V4.0实现交通灯控制系统该项目使用了WebIDE的图形化编程,Diamond软件verilog语言,嘉立创IDE绘制PCB板,实现了一个基于小脚丫FPGA STEP BaseBoard V4.0的交通灯控制系统的设计,它的主要功能为:在数码管上显示十字路口四个不同方向的计时信息,交通灯PCB直观展示路口状态,接近传感器检测行人通过路口意图(人员走近),在行人闯红灯时触发蜂鸣器报警,感知环境光并自动点亮路灯。
猫与黄油面包
69
2025寒假练 - 基于小脚FPGA STEP BaseBoard V4.0实现交通灯控制系统该项目使用了verilog语言、webIDE图形化编程,实现了交通灯控制系统的设计,它的主要功能为:通过数码管显示的倒计时控制红(40s)黄(5s)绿(35s)三色的灯跳变,在黄灯的时候蜂鸣器会响。。 该项目使用了verilog语言、Diamond 3.13,实现了环境光、距离检测的设计,它的主要功能为:通过检测环境光,控制led的亮灭;通过点亮的led灯数量来显示物体的距离。。
666xuehao
39
2025寒假练 基于小脚丫FPGA STEP BaseBoard V4.0套件实现交通灯控制系统该项目使用了小脚丫FPGA,lattice diamond和WebIDE开发平台,实现了交通灯控制系统的设计,它的主要功能为:在数码管上显示计时信息 - 图形化 蜂鸣器报警 - 图形化 接近传感器检测人员走近 -Verilog 环境光感知,自动点亮路灯(小脚丫核心板上的单色LED)- Verilog。
CCC_step
43
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号