1.笔者最近在仿真验证Verilog模块时遇到了有关start激励的一个困惑。先说说这个困惑吧,请看下面一个简单的counter模块:
`timescale 1ns / 1ps module counter( clk,rst_n, counter_start, count,count_done ); input clk,rst_n; input counter_start; output reg [2:0] count; output reg count_done; parameter St0=3‘b001, St1=3‘b010, St2=3‘b100, Stx=3‘bxxx; reg [2:0] current_state; reg [2:0] next_state; always @(posedge clk or negedge rst_n) begin if(!rst_n) current_state<=St0; else current_state<=next_state; end always @(counter_start or current_state or count) begin next_state=Stx; case(current_state) St0: begin if(counter_start) next_state=St1; else next_state=St0; end St1: begin if(count==3‘d7) next_state=St2; else next_state=St1; end St2: begin next_state=St0; end default: next_state=St0; endcase end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin count_done<=1‘b0; count<=3‘b0; end else case(next_state) St0: begin count_done<=1‘b0; count<=3‘b0; end St1: begin count<=count+1‘b1; end St2: begin count_done<=1‘b1; end default: begin count_done<=1‘b0; count<=3‘b0; end endcase end endmodule
这是用三段式状态机编写的8位计数器,然后我在写tb给counter_start信号时采用了两种方式:a、在clk上升沿时给;b、在clk上升沿后一瞬间给。那么这两种写法会有什么不同呢?请看如下波形:
a、在clk上升沿时给
b、在clk上升沿后一瞬间给
想必看官也早已猜到,这两种给法产生的结果完全是不用的:a中counter_start跳边到1时,count马上开始了计数;而b中counter_start跳边到1时,count是在下一个clk上升沿才开始计数的。千万别小看这么点不同,数字电路中的节拍可是至关重要的!那么问题来了,到底哪种给法会更加科学合理呢?
2.为了说明这个问题,我又给这个计数器添加了一个控制模块counter_control,让它产生counter_start信号:
1 `timescale 1ns / 1ps 2 3 module counter_control( 4 clk,rst_n, 5 start,counter_start 6 ); 7 8 input clk,rst_n; 9 input start; 10 output reg counter_start; 11 12 always @(posedge clk or negedge rst_n) 13 if(!rst_n) counter_start<=1‘b0; 14 else if(start) counter_start<=1‘b1; 15 else counter_start<=1‘b0; 16 17 endmodule
控制模块相当简单,就是当外围start信号到来时,让counter_start有效。
下面将两个模块组成顶层:
1 `timescale 1ns / 1ps 2 3 module counter_top( 4 clk,rst_n, 5 start,counter_start,count,count_done 6 ); 7 input clk,rst_n; 8 input start; 9 output [2:0] count; 10 output count_done,counter_start; 11 12 wire counter_start; 13 counter_control U1( 14 .clk(clk), 15 .rst_n(rst_n), 16 .start(start), 17 .counter_start(counter_start) 18 ); 19 20 counter U2( 21 .clk(clk), 22 .rst_n(rst_n), 23 .counter_start(counter_start), 24 .count(count), 25 .count_done(count_done) 26 ); 27 28 29 endmodule
start信号由于是外围用户给的,因此tb中它的使能应该是任意的,下面请看该顶层模块的仿真波形: