版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
完整的FPGA Verilog开发包括:C语言设计仿真,C到Verilog转化,Testbench+Verilog的modelsim仿真,Verilog编译综合生成流文件,上板子调试的所有步骤,而不只是verilog直接设计,否则排错难,编译慢,适合小的系统,可能一下子就出来了也可能卡住了很久都出不来,以上的处理方法能做到开发稳定,很少出错。
这次自己做了一个呼吸灯Verilog工程,逻辑不复杂,但是之前也错过很多次,碰巧正确了也不清楚为什么正确,所以采用了标准可靠的方法进行了设计,流程如下:
首先检查硬件,烧录例程,现象如下:
逻辑很简单,就是带复位的流水灯,经过这一步我们确定了板子、quartus、引脚分配、下载器等都没有问题。
开始编写C:
for(t = 0; t < 200 ; t++)//这个算是主循环了 ,就是主时钟
{
for(j = 0; j < 20; j++)//这个是正常闪烁 ,就是普通闪烁时钟
{
if(j < k)
printf("--");
else
printf("_ ");
}
printf("\n");
i++;
if(i%2) k++;//就是改变标志值的时钟
if(k > 20) k = 0;
Sleep(500);
}
转化的时候,最外面的for相当于敏感变量是主时钟的always块,里面的正常闪烁相当于一个毫秒级的定时器,计数前一半的时候LED亮,后一半熄灭,这样就能实现一个LED的亮度调节,如果占空比一半的话,亮度就是一半,占空比1/3的话,亮度也是1/3,下面的if调整亮度,每来40个(2*20个)主时钟周期,改变一下 占空比,实现了呼吸灯。
这个是控制台输出的波形图。
将C转化成Verilog:
module flow_led(
input sys_clk , //系统时钟
output reg [3:0] led //4个LED灯
);
//reg define
reg [23:0] counter_Normal;
reg [23:0] counter_Change;
reg [23:0] counter_Compare;
//*****************************************************
//** main code
//*****************************************************
//两个计数器,一个组合逻辑
always @(posedge sys_clk)
begin
//if(counter_Normal < 24'd5_0000)//24'd1000_0000 -- 200ms 除以200
if(counter_Normal < 24'd50)
counter_Normal <= counter_Normal + 1'b1;
else
counter_Normal <= 24'd0;
end
always @(posedge sys_clk)
begin
//if(counter_Compare < 24'd5_0000)//24'd1000_0000 -- 200ms 除以200
if(counter_Compare < 24'd50)
begin
if(counter_Change % 3 == 0)//主时钟变三次,占空比变一次
counter_Compare <= counter_Compare + 1'b1;
end
else
counter_Compare <= 24'd0;
end
always @(posedge sys_clk)
begin
//if(counter_Change < 24'd5_0000)
if(counter_Compare < 24'd50)
counter_Change <= counter_Change + 1'b1;
else
counter_Change <= 24'b0;
end
always @(posedge sys_clk)
begin
if(counter_Normal < counter_Compare)//小于就亮,大于就灭
led[3:0] <= 4'b0000;
else
led[3:0] <= 4'b1111;
end
endmodule
设置了三个寄存器变量,Normal将50M的主时钟50000分频,得到周期1ms的时钟,这里为了仿真看起来更加方便,把周期改成了1us,现象如下:
可以看到占空比在变化
建立Verilog工程:
//C语言测试好使的,完成了功能级的测试
// int main()
// {
// int i=0,j=0,k=10;
// int t;
// for(t = 0; t < 200 ; t++)//这个算是主循环了
// {
// for(j = 0; j < 20; j++)//这个是正常闪烁
// {
// if(j < k)
// printf("--");
// else
// printf("_ ");
// }
// printf("\n");
// i++;
// if(i%2) k++;
// if(k > 20) k = 0;
// Sleep(500);
// }
// }
module breathled(
input sys_clk , //系统时钟
output reg [3:0] led //4个LED灯
);
//reg define
reg [23:0] counter_Normal;
reg [23:0] counter_Change;
reg [23:0] counter_Compare;
//*****************************************************
//** main code
//*****************************************************
//两个计数器,一个组合逻辑
always @(posedge sys_clk)
begin
if(counter_Normal < 24'd5_0000)//24'd1000_0000 -- 200ms 除以200
//if(counter_Normal < 24'd50)
counter_Normal <= counter_Normal + 1'b1;
else
counter_Normal <= 24'd0;
end
always @(posedge sys_clk)
begin
if(counter_Compare < 24'd5_0000)//24'd1000_0000 -- 200ms 除以200
//if(counter_Compare < 24'd50)
begin
if(counter_Change % 1000 == 0)//主时钟变三次,占空比变一次
counter_Compare <= counter_Compare + 1'b1;
end
else
counter_Compare <= 24'd0;
end
always @(posedge sys_clk)
begin
if(counter_Change < 24'd5_0000)
counter_Change <= counter_Change + 1'b1;
else
counter_Change <= 24'b0;
end
always @(posedge sys_clk)
begin
if(counter_Normal < counter_Compare)//小于就亮,大于就灭
led[3:0] <= 4'b1110;
else
led[3:0] <= 4'b1111;
end
endmodule
与仿真区别就是周期改回了1ms,灯只有一个亮了,四个都亮太晃眼哈哈哈哈。现象如下: