FPGA学习笔记之流水灯(1)

来源:互联网 发布:gps pf11导航仪端口 编辑:程序博客网 时间:2024/06/01 10:35

FPGA学习笔记之流水灯(1)

FPGA的开发上手并不难,但是想成为顶尖高手十分不易,不知道要流过多少汗水,写过多少万行代码,调试过多少板子。但是我们不能因为山高难爬就放弃攀登,不能因为美人难追就放弃追求吧,况且学习的过程中也有诸多乐趣。现在就从大家最常接触的流水灯开始入手学习FPGA的开发,将实现多种样子的流水灯。开发语言采用Verilog。

  • 功能描述
  • 代码
  • 总结

功能描述

有编号1、2、3、4共4个LED灯,实现1灯至4灯的循环点亮,每次点亮1个LED灯。复位时所有灯全亮。

代码

下面代码将采用多种方式实现同等功能。

思路1:采用if语句实现。为使代码直观明了,使用两个always块,一个用于计时,一个根据所计时间判断该第几个灯点亮。

module led_top(     input           clk,             //系统时钟,50MHz     input           rst_n,           //复位     output reg[3:0] led              //输出    );parameter LED_CNT1 = 25_000_000;       //每数0.5秒LED闪一次parameter LED_CNT2 = LED_CNT1 * 2;parameter LED_CNT3 = LED_CNT1 * 3;parameter LED_CNT4 = LED_CNT1 * 4; reg [31:0] count;always @(posedge clk or negedge rst_n)  //计数器在0~LED_CNT4-1之间循环begin  if(!rst_n)    count <= 0;  else if(count == LED_CNT4 -1)    count <= 0;  else    count <= count + 1;endalways @(posedge clk or negedge rst_n)begin  if(!rst_n)     led <= 4'b1111;  else if(count == LED_CNT1-1)     led <= 4'b0001;  else if(count == LED_CNT2-1)     led <= 4'b0010;  else if(count == LED_CNT3-1)     led <= 4'b0100;  else if(count == LED_CNT4-1)        led <= 4'b1000;   endendmodule

思路2:采用case语句实现。定义5种状态,分别对应复位时灯全亮、第一支灯亮、第二支灯亮、第三支灯亮、第四支灯亮,根据计数器的指示,进行状态跳转。

module led02_top(     input           clk,    //FPGA时钟,50MHz     input           rst_n,  //复位     output reg[3:0] led     //输出灯    );parameter LED_CNT    = 25_000_000;     //即0.5 秒              parameter state_idle = 5'b00001;parameter ledstate1  = 5'b00010;parameter ledstate2  = 5'b00100;parameter ledstate3  = 5'b01000;parameter ledstate4  = 5'b10000;reg [31:0] count;             //时间计数器reg        led_en;            //跳转指示器,每当其为1时,赋值给下一灯reg [4:0]  led_state;         //当前状态always @(posedge clk or negedge rst_n)  //计数器在0~LED_CNT4 -1之间循环begin  if(!rst_n)    begin        count   <= 0;        led_en  <= 0;             //指示器为0    end  else if(count == LED_CNT-1)    begin      count   <= 1;      led_en  <= 1;               //指示器为1    end  else    begin      count  <= count + 1;      led_en  <= 0;               //指示器为0    endendalways @(posedge clk or negedge rst_n)    //完成状态跳转begin  if(!rst_n)    begin      led_state <= state_idle;    end  else if(led_en == 1'b1)     begin      case(led_state)          state_idle: led_state <= ledstate1;          ledstate1:  led_state <= ledstate2;          ledstate2:  led_state <= ledstate3;          ledstate3:  led_state <= ledstate4;          ledstate4:  led_state <= ledstate1;          default:    led_state <= state_idle;      endcase    endendalways @(posedge clk or negedge rst_n)   //每种状态对应的LED灯赋值begin  if(!rst_n)    begin      led <= 4'b1111;    end  else    begin      case(led_state)          state_idle:led <= 4'b1111;          ledstate1: led <= 4'b0001;          ledstate2: led <= 4'b0010;          ledstate3: led <= 4'b0100;          ledstate4: led <= 4'b1000;          default:   led <= 4'b1111;       endcase     endend endmodule

总结

代码1和代码2分别用if…else语句和case语句实现相同的功能。在代码2中,并未严格按三段式状态机来写,这里先以实现功能为主,在后续的学习中再研究三段式状态机的写法。

通常来说,if-else语句生成具有优先级的编码逻辑,速度较慢,占用的面积小,对速度没有要求但对面积有较高要求的情形。case语句生成并行的编码逻辑,速度较快,占用的面积大,适合对速度有较高要求的情形。

原创粉丝点击