完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
笔者从接触FPGA买开发板到现在已经过去三四个月了,看了特权同学、黑金、小墨同学、西瓜团队的资料。总的来说看的多写的少,其实学习任何东西必须实践,看的再多也不行,从今天开始。对FPGA的基础、例程review 一遍。。 一、led 流水灯中的并行和顺序执行 下面先上黑金的程序: `timescale 1ns / 1ps module led_test( clk, //开发板上的时钟输入 rst_n, //复位键 led //led 四位 ); //===================================================== // PORT declaration //===================================================== input clk; input rst_n; output [3:0] led; // 寄存器定义 reg [31:0] timer; reg [3:0] led; //======================================================= //计数器计数循环计数4s //======================================================= always @(posedge clk or negedge rst_n) begin if (~rst_n) timer <= 0; else if (timer == 32'd199_999_999) //定时器计时4秒(50M*4-1=199_999_999) timer <= 0; //计数器计满清零 else timer <= timer + 1'b1; //计数器加一 end //======================================================= else if (timer == 32'd49_999_999) //计数器计 到1秒, // Led 控制 //======================================================= always @(posedge clk or negedge rst_n) // 检测时钟上升沿和复位键的下降沿 begin if(~rst_n) led <= 4'b1111; // 检测复位键完成LED初始化全部熄灭 else if (timer == 32'd49_999_999) //计数器计 到1秒, led <= 4'b1110; //LED1点亮 else if (timer == 32'd99_999_999) //计数器计 到2秒, led <= 4'b1101; //LED2点亮 else if (timer == 32'd49_999_999) //计数器计 到3秒, led <= 4'b1011; //LED3点亮 else if (timer == 32'd49_999_999) led <= 4'b0111; end endmodule 上面这是一个完整的led.v文件,我们只看计数部分,第一个always 块是做了一个4s的循环计数,通俗的讲就是一个周期4s的时钟。第二个always块是四个led的循环现实,学过单片机的同学会觉得很亲切有种C语言的流水灯的意思。那么问题来了FPGA语言指令不是并行的吗?这个貌似是顺序执行的啊。这个问题先放着我们下面看特权同学的程序。 module led_water(led,clk); // 模块名及端口参数 output[3:0]led; // 输出端口定义 input clk; // 输入端口定义,50M 时钟 reg[3:0] led; //变量led_out 定义为寄存器型 //reg[4:0] led1; //变量led_out 定义为寄存器型 reg[24:0] counter; //变量led_out 定义为寄存器型 always@(posedge clk) begin counter<=counter+1; if(counter==25'd25000000) begin led<=led<<1; // led 向左移位,空闲位自动添0 补位 counter<=0; //计数器清0 if(led==8'b0000) //每到时间临界点后,左移一位,一直到8位全部都变为0 led<=8'b1111; //重新赋值为全1, end end endmodule 特权的程序就更像C语言了,这个循环程序跟单片机的流水灯简直一模一样。咱们再看看《verilog HDL 那些事儿_建模片》中的程序: module top_module ( CLK, RSTn, LED_Out ); input CLK; input RSTn; output [3:0]LED_Out; /*******************************/ wire LED0_Out; led0_module U1 ( .CLK( CLK ), .RSTn( RSTn ), .LED_Out( LED0_Out ) ); /*********************************/ wire LED1_Out; led1_module U2 ( .CLK( CLK ), .RSTn( RSTn ), .LED_Out( LED1_Out ) ); /*********************************/ wire LED2_Out; led2_module U3 ( .CLK( CLK ), .RSTn( RSTn ), .LED_Out( LED2_Out ) ); /*********************************/ wire LED3_Out; led3_module U4 ( .CLK( CLK ), .RSTn( RSTn ), .LED_Out( LED3_Out ) ); assign LED_Out = { LED3_Out, LED2_Out, LED1_Out, LED0_Out}; endmodule module led0_module // 这个模块有四个 ledo led1 led2 led 3 ( CLK, RSTn, LED_Out ); input CLK; input RSTn; output LED_Out; /*************************************/ //DB4CE15 开发板使用的晶振为 50MHz,50M*0.01=5_000_000 parameter T100MS = 23'd5_000_000; /*************************************/ reg [22:0]Count1; always @ ( posedge CLK or negedge RSTn ) if( !RSTn ) Count1 <= 23'd0; else if( Count1 == T100MS ) Count1 <= 23'd0; else Count1 <= Count1 + 1'b1; /*************************************/ reg rLED_Out; always @ ( posedge CLK or negedge RSTn ) if( !RSTn ) rLED_Out <= 1'b0; else if( Count1 >= 23'd0 && Count1 < 23'd1_250_000) //只有这一句代码不同,在不同时间点亮不同的灯 rLED_Out <= 1'b1; else rLED_Out <= 1'b0; assign LED_Out = rLED_Out; endmodule 巴拉巴拉这么多,其实上面就是把四个led各自写了一个模块,在顶层分别例化了一遍,程序执行是每个模块都进入执行状态但是在各自的时间段点亮各种的led。程序流程如下: 再看流水灯是不是有点儿并行的意思了,现在回过头来说黑金和特权同学的程序,在always块中的程序执行就是顺序执行的并且使用了if 语句可以说就是c语言的思想。但是做FPGA的话还是需要转变一下思想:并行 二、verilog 语法 (1) // PORT declaration //实体定义 input clk; input rst_n; output [3:0] led; // 寄存器定义 reg [31:0] timer; reg [3:0] led; //问题 下面两条语句的关系 output [3:0] led; reg [3:0] led; assign led= led; 一个是实体一个是寄存器,流水灯的第三个程序中是 assign LED_Out = rLED_Out; 定义的不一样必须进行赋值语句,定义的相同就不同赋值了其实编译器综合的时候是赋值了的。 三、顺序执行和并行执行(看的建模篇的资料) 上图是一个组合模块,里边包含了两个功能模块。一是对闪耀灯控制的功能模块,二是对流水灯控制的功能模块。假设我要利用“顺序操作”实现如图的功能模块。实际上是怎样的一个效果呢?C 语言 While ( 1 ) //大循环 { Flash_Funct(); //闪耀功能模块 Run_Funct(); //流水灯功能模块 } C语言是面向过程的语言,简言之上面的程序不管你的处理器速度多快两条语句之间至少有一条指令的时间间隔。下面是verliog 语言 module top_module ( ...... ); flash_module U1 //功能模块 1 实例化 ( ...... ); run_module U2 //功能模块 2 实例化 ( ...... ); 不同的module都是在上电的第一时刻开始执行的,是完全并发的。但是有一点不是模块内部的操作也都是并行执行的,笔者开始学习时水的不行总是存在误解。 继续前面的并行执行方式,实现闪耀灯和流水灯的模块程序。 程序不贴了了都在附件里,很简单。 可以自行编译观察一下资源的开销情况,体会一下程序思想。
led.rar
(8.62 MB, 下载次数: 18
)
|
|
相关推荐
|
|
基本FPGA或者树莓派或者其它微处理器(尽量压缩成本且完成项目)DFB激光器稳频
1169 浏览 1 评论
2302 浏览 1 评论
助力AIoT应用:在米尔FPGA开发板上实现Tiny YOLO V4
1177 浏览 0 评论
3439 浏览 1 评论
3075 浏览 0 评论
2295 浏览 58 评论
6146 浏览 113 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-24 21:04 , Processed in 0.563138 second(s), Total 66, Slave 48 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号