最近看了看 FSM based Digital Design using
verilog hdl, 根据Frame. 1.11的状态转移图写了一个module;
module one_pulse(//input
clk,s,rst_n,
//output
P,L);
input s;
input clk;
input rst_n;
output P;
output L;
reg [1:0] state;
reg [1:0] next_state;
//
always @(*) begin
case(state)
2'b00: begin
if (s) begin
next_state = 2'b10;
end
else begin
next_state = 2'b00;
end
end
2'b10: begin
next_state = 2'b01; // clk sensitive
end
2'b01: begin
if(!s) begin
next_state = 2'b00;
end
else begin
next_state = 2'b01;
end
end
default: begin
next_state =2'b00;
end
endcase
end
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
state <= 2'b00;
end
else begin
state <= next_state;
end
end
assign P = state[1]&~state[0];
assign L = state[1]^state[0];
endmodule
// testbench
module tb ();
reg clk;
reg rstn;
//reg seed;
reg enable;
initial begin
clk = 0;
rstn = 1;
enable = 0;
#10 rstn = 0;
#10 rstn = 1;
@(posedge clk) enable = 1;
@(posedge clk);
@(posedge clk) enable = 0;
@(posedge clk);
@(posedge clk);
@(posedge clk) enable = 1;
@(posedge clk) enable = 0;
@(posedge clk);
@(posedge clk);
@(posedge clk) enable = 1;
@(posedge clk) enable = 0;
@(posedge clk) enable = 1;
#150 $finish;
end
always #5 clk = ~clk;
one_pulse u_one_pulse (//input
.clk(clk),
.s(enable),
.rst_n(rstn),
//output
.P(),
.L());
// wire gclk_and = enable & clk;
endmodule
来自书中的状态转移图:
P: s 拉高后产生一个单脉冲;
有一处存疑就是如果s拉高一个cycle后立即拉低一个cycle, 然后再拉高;行为就会跟预想的不一样。
这里隐含着一个条件是,两次s 拉高要大于两个cycle
multiple pulse generation with resume pin added
module one_pulse_r(//input
clk,s,r,rst_n,
//output
P,L);
input s;
input r;
input clk;
input rst_n;
output P;
output L;
reg [1:0] state;
reg [1:0] next_state;
parameter S0 = 2'b00;
parameter S1 = 2'b10;
parameter S2 = 2'b11;
parameter S3 = 2'b01;
//
always @(*) begin
case(state)
S0: begin
if (s) begin
next_state = S1;
end
else begin
next_state = S0;
end
end
S1: begin
next_state = S2; // clk sensitive
end
S2: begin
if(r) begin
next_state = S1;
end
else begin
next_state = S3;
end
end
S3: begin
if (s) begin
next_state = S3;
end
else begin
next_state = S0;
end
end
default: begin
next_state =S0;
end
endcase
end
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
state <= 2'b00;
end
else begin
state <= next_state;
end
end
assign P = state[1]&~state[0];
assign L = state[1]^state[0];
endmodule
//testbench
@(posedge clk) enable = 0;
@(negedge clk) rstn_r = 1;
@(posedge clk) enable = 1;
// @(posedge clk);
@(posedge clk) resume = 1;
@(posedge clk) enable = 0;
@(posedge clk);
@(posedge clk);
@(posedge clk) resume = 0;
// waveform
resume
// 状态转移图