计数器阶段三 - 练习五
按照协议约定,输入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
仿真波形: