题目链接:Exams/2014 q3fsm - HDLBits (01xz.net)
题目比较简单,提几个要点
- A状态在接收到S=1后跳转到B状态,主要工作在B状态设计
- 需要在B状态期间计算W的周期数,必须等于2个周期才可以输出一个周期的z
- z的有效周期在3个B周期之后下一个周期,也就是开头第一个B周期(注意时序)
- 尽量少的状态
一开始采用了4个状态的设计,代码如下:
module top_module (
input clk,
input reset, // Synchronous reset
input s,
input w,
output z
);
parameter A = 2'd0;
parameter B = 2'd1;
parameter B1 = 2'd2;
parameter B2 = 2'd3;
reg [1:0] curr_state;
reg [1:0] next_state;
reg [1:0] num_w;
always@(posedge clk) begin
if(reset) begin
curr_state <= A;
end
else begin
curr_state <= next_state;
end
end
always@(*) begin
case(curr_state)
A:next_state = s ? B : A;
B:next_state = B1;
B1:next_state = B2;
B2:next_state = B;
default:next_state = A;
endcase
end
always@(posedge clk) begin
if(reset) begin
num_w <= 2'b0;
end
else begin
if(curr_state == B) begin
num_w <= w;
end
else if((curr_state == B1)||(curr_state == B2)) begin
num_w <= num_w + w;
end
else begin
num_w <= num_w;
end
end
end
assign z = (curr_state == B)&&(num_w == 2'd2);
endmodule
后来觉得状态太多了,不符合题目要求,改成了两个状态的设计,多使用了一个3状态的计数器。但是4个状态的设计可读性更好,有好有坏吧。代码如下:
module top_module (
input clk,
input reset, // Synchronous reset
input s,
input w,
output z
);
parameter A = 1'd0;
parameter B = 1'd1;
reg curr_state;
reg next_state;
reg [1:0] num_w;
reg [1:0] count;
always@(posedge clk) begin
if(reset) begin
curr_state <= A;
end
else begin
curr_state <= next_state;
end
end
always@(*) begin
case(curr_state)
A:next_state = s ? B : A;
B:next_state = B;
default:next_state = A;
endcase
end
always@(posedge clk) begin
if(reset) begin
num_w <= 2'b0;
end
else begin
if(curr_state == B) begin
if(count == 2'b0) begin
num_w <= w;
end
else begin
num_w <= num_w + w;
end
end
else begin
num_w <= num_w;
end
end
end
always@(posedge clk) begin
if(reset) begin
count <= 2'b0;
end
else begin
if(curr_state == B) begin
if(count == 2'd2) begin
count <= 2'd0;
end
else begin
count <= count + 1'b1;
end
end
else begin
count <= 2'd0;
end
end
end
assign z = (curr_state == B)&&(num_w == 2'd2)&&(count == 2'b0);
endmodule
写代码的时候,发现自己对状态的变化时刻还是不太敏感,导致错误比较多,哎,慢慢加油吧!