使用一个较为简单思路进行解答
代码没有整理规范,但思路比较好理解。
在上一题状态机基础上做补充。50行之前为上一题答案
思路:
状态机部分:Exams/review2015 fsm
- 序列检测使用寄存器存储之前110,和当前时刻1,即切换状态
- SHIFT状态下保存4个时钟,使用shift_cnt计数0-3,切状态
- COUNT状态等待done_counting切状态
- DONE状态等待ACK切状态
Exams/review2015 fancytimer在状态机上进行补充
- 目的:需要使用shift_ena、counting信号产生done_counting供切状态;
- 思路:
产生该信号需要计数,计数原型需要在shift_ena存储计数的开始值。
根据需求,使用shift_flg_cnt计数到999,shift_ena值-1;
直到 (shift_flg_cnt == 16’d999) && (shift_reg == 4’d0)时即计数完毕即done_counting信号
module top_module (
input clk,
input reset, // Synchronous reset
input data,
output [3:0] count,
output counting,
output done,
input ack );
localparam [1:0]DETC1101 = 0,SHIFT = 1,COUNT = 2,DONE = 3;
reg [1:0]CS,NS;
always@(posedge clk)begin
if(reset)
CS <= DETC1101;
else
CS <= NS;
end
always@(*)begin
case(CS)
DETC1101 : NS = ((reg_data == 3'b110) && data )?SHIFT:DETC1101;
SHIFT : NS = (shift_cnt == 2'd3)?COUNT:SHIFT;
COUNT : NS = done_counting?DONE:COUNT;
DONE : NS = ack?DETC1101:DONE;
default : NS = DETC1101;
endcase
end
reg [2:0]reg_data = 0;
always@(posedge clk)begin
if(CS == DETC1101 && (!reset))
reg_data <= {reg_data[1:0],data};
else
reg_data <= 3'd0;
end
reg [1:0]shift_cnt;
always@(posedge clk)begin
if(CS == SHIFT)
shift_cnt <= shift_cnt +1'b1;
else
shift_cnt <= 2'b0;
end
wire shift_ena;
assign shift_ena = (CS == SHIFT);
assign counting = (CS == COUNT);
assign done = (CS == DONE);
reg [3:0]shift_reg = 0;
always@(posedge clk)begin
if(shift_ena)
shift_reg <= {shift_reg[2:0],data};
else if(shift_flg_cnt == 16'd999)
shift_reg <= shift_reg - 1'b1;
else
shift_reg <= shift_reg;
end
reg [15:0]shift_flg_cnt;
always@(posedge clk)begin
if(CS == COUNT)begin
if(shift_flg_cnt == 16'd999)
shift_flg_cnt <= 16'd0;
else
shift_flg_cnt <= shift_flg_cnt + 1'b1;
end
else
shift_flg_cnt <= 16'd0;
end
assign count = shift_reg;
wire done_counting = (shift_flg_cnt == 16'd999)&&(shift_reg == 4'd0);
endmodule