计数器阶段9 - 练习一

2022/3/19 23:30:59

本文主要是介绍计数器阶段9 - 练习一,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

题目:

 

 

 

把时序画的具体点:

 

 

 设计关键点:

(1)、需用到两个计数器,计数器cnt0 用于产生1M的soic时钟计数,系统100M,产生1M,需计数100次; 计数器cnt1用于对bit位数进行计数,需发送12bit。

(2)、增加flag_add,用于标出需要计数的阶段。

(3)、 soic 在cnt1=0和cnt1=11期间,需保持为高,不能拉低,用于产生起始位和停止位。

(4)、soid 是在soic低电平中间改变,soic高电平期间保持不变。

代码:

  1 module sccb(
  2                 clk,
  3                 rst_n,
  4                 en,
  5                 
  6                 soic,
  7                 soid
  8 );
  9 parameter     SOIC_1M = 100;
 10 
 11 input            clk;
 12 input            rst_n;
 13 input            en;
 14     
 15 output             soic;
 16 output            soid;
 17     
 18 wire             add_cnt0;
 19 wire             end_cnt0;
 20 wire             add_cnt1;
 21 wire             end_cnt1;
 22 wire [12-1:0]    data;
 23 
 24 reg             flag_add;
 25 reg             soic;
 26 reg             soid;
 27 
 28 reg    [8-1:0]        cnt0;
 29 reg    [4-1:0]        cnt1;
 30 
 31 assign data = {1'b0,8'h5a,1'b1,1'b0,1'b1};  //将数据拼接好,起始位、8bit数据、ack位、停止位、还有最后将soid拉高
 32 
 33 always @(posedge clk or negedge rst_n)begin
 34     if(!rst_n)begin
 35         cnt0 <= 0;
 36     end
 37     else if(add_cnt0)begin
 38         if(end_cnt0)begin
 39             cnt0 <= 0;
 40         end
 41         else begin
 42             cnt0 <= cnt0 + 1;
 43         end
 44     end
 45 end
 46 
 47 assign add_cnt0 = flag_add;
 48 assign end_cnt0 = add_cnt0 && cnt0 == SOIC_1M - 1;
 49 
 50 always @(posedge clk or negedge rst_n)begin
 51     if(!rst_n)begin
 52         cnt1 <= 0;
 53     end
 54     else if(add_cnt1)begin
 55         if(end_cnt1)begin
 56             cnt1 <= 0;
 57         end
 58         else begin
 59             cnt1 <= cnt1 + 1;
 60         end
 61     end
 62 end
 63 
 64 assign add_cnt1 = end_cnt0;
 65 assign end_cnt1 = add_cnt1 && cnt1 == 12 - 1;
 66 
 67 always @(posedge clk or negedge rst_n)begin
 68     if(!rst_n) begin
 69         flag_add <= 0;
 70     end
 71     else if(en)begin
 72         flag_add <= 1;
 73     end
 74     else if(end_cnt1)begin
 75         flag_add <= 0;
 76     end
 77 end
 78 
 79 //soic 在cnt1=0和cnt1=11期间,需保持为高,不能拉低,产生起始位和停止位
 80 always @(posedge clk or negedge rst_n)begin
 81     if(!rst_n) begin
 82         soic <= 1;
 83     end
 84     else if(add_cnt0 && cnt0 == SOIC_1M/2 &&  cnt1 != 0 && cnt1 != 11)begin
 85         soic <= 0;
 86     end
 87     else if(end_cnt0)begin
 88         soic <= 1;
 89     end
 90 end
 91 
 92 //soid 是在soic低电平中间改变,soic高电平期间保持不变
 93 always @(posedge clk or negedge rst_n)begin
 94     if(!rst_n)begin
 95         soid <= 1;
 96     end
 97     else if(add_cnt0 && cnt0 == 75-1)begin // && cnt1 >= 0 && cnt1 < 12
 98         soid <= data[11-cnt1];
 99     end
100 end
101 
102 endmodule

仿真代码:

 1 module sccb_sim;
 2 
 3 reg     clk;
 4 reg     rst_n;
 5 reg     en;
 6 
 7 wire    soic;
 8 wire    soid;
 9 
10 parameter CLK_CYCLE = 10;  //100M,时钟周期是10ns 
11 
12 initial begin
13         clk = 0;
14         forever #(CLK_CYCLE/2) clk = ~clk;
15 end
16 
17 initial begin
18         #1;
19         rst_n = 0;
20         #(CLK_CYCLE*10);
21         rst_n = 1;
22 end
23 
24 initial  begin
25         #1;
26         en = 0;
27         #(CLK_CYCLE*15);
28         repeat(10)begin
29             en = 1;
30             #(CLK_CYCLE);
31             en = 0;
32             #(CLK_CYCLE*$urandom_range(1300,1500));
33         end
34 end
35 
36 sccb    sccb_inist(
37                         .clk(clk),
38                         .rst_n(rst_n),
39                         .en(en),
40                         
41                         .soic(soic),
42                         .soid(soid)
43                 );
44 
45 
46 endmodule 

仿真波形:

 



这篇关于计数器阶段9 - 练习一的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程