状态机与时钟分频

描述

题目描述:    

使用状态机实现时钟分频,要求对时钟进行四分频,占空比为0.25

信号示意图:

clk为时钟

rst为低电平复位

clk_out 信号输出

Ps 本题题解是按照1000的状态转移进行的,不按照此状态进行,编译器可能报错但没有影

波形示意图:

输入描述:

clk为时钟

rst为低电平复位

输出描述:

clk_out 信号输出

解题思路 

根据波形图的描述可得

本题中采用的时钟分频的状态机本质上可以视为生成"1000"序列的序列发生器;

因此我们使用传统的有限状态机的三段式写法:

进程一:同步时序always模块,格式化描述次态寄存器迁移到现态寄存器;

always @(posedge clk or negedge rst) begin
	if (!rst)	current_state <= IDLE;
	else		current_state <= next_state;
end

进程二:组合逻辑always模块,描述次态转移条件判断

always @(*) begin
	case(current_state)
	IDLE:	next_state = S1;
	S1:		next_state = S2;
	S2:     next_state = S3;
	S3:     next_state = IDLE;
	default:next_state = IDLE;
	endcase
end

进程三:同步时序always模块,格式化描述次态寄存器输出

always @(posedge clk or negedge rst) begin
	if (!rst) clk_out <= 1'b0;
	else begin
	case (next_state)
	IDLE: clk_out <= 1'b0;
	S1:	  clk_out <= 1'b1;
	S2:	  clk_out <= 1'b0;
	S3:   clk_out <= 1'b0;
	default:clk_out <= 1'b0;
	endcase
	end
end

问题:

对于进程三,当使用如下代码时,会出现结果错误:

always @(posedge clk or negedge rst) begin
	if (!rst) clk_out <= 1'b0;
	else begin
	case (next_state)
	IDLE: clk_out <= 1'b1;
	S1:	  clk_out <= 1'b0;
	S2:	  clk_out <= 1'b0;
	S3:   clk_out <= 1'b0;
	default:clk_out <= 1'b0;
	endcase
	end
end

而将case中的next_state换成current_state时,不会报错:

always @(posedge clk or negedge rst) begin
	if (!rst) clk_out <= 1'b0;
	else begin
	case (current_state)
	IDLE: clk_out <= 1'b1;
	S1:	  clk_out <= 1'b0;
	S2:	  clk_out <= 1'b0;
	S3:   clk_out <= 1'b0;
	default:clk_out <= 1'b0;
	endcase
	end
end

完整代码如下:

`timescale 1ns/1ns

module huawei7(
	input wire clk  ,
	input wire rst  ,
	output reg clk_out
);

//*************code***********//

reg [1:0] current_state, next_state;
//设置状态名称
parameter [1:0] IDLE = 2'b00;
parameter [1:0] S1 = 2'b01;
parameter [1:0] S2 = 2'b11;
parameter [1:0] S3 = 2'b10;

always @(posedge clk or negedge rst) begin
	if (!rst)	current_state <= IDLE;
	else		current_state <= next_state;
end

always @(*) begin
	case(current_state)
	IDLE:	next_state = S1;
	S1:		next_state = S2;
	S2:     next_state = S3;
	S3:     next_state = IDLE;
	default:next_state = IDLE;
	endcase
end

always @(posedge clk or negedge rst) begin
	if (!rst) clk_out <= 1'b0;
	else begin
	case (next_state)
	IDLE: clk_out <= 1'b0;
	S1:	  clk_out <= 1'b1;
	S2:	  clk_out <= 1'b0;
	S3:   clk_out <= 1'b0;
	default:clk_out <= 1'b0;
	endcase
	end
end

//*************code***********//
endmodule

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部