fpga 电梯项目

累死我了。昨天下午到今天中午。

累不累不要紧,主要是这是期末复习周。分秒寸金的复习周。

吐槽两句

调试:

vivado,verilog的开发方式和其他语言不太一样。调试的话,要么仿真,要么建立一个debug core调试核,要么下板。一开始,觉得很快就能做完;觉得编写仿真文件,或者现学调试不合算,我选择直接下板。然后被这个反复下板浪费的时间折磨到了。

而且三阶段,一个是分析,一个是硬件,一个是比特流,每一项都花时间,每一项都走不开,不能像是“让程序慢慢跑,吃个饭先”之类的。

下次一定仿真。

暂时不要相信gpt的复杂代码水平

基于python或c或go之类的几十行一两百行还好,这种复杂的程序真的是难为gpt这种泛用模型了。尤其是verilog还是个非主流语言。

而且,我这个项目,是网络上已经有不少现成的,gpt是将它们按照我的要求缝在了一起。有的地方缝错位了,有的地方不该缝的缝上了。还有有的地方我以为缝错了其实缝对了。导致修改花了绝大多数时间。

不过,要我自己从零写,不知道要花多少时间。我没这个时间也没这个精力再写一次。

遗憾:

fpga开发板贵的一批。学校给了我使用的机会,但我没有珍惜。

下次一定。

基本架构

有以下几个部分:

  • top:顶层文件
  • key_debounce:按键消抖
  • matrix_key:矩阵键盘。实际使用四个键,属于是卵用没有,只能添乱。
  • switch_control:拨码开关控制(并输出floor查看运行状态)
  • clk_div:理论有用但实际没用,全他妈用的是自己分频…………这个模块对我的唯一贡献,是给led_control模块塞了一个花了我好长时间的bug……
  • seg_control:控制数码管显示。大改过。
  • led_control:控制led和电梯上下楼,名副其实的灵魂模块。
  • beep_control:一个意义不明的模块,我不知道gpt本来是想做什么,反正它在我这里就是一个运行指示器。

top里面重要的reg:

  • row行信号,设置为1110
    • 一开始设的是0001,纳闷了好久。
  • 几个led灯
  • key_in和key_out
  • floor和floor_out
    • floor是寄存器,作为模块输入,不能作为输出。
    • 要改变floor的值,需要通过一个wire,floor_out来转接。
    • 我在top里面加了一句always @(posedge clk) floor<=floor_out; endmodule,用来将这两个直接相连。

模块介绍

top:顶层文件

模块例化,将floor_out和floor链接。

`timescale 1ns / 1ps不知道有没有用,总之加上就是了。之前因为这一句翻过车。

总之就是要把各个变量对应好,不要出现什么时钟频率错误,in和out变量错误什么的。

key_debounce:按键消抖

基本原理是检测到按键按下,然后等20个时钟周期再看看,如果还是按下,那就真的按下了,输出按键信息。

switch_control:拨码开关控制(并输出floor查看运行状态)

其实也是个没卵用的模块,把二位的led_status分割成一个rst一个start。我是不知道为什么我不在xdc里面直接定义rst和start……可能是闲得蛋疼。

但是我还是保留了,毕竟能正常工作,还能加点其他功能,不在其他模块碍眼。例如打印floor状态。

clk_div:理论有用但实际没用,全他妈用的是自己分频…………这个模块对我的唯一贡献,是给led_control模块塞了一个花了我好长时间的bug……

字面意思,理论上应该用这个控制所有时钟分频,但是我的模块用分频的少,所以都自己分了。

 seg_control:控制数码管显示。大改过。

大改指的是把本来的全部注释掉然后重写。

主要是因为我改了matrix_key,没用,导致编码从8421变成了独热码。而且我的floor只有两位,按键四个,不需要那么复杂的东西。

两个数码管,交替选择,选择时显示内容。

如果不使用分频,会导致残影。理论上需要专门的方法去除,但是我懒狗,我是把频率降一下就当没看到残影。我是用的是1000hz。

led_control:控制led和电梯上下楼,名副其实的灵魂模块。

首先是判断key_in,如果非零,那就说明按键按下。在这个情况下,需要根据floor和key的内容选择新的floor。

松开按键,则key就会归零,于是针对key我使用了一个key_reg保存上一次的输入。所有判断都是在计时器计满之后执行的;都是基于上一次key的输入来选择判断。

好吧,实际用到key_reg的只有一处,控制led灯那里。要求是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
led_out0:按下KEY0键,若电梯不在1楼,则LED0亮;电梯到达1楼后,LED0指示灯灭掉
由于按下key0,电平会从高变低,因此是:
若为一楼停靠:00:led0灭,为0
若为二楼停靠,或者其他状态:key0取反

led_out1
按下KEY1键, 若电梯不在2楼,则LED1亮,电梯到达2楼后,LED1指示灯灭掉.
由于按下key1,电平会从高变低,因此是:
若为一楼停靠,或其他状态:key1取反,若key1按下,则为1,若未按下,则为0
若为二楼停靠:01:led1灭,为0

led_out2
电梯在2楼,按KEY2键, 则LED2亮,电梯到1楼后LED2
0111:key2取反
0010:设0

led_out3
电梯在1楼,按KEY3键, 则LED3亮,电梯到2楼后LED3灭。
0010:key3取反(一楼、一楼到二楼)
0111:设0

本来有很多用了key_reg的,砍掉了。

还有就是运行时灯的流动,

1
2
led_reg,五个灯,0.1秒移动一次,在电梯运行时移动。
led_reg则是对应G5~T4,从左到右分别01234

代码:
1
2
2'b10: led_reg <= {led_reg[3:0],led_reg[4]<=1}; //如果电梯上行,LED11至LED7从左到右轮流点亮
2'b11: led_reg <= {led_reg[0]<=1,led_reg[4:1]}; //如果电梯下行,LED11至LED7从右到左轮流点亮

注意不是流水灯,但大差不差。

beep_control:一个意义不明的模块,我不知道gpt本来是想做什么,反正它在我这里就是一个运行指示器。

改了,改成了到站叫一声。

使用了一个timer_start一个beep_enable来分别控制counter和timer,timer控制时长,counter控制频率。


fpga 电梯项目
http://petertan303.github.io/2023/06/13/fpga-电梯项目/
作者
peter?
发布于
2023年6月13日
许可协议