当前位置:   article > 正文

【FPGA/verilog -入门学习3】verilog脉冲计数_fpga脉冲计数

fpga脉冲计数

需求:

1,在EN为高电平时,对输入的Pluse 脉冲计数,每个上升沿计数一次

2,EN 为低电平时,输出计数值和计数完成状态

需求分析:

输入输出

输入:clk,rest_n,i_en,pluse

输出:o_cnt ,o_state

操作步骤

输入端推进:

步骤1,对pluse 进行脉冲边沿检测,识别出每次上升沿,用于后续的计数

输出端获取:

步骤2,对输出o_state 实现方式:在每一次en=0 时识别为计数结束。可以用脉冲边沿检测法,检测en信号的下降沿作为o_state 的结束信号

步骤3:使用内部寄存器r_cnt ,当en=1时,pluse 的上升沿脉冲计数。计数到en= 0 时清零。

步骤4:当en = 0时,且r_cnt 有数值,将o_cnt <=r_cnt.

vlg_design

  1. /
  2. /*
  3. 脉冲计数,当是能时,对pluse脉冲计数
  4. 实现步骤
  5. 1)产生pluse 上升沿脉冲 一个clk时钟
  6. 2)产生i_en 下降沿,当下降沿 o_state=1
  7. 3)对pluse上升沿计数,锁存在r_cnt
  8. 4)当o_state=1 时,o_cnt<=r_cnt
  9. */
  10. /
  11. `timescale 1ns/1ps
  12. module vlg_design(
  13. input clk,//100M
  14. input pulse,//
  15. input rest_n,
  16. input i_en,
  17. output reg[31:0] o_cnt, //输出计数值
  18. output o_state
  19. );
  20. reg [1:0] r_pluse;
  21. reg [1:0] r_en;
  22. wire w_pluse_pos;
  23. wire w_en_neg;
  24. reg[31:0] r_cnt;
  25. //产生一个pluse 上升沿脉冲时钟
  26. always @(posedge clk) begin
  27. if(!rest_n) r_pluse <='b00;
  28. else r_pluse <= {r_pluse[0],pulse};
  29. end
  30. assign w_pluse_pos = r_pluse[0] & ~r_pluse[1];
  31. //产生一个i_en 下降沿脉冲时钟
  32. //en 下降沿时 o_state =1
  33. always @(posedge clk) begin
  34. if(!rest_n) r_en <='b00;
  35. else r_en <= {r_en[0],i_en};
  36. end
  37. assign o_state = r_en[1] & ~r_en[0];
  38. //EN = 1时候计数
  39. always @(posedge clk) begin
  40. if(!rest_n) r_cnt <= 'b0;
  41. else if(i_en)
  42. if(w_pluse_pos)r_cnt <= r_cnt + 1'b1;
  43. else ;
  44. else r_cnt <= 'b0;
  45. end
  46. //输出o_cnt
  47. always @(posedge clk) begin
  48. if(!rest_n) o_cnt <= 'b0;
  49. else if(!i_en && r_cnt) begin
  50. o_cnt <= r_cnt;
  51. $display("r_cnt=%d\n",r_cnt);//显示
  52. end
  53. else o_cnt <= 'b0;
  54. end
  55. endmodule

testbench_top

  1. `timescale 1ns/1ps
  2. module testbench_top();
  3. //参数定义
  4. `define CLK_PERIORD 10 //时钟周期设置为10ns(100MHz)
  5. //接口申明
  6. reg clk;
  7. reg pulse;
  8. reg rest_n;
  9. reg i_en;
  10. wire [31:0] o_cnt;
  11. wire o_state;
  12. vlg_design uut_vlg_design(
  13. .clk(clk),
  14. .pulse(pulse),
  15. .rest_n(rest_n),
  16. .i_en(i_en),
  17. .o_cnt(o_cnt),
  18. .o_state(o_state)
  19. );
  20. //时钟和复位初始化、复位产生
  21. initial begin
  22. clk <= 0;
  23. rest_n <= 0;
  24. #10;
  25. rest_n <= 1;
  26. clk <= 1;
  27. pulse <= 1'b0;
  28. i_en <= 0;
  29. end
  30. //时钟产生
  31. always #(`CLK_PERIORD/2) clk = ~clk;
  32. integer i;
  33. //测试激励产生
  34. initial begin
  35. @(posedge rest_n); //等待复位完成
  36. @(posedge clk);
  37. i_en <= 1;
  38. @(posedge clk);
  39. for (i = 0; i < 16; i = i+1) begin
  40. pulse = ~pulse;
  41. repeat(3)@(posedge clk);
  42. end
  43. i_en <= 0;
  44. @(posedge clk);
  45. i_en <= 0;
  46. for (i = 0; i < 16; i = i+1) begin
  47. pulse = ~pulse;
  48. repeat(3)@(posedge clk);
  49. end
  50. i_en <= 0;
  51. @(posedge clk);
  52. i_en <= 1;
  53. @(posedge clk);
  54. for (i = 0; i < 6; i = i+1) begin
  55. pulse = ~pulse;
  56. repeat(5)@(posedge clk);
  57. end
  58. i_en <= 0;
  59. @(posedge clk);
  60. #2_000_000;
  61. $stop;
  62. end
  63. endmodule

仿真结果

难点分析

1,按模块划分,

//产生一个pluse 上升沿脉冲时钟

//产生一个i_en 下降沿脉冲时钟 //en 下降沿时 o_state =1

//EN = 1时候计数

//输出o_cnt

各模块的赋值部分,相互独立,各自处理各自判断,防止时序偏差

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/529109
推荐阅读
相关标签
  

闽ICP备14008679号