计数器阶段三 - 练习五


按照协议约定,输入din_vld出现低电平脉冲时必定超过24个时钟周期,当出现低电平脉冲时,将第16~23个时钟对应din的8个值分别赋给dout[0]~dout[7]。

 1 module test_cnt(
 2                     clk        ,
 3                     rst_n    ,
 4                     din_vld    ,
 5                     din        ,
 6                     dout    ,
 7                     dout_vld,
 8 );
 9 
10 input             clk    ;
11 input             rst_n;
12 input            din_vld;
13 input            din;
14 output     [7:0]    dout;
15 output            dout_vld;
16 
17 wire             add_cnt0;
18 wire             end_cnt0;
19 
20 reg             dout_vld;
21 reg [7:0]        dout    ;
22 reg [6-1:0]     cnt0    ;
23 reg             flag_add;
24 always @(posedge clk or negedge rst_n)begin
25     if(!rst_n)begin
26         cnt0 <= 0;
27     end
28     else if(add_cnt0)begin
29         if(end_cnt0)begin
30             cnt0 <= 0;
31         end
32         else begin
33             cnt0 <= cnt0 + 1;
34         end
35     end
36 end
37 
38 assign add_cnt0 = din_vld == 0 && flag_add == 0;  //将din_vld == 0作为计数器加1条件,同时增加一个flag_add信号区分
39 assign end_cnt0 = add_cnt0 && cnt0 == 24 - 1;
40 
41 always @(posedge clk or negedge rst_n)begin
42     if(!rst_n)begin
43         flag_add <= 0;
44     end
45     else if(end_cnt0)begin //在计数器到24个时钟时,将flag_add 置1
46         flag_add <= 1;
47     end
48     else if(din_vld == 1)begin//将flag_add 置0
49         flag_add <= 0;
50     end
51 end
52 
53 reg [8-1:0] dout_temp;
54 always @(posedge clk or negedge rst_n)begin
55     if(!rst_n)begin
56         dout_temp <= 0;
57     end
58     else if(add_cnt0 && cnt0 >= 16 && cnt0 < 24)begin //在cnt0 = 16~23期间将din赋给dout
59         dout_temp[cnt0 - 16] <= din;
60     end
61 end
62 
63 always @(posedge clk or negedge rst_n)begin
64     if(!rst_n)begin
65         dout <= 0;
66     end
67     else if(end_cnt0)begin
68         dout <= dout_temp; //收完一个完整的8bit数据锁存
69     end
70 end
71 
72 always @(posedge clk or negedge rst_n)begin
73     if(!rst_n)begin
74         dout_vld <= 0;
75     end
76     else if(end_cnt0)begin //产生一个有效信号,且只保留一个时钟周期
77         dout_vld <= 1;
78     end
79     else begin
80         dout_vld <= 0;
81     end
82 end
83 
84 
85 endmodule 

测试文件:

 1 module top_sim;
 2 
 3 reg clk;
 4 reg rst_n;
 5 reg din_vld;
 6 reg din;
 7 
 8 wire dout_vld;
 9 wire [7:0] dout;
10 
11 `define CYCLE 20
12 
13 initial begin
14         clk = 0;
15         forever 
16         #(`CYCLE/2) clk = ~clk;
17 end
18 
19 initial begin
20         #1;
21         rst_n = 0;
22         #(`CYCLE*5);
23         rst_n = 1;
24 end
25 
26 initial begin
27     din_vld = 1;
28     #(`CYCLE*6);
29     #1;
30     din_vld = 1;
31     repeat(100)begin
32     #(`CYCLE*3);
33     din_vld = $urandom_range(0,1); //$urandom_range(min,max)生成min到max范围内的随机无符号整数
34     //din = $signed($urandom_range(1,2))-1;
35     #(`CYCLE*$urandom_range(24,30)); //产生不低于24个时钟周期的延时
36     end
37 end
38 
39 
40 initial begin
41     din = 0;
42     #(`CYCLE*6);
43     #1;
44     din = 0;
45     repeat(100)begin
46     #(`CYCLE*1);
47     din = $urandom_range(0,1); //$urandom_range(min,max)生成min到max范围内的随机无符号整数
48     //din = $signed($urandom_range(1,2))-1;
49     #(`CYCLE*$urandom_range(1,8));
50     end
51 end
52 
53 test_cnt    u1(
54                     .clk        (clk        ),
55                     .rst_n        (rst_n        ),
56                     .din        (din        ),
57                     .din_vld    (din_vld    ),
58                     .dout        (dout        ),
59                     .dout_vld    (dout_vld    )
60 );
61 
62 endmodule

仿真波形:

相关