在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
123
返回列表 发新帖
楼主: bh3715

[求助] 用Verilog如何实现一个边沿启动计数器模块

[复制链接]
发表于 2015-5-6 17:04:27 | 显示全部楼层


这里的state有啥用?
发表于 2015-11-30 19:55:13 | 显示全部楼层
学习学习
发表于 2018-6-15 09:53:52 | 显示全部楼层
学习了
发表于 2018-6-22 15:56:03 | 显示全部楼层
检查en的边缘。边缘检查电路
发表于 2018-6-26 11:47:02 | 显示全部楼层
从你的信号描述看,你的start的高脉冲应该是大于计数器的工作时钟的时钟周期的,否则,需要传递一个Start的随路时钟

补充内部代码如下:
1. 需要对Start信号进行跨时钟域的同步处理,同步后进行采样
2. 产生计数器计数使能,在同步后的Start上升沿拉高,计数到同步值后拉低
3. 计数器在计数使能进行计数,并在Start上沿恢复到初始值

推荐Verilog 2001的Coding Style
module counter(
      input                     clk             ,
      input                     rst_n         ,
      input                     start          ,    // Async
      input        [9:0]      set_count  ,    // Maximum Value of counter
      output reg              alarm             // Counter over flag
       );
      
//   Signal Declarations
      reg                start_sync0;
      reg                start_sync1;
      reg                start_sync2;
      reg                start_sync3;
      reg                start_pos;

      reg                cnt_en;
      reg  [9:0]       cnt;


      always @(posedge clk or negedge rst_n) begin
             if (rst_n == 1'b0) begin
                    start_sync0 <= 1'b0;
                    start_sync1 <= 1'b0;
                    start_sync2 <= 1'b0;
                    start_sync3 <= 1'b0;
             end
             else begin
                    start_sync0 <= start;
                    start_sync1 <= start_sync0;
                    start_sync2 <= start_sync1;
                    start_sync3 <= start_sync2;
             end
      end

      always@(*) begin
             if ((start_sync2 == 1'b1) && (start_sync3 == 1'b0)) begin // posedge of start
                   start_pos = 1'b1;
             end
             else begin
                   start_pos = 1'b1;
             end
      end

// Generation of couner enable
      always @(posedge clk or negedge rst_n) begin
             if (rst_n == 1'b0) begin
                    cnt_en <= 1'b0;
             end
             else if (start_pos == 1'b1) begin
                   cnt_en <= 1'b1;
             end
             else if ( cnt == (set_count - 1'b1)) begin
                    cnt_en <= 1'b0;
             end
     end

     always @(posedge clk or negedge rst_n) begin
             if (rst_n == 1'b0) begin
                    cnt <= {10{1'b0}};
             end
             else if ((start_pos == 1'b1) || (cnt == (set_count - 1'b1))) begin
                    cnt <= {10{1'b0}};
             end
             else if (cnt_en == 1'b1) begin
                   cnt <= cnt + 1'b1;
             end
       end

// output alarm generation , 1 cycle later than counter's maximum

     always @(posedge clk or negedge rst_n) begin
             if (rst_n == 1'b0) begin
                    alarm <= 1'b0;
             end
             else if ((cnt == (set_count - 1'b1))) begin
                    alarm <= 1'b1;
             end
             else begin
                    alarm <= 1'b0;
             end
      end
endmodule
发表于 2018-6-26 11:47:49 | 显示全部楼层
从你的信号描述看,你的start的高脉冲应该是大于计数器的工作时钟的时钟周期的,否则,需要传递一个Start的随路时钟

补充内部代码如下:
1. 需要对Start信号进行跨时钟域的同步处理,同步后进行采样
2. 产生计数器计数使能,在同步后的Start上升沿拉高,计数到同步值后拉低
3. 计数器在计数使能进行计数,并在Start上沿恢复到初始值

推荐Verilog 2001的Coding Style
module counter(
      input                     clk             ,
      input                     rst_n         ,
      input                     start          ,    // Async
      input        [9:0]      set_count  ,    // Maximum Value of counter
      output reg              alarm             // Counter over flag
       );
      
//   Signal Declarations
      reg                start_sync0;
      reg                start_sync1;
      reg                start_sync2;
      reg                start_sync3;
      reg                start_pos;

      reg                cnt_en;
      reg  [9:0]       cnt;


      always @(posedge clk or negedge rst_n) begin
             if (rst_n == 1'b0) begin
                    start_sync0 <= 1'b0;
                    start_sync1 <= 1'b0;
                    start_sync2 <= 1'b0;
                    start_sync3 <= 1'b0;
             end
             else begin
                    start_sync0 <= start;
                    start_sync1 <= start_sync0;
                    start_sync2 <= start_sync1;
                    start_sync3 <= start_sync2;
             end
      end

      always@(*) begin
             if ((start_sync2 == 1'b1) && (start_sync3 == 1'b0)) begin // posedge of start
                   start_pos = 1'b1;
             end
             else begin
                   start_pos = 1'b1;
             end
      end

// Generation of couner enable
      always @(posedge clk or negedge rst_n) begin
             if (rst_n == 1'b0) begin
                    cnt_en <= 1'b0;
             end
             else if (start_pos == 1'b1) begin
                   cnt_en <= 1'b1;
             end
             else if ( cnt == (set_count - 1'b1)) begin
                    cnt_en <= 1'b0;
             end
     end

     always @(posedge clk or negedge rst_n) begin
             if (rst_n == 1'b0) begin
                    cnt <= {10{1'b0}};
             end
             else if ((start_pos == 1'b1) || (cnt == (set_count - 1'b1))) begin
                    cnt <= {10{1'b0}};
             end
             else if (cnt_en == 1'b1) begin
                   cnt <= cnt + 1'b1;
             end
       end

// output alarm generation , 1 cycle later than counter's maximum

     always @(posedge clk or negedge rst_n) begin
             if (rst_n == 1'b0) begin
                    alarm <= 1'b0;
             end
             else if ((cnt == (set_count - 1'b1))) begin
                    alarm <= 1'b1;
             end
             else begin
                    alarm <= 1'b0;
             end
      end
endmodule
发表于 2018-6-26 11:48:31 | 显示全部楼层
从你的信号描述看,你的start的高脉冲应该是大于计数器的工作时钟的时钟周期的,否则,需要传递一个Start的随路时钟

补充内部代码如下:
1. 需要对Start信号进行跨时钟域的同步处理,同步后进行采样
2. 产生计数器计数使能,在同步后的Start上升沿拉高,计数到同步值后拉低
3. 计数器在计数使能进行计数,并在Start上沿恢复到初始值

推荐Verilog 2001的Coding Style
module counter(
      input                     clk             ,
      input                     rst_n         ,
      input                     start          ,    // Async
      input        [9:0]      set_count  ,    // Maximum Value of counter
      output reg              alarm             // Counter over flag
       );
      
//   Signal Declarations
      reg                start_sync0;
      reg                start_sync1;
      reg                start_sync2;
      reg                start_sync3;
      reg                start_pos;

      reg                cnt_en;
      reg  [9:0]       cnt;


      always @(posedge clk or negedge rst_n) begin
             if (rst_n == 1'b0) begin
                    start_sync0 <= 1'b0;
                    start_sync1 <= 1'b0;
                    start_sync2 <= 1'b0;
                    start_sync3 <= 1'b0;
             end
             else begin
                    start_sync0 <= start;
                    start_sync1 <= start_sync0;
                    start_sync2 <= start_sync1;
                    start_sync3 <= start_sync2;
             end
      end

      always@(*) begin
             if ((start_sync2 == 1'b1) && (start_sync3 == 1'b0)) begin // posedge of start
                   start_pos = 1'b1;
             end
             else begin
                   start_pos = 1'b1;
             end
      end

// Generation of couner enable
      always @(posedge clk or negedge rst_n) begin
             if (rst_n == 1'b0) begin
                    cnt_en <= 1'b0;
             end
             else if (start_pos == 1'b1) begin
                   cnt_en <= 1'b1;
             end
             else if ( cnt == (set_count - 1'b1)) begin
                    cnt_en <= 1'b0;
             end
     end

     always @(posedge clk or negedge rst_n) begin
             if (rst_n == 1'b0) begin
                    cnt <= {10{1'b0}};
             end
             else if ((start_pos == 1'b1) || (cnt == (set_count - 1'b1))) begin
                    cnt <= {10{1'b0}};
             end
             else if (cnt_en == 1'b1) begin
                   cnt <= cnt + 1'b1;
             end
       end

// output alarm generation , 1 cycle later than counter's maximum

     always @(posedge clk or negedge rst_n) begin
             if (rst_n == 1'b0) begin
                    alarm <= 1'b0;
             end
             else if ((cnt == (set_count - 1'b1))) begin
                    alarm <= 1'b1;
             end
             else begin
                    alarm <= 1'b0;
             end
      end
endmodule
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条


小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-12-23 06:50 , Processed in 0.018474 second(s), 6 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表