本帖最后由 abner_ma 于 2020-11-27 21:39 编辑

FPGA设计的一个难点,就是设计技巧和规则的掌握,下面来看一个简单例子的实现过程,作为初级入门案例。

一、按键按下实现LED点亮

当LED引脚输出低电平时LED点亮,

(1)代码实现如下

  1. module test(clk,rst_n,led);
  2. input clk ;
  3. input rst_n ;
  4. output reg led ;
  5. always @ ( posedge clk or negedge rst_n)
  6. begin
  7.         if(!rst_n)
  8.                 begin
  9.                         led<=0;
  10.                 end
  11.         else
  12.         begin
  13.                         led<=1;
  14.         end
  15. end
  16. endmodule

(2)基础语法要点:

在always里面被赋值必须是reg变量。

凡是在时序电路中被赋值的变量 必须是非阻塞赋值。always @ ( posedge clk or negedge rst_n)

凡是在组合电路中被赋值的变量 必须是阻塞赋值always @ ( *)

(3)Modelsim仿真测试文件。
      
  1. `timescale 1 ps/ 1 ps
  2. module test_tb();
  3. reg clk;
  4. reg rst_n;                                             
  5. wire led;                 
  6. test i1 (
  7.         .clk(clk),
  8.         .led(led),
  9.         .rst_n(rst_n)
  10. );
  11. initial                                                
  12. begin                                                                                            
  13. $display("Running testbench");      
  14. clk=0;
  15. rst_n=0;
  16. #1000 rst_n=1;
  17. end                                                   
  18. always #10 clk=~clk;                                                   
  19. endmodule
                                         


  • 输入都改为reg(系统产生)
  • 输出都改为wire:连线(系统产生)
  • 实例化模块并连接导线。(系统产生)
  • initial中初始化变量。(自己修改)
  • always产生时钟。(自己修改)

(4)Modelsim仿真

仿真中常用命令:

do wave.do

restart

run 0.1ms

(5)如果点亮四个LED呢?

改变led输出变量的位宽:

  1. module test(clk,rst_n,led);
  2. input clk ;
  3. input rst_n ;
  4. output reg [3:0]]led ;
  5. always @ ( posedge clk or negedge rst_n)
  6. begin
  7.         if(!rst_n)
  8.                 begin
  9.                         led<=4'b1111;
  10.                 end
  11.         else
  12.         begin
  13.                         led<=4'b0000;
  14.         end
  15. end
  16. endmodule

同样改变测试文件位宽

wire [3:0] led ;

二、状态机设计实现流水灯

(1)模块代码

  1. module test(clk,rst_n,led);
  2. input clk ;
  3. input rst_n ;
  4. output reg [3:0]led ;
  5. reg[1:0] state;
  6. always @ ( posedge clk or negedge rst_n)
  7. begin
  8.         if(!rst_n)
  9.                 begin
  10.                         led<=4'b1111;
  11.                         state<=0;
  12.                 end
  13.         else
  14.         begin
  15.                 case(state)
  16.                         0:begin
  17.                                 led<=4'b0111;
  18.                                 state<=1;
  19.                         end
  20.                         1:begin
  21.                                 led<=4'b1011;
  22.                                 state<=2;                       
  23.                         end
  24.                         2:begin
  25.                                 led<=4'b1101;       
  26.                                 state<=3;                               
  27.                         end
  28.                         3:begin
  29.                                 led<=4'b1110;
  30.                                 state<=0;                       
  31.                         end
  32.                         default:
  33.                                 state<=0;
  34.                         endcase
  35.         end
  36. end
  37. endmodule
(2)状态机正确仿真:



(3)设计要点

注意state变量的赋初值。

(4)频率反转太快、看不出LED效果。

改善方法1:

状态机中增加计数器。

  1. module test(clk,rst_n,led);
  2. input clk ;
  3. input rst_n ;
  4. output reg [3:0]led ;
  5. reg[1:0] state;
  6. reg [3:0] counter;
  7. always @ ( posedge clk or negedge rst_n)
  8. begin
  9.         if(!rst_n)
  10.                 begin
  11.                         led<=4'b1111;
  12.                         state<=0;
  13.                         counter<=0;
  14.                 end
  15.         else
  16.         begin
  17.                 case(state)
  18.                         0:begin
  19.                                 led<=4'b0111;
  20.                                 if(counter<12)
  21.                                         counter<=counter+1;
  22.                                 else
  23.                                         begin
  24.                                                 counter<=0;
  25.                                                 state<=1;
  26.                                         end
  27.                         end
  28.                         1:begin
  29.                                 led<=4'b1011;
  30.                                 if(counter<12)
  31.                                         counter<=counter+1;
  32.                                 else
  33.                                         begin
  34.                                                 counter<=0;
  35.                                                 state<=2;
  36.                                         end               
  37.                         end
  38.                         2:begin
  39.                                 led<=4'b1101;       
  40.                                 if(counter<12)
  41.                                         counter<=counter+1;
  42.                                 else
  43.                                         begin
  44.                                                 counter<=0;
  45.                                                 state<=3;
  46.                                         end                               
  47.                         end
  48.                         3:begin
  49.                                 led<=4'b1110;
  50.                                 if(counter<12)
  51.                                         counter<=counter+1;
  52.                                 else
  53.                                         begin
  54.                                                 counter<=0;
  55.                                                 state<=0;
  56.                                         end                       
  57.                         end
  58.                         default:
  59.                                 state<=0;
  60.                         endcase
  61.         end
  62. end
  63. endmodule


(5)设计要点:

同一变量不能同时在两个always块内复制,如分频和状态机的两个always块,复位时复位什么变量由本块内用到的变量决定。

基础十分重要,是FPGA设计的前提。通过以上学习我们学会了状态机  计数器  时钟分频电路的设计。

以上代码中包含了分频,LED状态机等多个功能模块。

  1. module test(clk,rst_n,led);
  2. input clk ;
  3. input rst_n ;
  4. output reg [3:0]led ;
  5. reg[1:0] state;
  6. reg [3:0] counter;
  7. reg clk_show;
  8. always @ ( posedge clk or negedge rst_n)
  9. begin
  10.         if(!rst_n)
  11.                 begin
  12.                         clk_show<=0;
  13.                         counter<=0;
  14.                 end
  15.         else
  16.                 if(counter<12)
  17.                         counter<=counter+1;
  18.                 else
  19.                         begin
  20.                                 counter<=0;                       
  21.                                 clk_show=~clk_show;
  22.                         end
  23. end
  24. always @ ( posedge clk_show or negedge rst_n)
  25. begin
  26.         if(!rst_n)
  27.                 begin
  28.                         led<=4'b1111;
  29.                         state<=0;
  30.                 end
  31.         else
  32.         begin
  33.                 case(state)
  34.                         0:begin
  35.                                 led<=4'b0111;
  36.                                 state<=1;
  37.                         end
  38.                         1:begin
  39.                                 led<=4'b1011;
  40.                                 state<=2;       
  41.                         end
  42.                         2:begin
  43.                                 led<=4'b1101;       
  44.                                 state<=3;                       
  45.                         end
  46.                         3:begin
  47.                                 led<=4'b1110;
  48.                                 state<=0;       
  49.                         end
  50.                         default:
  51.                                 state<=0;
  52.                         endcase
  53.         end
  54. end
  55. endmodule
  56. 测试:
  57. `timescale 1 ps/ 1 ps
  58. module test_tb();
  59. // constants                                          
  60. // general purpose registers
  61. // test vector input registers
  62. reg clk;
  63. reg rst_n;
  64. // wires                                               
  65. wire [3:0]led;
  66. // assign statements (if any)                          
  67. test i1 (
  68. // port map - connection between master ports and signals/registers   
  69.         .clk(clk),
  70.         .led(led),
  71.         .rst_n(rst_n)
  72. );
  73. initial                                                
  74. begin                                                  
  75. // code that executes only once                        
  76. // insert code here --> begin                          
  77.                                                       
  78. // --> end                                             
  79. $display("Running testbench");      
  80. clk=0;
  81. rst_n=0;
  82. #1000 rst_n=1;
  83.                  
  84. end                                                   
  85. always #10 clk=~clk;                                                   
  86. endmodule