七夜浮生

【原创】从零开始学习FPGA-----复杂计数器练习

1
阅读(3458)

【原创】从零开始学习FPGA-----复杂计数器练习

1. 复杂计数器练习

1) 模块时钟是100M。dout的依次如下变化:

a 第一阶段时间是20us。此时如果din_vld出现超过50ns的高电平脉冲,则dout输出10ns的高电平;

b 第二阶段时间是40us。此时如果din_vld出现超过100ns的高电平脉冲,则dout输出10ns的高电平;

c 第三阶段时间是100us。此时如果din_vld出现超过200ns的高电平脉冲,则dout输出10ns的高电平;

d 第四阶段时间是200us。此时如果din_vld出现超过40ns的高电平脉冲,则dout输出10ns的高电平;

e 循环a~d。

分析如下:

这道练习题需要3个计数器,计数器0,计din_vld阶段50ns 100ns 200ns 40ns的产生,计数器1计20us 40us 100us 200us,计数器2计a,b,c,d这4个阶段。

不多说,代码如下,经过这几天的训练,在代码规范性上有了很大提升,值得鼓励。。

`timescale 1ns/1ns

module module_name(

    clk    ,

    rst_n  ,

    din_vld,

    //其他信号,举例dout

    dout

    );

    //参数定义

    parameter      DATA_W =        1;

    //输入信号定义

    input               clk    ;//10ns

    input               rst_n  ;

    input               din_vld;

    //输出信号定义

    output[DATA_W-1:0]  dout   ;

    //输出信号reg定义

    reg   [DATA_W-1:0]  dout   ;

    //参数定义

    parameter       T_20US = 15'd2_000;

    parameter       T_40US = 15'd4_000;

    parameter       T_100US = 15'd10_000;   

    parameter       T_200US = 15'd20_000;  

    parameter       T_50NS =  5'd5;  

    parameter       T_100NS =  5'd10;

    parameter       T_200NS =  5'd20;

    parameter       T_40NS =  5'd4;

   reg[5:0]                cnt0;//计50ns 100ns 200ns 40ns

   reg[14:0]               cnt1;//计20us 40us 100us 200us

   reg[3:0]                cnt2;//计 a b c d

   //各阶段中间变量

   reg[5:0]            t_ns   ;

   reg[14:0]           t_us   ;

    //计数器0

   assign add_cnt0 = din_vld ;

   assign end_cnt0 = ~din_vld ;

   always  @(posedge clk or negedge rst_n)begin

       if(rst_n==1'b0)begin

           cnt0 <= 0;

       end

       else if(add_cnt0)begin

           if(end_cnt0)begin

               cnt0 <= 0;

           end

           else if(cnt0 == t_ns)begin

               cnt0 <= cnt0;

           end

           else begin

               cnt0 <= cnt0 + 1;

           end

       end

   end

   //计数器1

   assign end_cnt1 = (cnt2 == t_us-1) && add_cnt1;

   always  @(posedge clk or negedge rst_n)begin

       if(rst_n==1'b0)begin

           cnt1 <= 0;

       end

       else if(end_cnt1)

           cnt1 <= 0;

       else

           cnt1 <= cnt1 +1;

   end

   //计数器2

   assign add_cnt2 = end_cnt1;

   assign end_cnt2 = (cnt2 == 4-1) && add_cnt2;

    always@(posedge clk or negedge rst_n)begin

        if(rst_n==1'b0)begin

            cnt2 <= 0;

        end

        else if(add_cnt2)begin

            if(end_cnt2)

                cnt2 <= 0;

            else

                cnt2 <= cnt2 +1;

        end

    end

    //中间变量

       always  @(*)begin

        if(cnt2==0)begin

            t_ns = T_50NS;

            t_us = T_20US;

        end

        else if(cnt2 == 1)begin

            t_ns = T_100NS;

            t_us = T_40US;

        end

        else if(cnt2 == 2)begin

            t_ns = T_200NS;

            t_us = T_100US;

        end

        else begin

            t_ns = T_40NS;

            t_us = T_200US;

        end

    end

    //输出dout

    always  @(posedge clk or negedge rst_n)begin

        if(rst_n==1'b0)begin

            dout <= 1'b0;

        end

        else if(cnt0 == t_ns-1 && din_vld) begin

            dout <= 1'b1;

        end

        else begin

            dout <= dout;

        end

    end

endmodule

计数器练习到这已经练的差不多了,接下来要进行串口,SPI,VGA,FIFO等模块的学习,这些模块计数器是基础,基础一定要打好,对以后的学习会起到事半功倍的效果。

今天就到这里,睡觉了,晚安,同学们。