器材准备:
EP4CE6E22C8N板子,下载器。
电路图:
逻辑框架
因为这是一个流水灯,所以需要有一个时序逻辑关系,也就需要一个时钟信号。所以需要给模块设计一个时钟输入信号。此外,如何让机器上电的时候让流水灯在定义的最开始的状态开始执行,也是另外一个问题。因此,需要在输入端设计复位和时钟两个信号的输入。
类比C语言程序,这一个时序逻辑模块里面有两个功能模块。一个是定时计时功能的,一个是根据定时输出流水灯信号的模块。在FPGA里面,也就是硬件里面。不像程序那样按照顺序执行,一个电路里面所有元器件在上电瞬间就一起工作了(在不考虑电容延时、和门级电路延时的情况下),所以FPGA是并行工作的。
-----------------------------分界线----------------------------------
Verilog代码:
module flow_led(
input sys_clk ,
input sys_rst_n,
output reg [3:0] led );
reg [23:0] counter;
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
counter <= 24'd0;
else if (counter < 24'd1000_0000)
counter <= counter + 1'b1;
else
counter <= 24'd0;
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
led <= 4'b0001;
else if(counter == 24'd1000_0000)
led[3:0] <= {led[2:0],led[3]};
else
led <= led;
end
endmodule
------------------------------分界线---------------------------------
详解:
代码中,定义了sys_clk、sys_rst_n两个输入端口,输出是一个四位的寄存器。这里定时200ms改变一次led状态。与sys_clk连接的是外部50Mhz晶振,这个提供了稳定的时钟源。
由于50Mhz对应一个周期为:0.000000002s=0.000002ms。所以对应200ms需要24'd1000_0000(带宽为24的10进制数:10000000)个上升沿信号,当达到这个数量的计数时候,计数寄存器清零,并且更换一次led状态。
此外,寄存器数据位移的实现,根据寄存器数据拆分再组合的逻辑来表达。例如寄存器初值为:0001。{led[2:0],led[3]}表示为寄存器的0~2位和3位组合成新的数据并放进寄存器。在这个程序中,顺序为:
0001-》0010-》0100-》1000-》0001
------------------------------分界线---------------------------------
最后,生成代码之前,还需要对管脚进行安排。需要根据对应电路板的电路图进行引脚安排。例如:硬件电路上,时钟晶振的引脚接到了23引脚上,那就设置成对应的引脚即可。其他引脚如此类推。
引脚接口示意图如下:
设置引脚过程:
最后烧录进去板子,流水灯跑起来。