群里看到的一道题目,可以用状态机的方法解决。
DILE:等待in信号拉高
s0 :计数in信号维持周期数
s1:小于4时的状态,out输出0,跳回IDLE
s2:大于4时的状态,out输出n/4个时钟周期,然后跳回IDLE
代码如下,用的三段式状态机,加强自己写三段式的熟练度和经验
module test(in,clk ,out , rst) ;
input in , clk , rst ;
output reg out ;
reg [4:0] cnt ;
reg [1:0] cstate , nstate , fin ;
reg inbuf , neg_in , pos_in ;
parameter IDLE = 0 ;
parameter s0 = 1 ;
parameter s1 = 2 ;
parameter s2 = 3 ;
module test(in,clk ,out , rst) ;
input in , clk , rst ;
output reg out ;
reg [4:0] cnt ;
reg [1:0] cstate , nstate , fin ;
reg inbuf , neg_in , pos_in ;
parameter IDLE = 0 ;
parameter s0 = 1 ;
parameter s1 = 2 ;
parameter s2 = 3 ;
always @(posedge clk ) begin //这一部分没有使用到
inbuf <= in ;
pos_in <= in & (~inbuf) ;
neg_in <= (~in) & inbuf ;
end
always @(posedge clk or negedge rst ) begin
if(~rst) cstate <= IDLE ;
else cstate <= nstate ;
end
always@(clk ) begin
nstate = IDLE ;
case(cstate)
IDLE:
if(in) nstate = s0 ;
else nstate = IDLE ;
s0 : begin
if(in) nstate = s0 ;
else if(cnt>=4) nstate = s2 ;
else nstate = s1 ;
end
s1:
nstate = IDLE ;
s2 : begin
if(cnt<4) nstate = IDLE ;
else nstate = s2 ;
end
default : ;
endcase
end
always@(posedge clk or negedge rst) begin
if(~rst) begin
cnt <= 0 ;
fin <= 0 ;
out <= 0 ;
end
case(nstate)
IDLE : begin
out <= 0 ;
cnt <= 0 ;
end
s0 : begin
cnt <= cnt + 1 ;
end
s1 : begin
out <= 0 ;
cnt <= 0 ;
end
s2 : begin
out <= 1 ;
cnt <= cnt - 4 ;
end
default : ;
endcase
end
endmodule
always @(posedge clk ) begin
inbuf <= in ;
pos_in <= in & (~inbuf) ;
neg_in <= (~in) & inbuf ;
end
always @(posedge clk or negedge rst ) begin
if(~rst) cstate <= IDLE ;
else cstate <= nstate ;
end
always@(clk ) begin
nstate = IDLE ;
case(cstate)
IDLE:
if(in) nstate = s0 ;
else nstate = IDLE ;
s0 : begin
if(in) nstate = s0 ;
else if(cnt>=4) nstate = s2 ;
else nstate = s1 ;
end
s1:
nstate = IDLE ;
s2 : begin
if(cnt<4) nstate = IDLE ;
else nstate = s2 ;
end
default : ;
endcase
end
always@(posedge clk or negedge rst) begin
if(~rst) begin
cnt <= 0 ;
fin <= 0 ;
out <= 0 ;
end
case(nstate)
IDLE : begin
out <= 0 ;
cnt <= 0 ;
end
s0 : begin
cnt <= cnt + 1 ;
end
s1 : begin
out <= 0 ;
cnt <= 0 ;
end
s2 : begin
out <= 1 ;
cnt <= cnt - 4 ;
end
default : ;
endcase
end
endmodule
测试代码如下
`timescale 1ns/1ps
module test_tb();
reg clk , rst , in ;
wire out ;
initial begin
clk = 0 ;
rst = 0 ;
in = 0 ;
#100 rst = 1 ;
#40 in = 1 ;
#60 in = 0 ;
#100 in = 1 ;
#100 in = 0 ;
#100 in = 1 ;
#320 in = 0 ;
#2000 $stop ;
end
test test_inst(
.clk(clk) ,
.in(in) ,
.out(out) ,
.rst(rst)
);
always #10 clk = ~clk ;
endmodule
代码10分钟,调试两小时。。。