硬件基础是正点原子开拓者开发板,通过基本的时序电路流水灯来学习FPGA的设计流程。
硬件部分
通过下面硬件可以看到按键所对应的板子的接口,同时也可以发现为什么复位在仿真的时候是低电平,因为按下的时候和GND导通了。按键没有按下的时候,RESET是高电平,按键按下的时候是低电平。
软件部分
正点原子的开拓者开发板上的时钟是50Mhz的,这里涉及到的循环左移的语法,可以参考
Verilog语法基础
module flow_led(
input sys_clk,
input sys_rst,
output reg [3:0] led
);
reg [23:0] counter;
//**************************************
// main code ///
//*************************************//
//计数器对系统进行时钟计数,计时0.2s
//50M的频率,那么0.2s要计数:0.2*50*1000*1000=1000_0000 //这里的_可有可无,方便观察
//目前有个疑问,时钟50Mhz
always @(posedge sys_clk or negedge sys_rst) begin //系统时钟上升沿和复位信号下降沿都会触发
if(!sys_rst)
counter <= 24'd0;
else if(counter< 24'd1000_0000 - 1'b1) //减去1,0的时候有一个时序,一直到9还有一个时序,总共是是个
counter <= counter + 1'b1;
else
counter <= 24'd0;
end
//判断条件更改LED状态,因为使用的是reg
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
led <= 4'b0001;
else if(counter == 24'd1000_0000 - 1'b1)
led[3:0] <= {led[2:0],led[3]}; //利用组合的方式,进行循环移位操作
else
led <= led;
end
endmodule
这里面主要有一些细节和语法需要熟悉。
仿真部分
`timescale 1ns/1ns // 定义仿真单位是1ns和仿真时间1ns
module flow_led_tb; // 测试模块
parameter T=20; //定义一个参数,时间周期是20ns
//reg define
reg sys_clk; // 时钟信号
reg sys_rst; // 复位信号
//wire define
wire [3:0] led; //这里使用wire是因为这个输出信号,在仿真程序中用不到
//*****************************************************
//** main code
//*****************************************************
//给输入信号初始值
initial begin
sys_clk =1'b0;
sys_rst =1'b0;
//#是延时的作用,后面的数字即延时时间,单位是定义的仿真timescale
#(T+1) sys_rst = 1'b1; // 在第21ns的时候复位信号信号拉高
end
//50Mhz的时钟,周期则为1/50Mhz=20ns,所以每10ns,电平取反一次
always #(T/2) sys_clk = ~sys_clk;
//例化led模块 将程序模块flow_led例化为u0_flow_led
//前面是程序中的信号,后面应该是例化为新的仿真信号名。
flow_led u0_flow_led (
.sys_clk (sys_clk ),
.sys_rst (sys_rst),
.led (led )
);
endmodule
下图是仿真,对区段进行截取可以看到200ms,LED的时间变化一次。
下载程序到板子中,也可以看到实现了流水灯,需要经常学习仿真的使用,之后对时序严格后要注意一些小问题的出现。