题解 | #加减计数器#
加减计数器
https://www.nowcoder.com/practice/9d50eb2addaf4a37b7cd5a5ee7b297f6
这个时序图有问题把??
能通过的答案也很好理解。但是跟题目的时序图对应不上啊??有大佬给解惑下不。。
按照能够通过测试的程序来进行测试。编写testbench模拟题目的时序。
时序图问题:
问题一:按照题目的时序,在这个上升沿的位置,rst_n已经是高电平。但是此时mode还是未知状态,这样会导致中间变量num也会是未知状态,如下图所示,而不应该是题目中的样子(是我哪里推理错了吗?)
问题二:
就像其中一个讨论种说的“参考的时序图是不是有问题,开始的时候number没有延迟而是直接开始加一,到mode变为0的时候又需要延时再减一”???
问题三:
其实就是问题二的问题。和VL51 可置位计数器的问题一样。
VL51 可置位计数器问题:https://blog.nowcoder.net/n/836d04d849dd441c84d3b25e6e0b7c14?f=comment
所以真正的符合时序图的话不应该是下面的程序:
`timescale 1ns/1ns module count_module( input clk, input rst_n, input set, input [3:0] set_num, output reg [3:0]number, output reg zero ); reg [3:0] num_reg; always@(posedge clk or negedge rst_n)begin if(!rst_n)begin num_reg <= 4'b0; end else num_reg <= set ? set_num:number+1; end always@(posedge clk or negedge rst_n)begin if(!rst_n)begin zero <= 0; end else zero <= num_reg==4'b0000; end always@(posedge clk or negedge rst_n)begin if(!rst_n)begin number <= 0; end else number <= num_reg; end endmodule
testbench:
`timescale 1ns/1ns module testbench(); reg clk,rst_n; reg mode; wire [3:0]number; wire zero; initial begin $dumpfile("out.vcd"); $dumpvars(0,testbench); //clk = 0; rst_n = 0; end count_module dut( .clk(clk), .rst_n(rst_n), .mode(mode), .number(number), .zero(zero) ); initial begin //#5; clk=1; repeat(500) #5 clk =~clk; end initial begin #10; rst_n =1; end initial begin #20;mode = 1; #150; mode = 0; #100; $stop; end endmodule
通过的程序:
`timescale 1ns/1ns module count_module( input clk, input rst_n, input mode, output reg [3:0]number, output reg zero ); reg [3:0] num; always@(posedge clk or negedge rst_n) if(~rst_n) zero <= 0; else zero <= num==0; always@(posedge clk or negedge rst_n)begin if(~rst_n) num <= 0; else if((num==9)&&(mode==1)) num <= 0; else if ((num==0)&&(mode==0)) num <= 9; else num <= mode? num+1 : num - 1; end always@(posedge clk or negedge rst_n) if(~rst_n) number <= 0; else number <= num; endmodule