阶段四练习3
模块时钟是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 的高电平;
然后循环a~d。
时序:

设计关键点:
(1)、确认计数器个数:
>> 要对din_vld进行数数,需要一个 cnt0,每个阶段数的数不一样,引入变量x;
>>每个阶段的时间不一样,需要一个 cnt1 对其进行计数,引入变量y;
>>有四个阶段,需要一个 cnt2 对阶段进行数数,次数为4;
通过组合逻辑,利用阶段计数器cnt2区分分别对变量x , y 进行赋值。
(2)、当din_vld连续高电平个数不足数量时就被拉低了,此时需要将cnt0计数器清零,方便下次重新数数。
(3)、当din_vld连续高电平个数超过指定数量时,cnt0不需在进行数数,所以计数器判断条件得附加上flag_add,flag_add用于区分计数满之后就不用在计数标志。
(4)、dout输出高电平只需保持一个时钟周期。
代码:
1 module test_cnt( 2 clk , 3 rst_n , 4 din_vld , 5 6 dout 7 ); 8 9 input clk ; 10 input rst_n; 11 input din_vld; 12 13 14 output dout; 15 16 wire add_cnt0; 17 wire end_cnt0; 18 wire add_cnt1; 19 wire end_cnt1; 20 wire add_cnt2; 21 wire end_cnt2; 22 23 reg flag_add; 24 reg dout; 25 reg [5-1 :0] cnt0; 26 reg [16-1:0] cnt1; 27 reg [3-1 :0] cnt2; 28 reg [5-1 :0] x; 29 reg [16-1:0] y; 30 31 //对din_vld 高电平进行数数 32 always @(posedge clk or negedge rst_n)begin 33 if(!rst_n)begin 34 cnt0 <= 0; 35 end 36 else if(add_cnt0)begin 37 if(end_cnt0)begin 38 cnt0 <= 0; 39 end 40 else begin 41 cnt0 <= cnt0 + 1; 42 end 43 end 44 else begin //如果中间din_vld数到不够数时就拉低了,计数器一定要清零,方便下次开始数数 45 cnt0 <= 0; 46 end 47 end 48 49 assign add_cnt0 = din_vld == 1 && flag_add == 0; //附加上flag_add条件,数到数量够时,不在对din_vld进行数数 50 assign end_cnt0 = add_cnt0 && cnt0 == x - 1; 51 52 //一个阶段的时间 53 always @(posedge clk or negedge rst_n)begin 54 if(!rst_n)begin 55 cnt1 <= 0; 56 end 57 else if(add_cnt1)begin 58 if(end_cnt1)begin 59 cnt1 <= 0; 60 end 61 else begin 62 cnt1 <= cnt1 + 1; 63 end 64 end 65 end 66 67 assign add_cnt1 = 1; //注意开始条件不在是end_cnt0 68 assign end_cnt1 = add_cnt1 && cnt1 == y - 1; 69 70 //对第1阶段 、第2阶段 、第3阶段 、第4阶段,4个阶段进行数数 71 always @(posedge clk or negedge rst_n)begin 72 if(!rst_n)begin 73 cnt2 <= 0; 74 end 75 else if(add_cnt2)begin 76 if(end_cnt2)begin 77 cnt2 <= 0; 78 end 79 else begin 80 cnt2 <= cnt2 + 1; 81 end 82 end 83 end 84 85 assign add_cnt2 = end_cnt1; 86 assign end_cnt2 = add_cnt2 && cnt2 == 4 - 1; 87 88 always @(posedge clk or negedge rst_n)begin 89 if(!rst_n)begin 90 flag_add <= 0; 91 end 92 else if(end_cnt0)begin //数到够数量时就停止计数 93 flag_add <= 1; 94 end 95 else if(din_vld == 0)begin //等到din_vld变低时,将flag_add变0,便于下次开始计数 96 flag_add <= 0; 97 end 98 end 99 100 always @(posedge clk or negedge rst_n)begin 101 if(!rst_n)begin 102 dout <= 0; 103 end 104 else if(end_cnt0)begin //只保持一个时钟周期 105 dout <= 1; 106 end 107 else begin 108 dout <= 0; 109 end 110 end 111 112 //四种不同阶段下,对x ,y变量进行赋值 113 always @(*)begin 114 if(cnt2 == 0)begin 115 x = 5; 116 y = 2000; 117 end 118 else if(cnt2 == 1)begin 119 x = 10; 120 y = 4000; 121 end 122 else if(cnt2 == 2)begin 123 x = 20; 124 y = 10000; 125 end 126 else begin 127 x = 4; 128 y = 20000; 129 end 130 end 131 132 endmodule
测试文件:关键点利用 //$urandom_range(min,max)生成min到max范围内的随机无符号整数
1 module top_sim; 2 3 reg clk; 4 reg rst_n; 5 reg din_vld; 6 7 wire dout; 8 9 `define CYCLE 10 //100MHz ,一个周期10ns 10 11 initial begin 12 clk = 0; 13 forever 14 #(`CYCLE/2) clk = ~clk; 15 end 16 17 initial begin 18 rst_n = 0; 19 #1; 20 #(`CYCLE*5); 21 rst_n = 1; 22 end 23 24 25 //$urandom_range(min,max)生成min到max范围内的随机无符号整数 26 initial begin 27 din_vld = 0; 28 #1; 29 #(`CYCLE*10); 30 31 //第一阶段 32 repeat(20)begin 33 din_vld = 1; 34 #(`CYCLE*$urandom_range(7,8)); 35 din_vld = 0; 36 #(`CYCLE*20); 37 din_vld = 1; 38 #(`CYCLE*$urandom_range(2,6)); 39 40 repeat(20)begin 41 din_vld = 0; 42 #(`CYCLE*10); 43 end 44 end 45 46 //第二阶段 47 repeat(20)begin 48 din_vld = 1; 49 #(`CYCLE*$urandom_range(12,15)); 50 din_vld = 0; 51 #(`CYCLE*20); 52 din_vld = 1; 53 #(`CYCLE*$urandom_range(10,12)); 54 55 repeat(20)begin 56 din_vld = 0; 57 #(`CYCLE*10); 58 end 59 end 60 61 //第三阶段 62 repeat(100)begin 63 din_vld = 1; 64 #(`CYCLE*$urandom_range(22,15)); 65 din_vld = 0; 66 #(`CYCLE*20); 67 din_vld = 1; 68 #(`CYCLE*$urandom_range(18,21)); 69 70 repeat(100)begin 71 din_vld = 0; 72 #(`CYCLE*10); 73 end 74 end 75 76 //第四阶段 77 repeat(100)begin 78 din_vld = 1; 79 #(`CYCLE*$urandom_range(5,7)); 80 din_vld = 0; 81 #(`CYCLE*20); 82 din_vld = 1; 83 #(`CYCLE*$urandom_range(3,5)); 84 85 repeat(100)begin 86 din_vld = 0; 87 #(`CYCLE*10); 88 end 89 end 90 91 end 92 93 test_cnt u1_inist( 94 .clk(clk), 95 .rst_n(rst_n), 96 .din_vld(din_vld), 97 98 .dout(dout) 99 ); 100 101 102 endmodule
仿真波形:

查看具体细节:


浙公网安备 33010602011771号