FPGAverilog呼吸灯_全流程Verilog开发_C语言设计仿真_C到Verilog转化_Testbench+Verilog的modelsim仿真_Verilog编译综合生成流文件_上板子调试

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/Mr_liu_666/article/details/102178330

完整的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,灯只有一个亮了,四个都亮太晃眼哈哈哈哈。现象如下:

猜你喜欢

转载自blog.csdn.net/Mr_liu_666/article/details/102178330