【Verilog学习日常】—牛客网刷题—Verilog企业真题—VL65

状态机与时钟分频

描述

题目描述:

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

信号示意图:

clk为时钟

rst为低电平复位

clk_out 信号输出

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

波形示意图:

输入描述:

clk为时钟

rst为低电平复位

输出描述:

clk_out 信号输出

解题思路

根据波形图的描述可得

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

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

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

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

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

cpp 复制代码
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模块,格式化描述次态寄存器输出

cpp 复制代码
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

问题:

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

cpp 复制代码
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时,不会报错:

cpp 复制代码
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

完整代码如下:

cpp 复制代码
`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
相关推荐
_文书先生9 分钟前
《NoSQL》非关系型数据库MongoDB 学习笔记!
学习·mongodb·nosql
LearnTech_12329 分钟前
【学习笔记】手写 Tomcat 八
java·笔记·学习·tomcat·手写 tomcat
OEC小胖胖1 小时前
Spring MVC系统学习(二)——Spring MVC的核心类和注解
java·后端·学习·spring·mvc·web
国中之林2 小时前
【刷点笔试面试题试试水】不使用任何中间变量如何将a、b的值进行交换?
c++·学习·面试·笔试·刷题
samroom2 小时前
前端学习第一天笔记 HTML5 CSS初学以及VSCODE中的常用快捷键
前端·css·笔记·学习·html5
艾伦~耶格尔2 小时前
Java Web 之 Cookie 详解
java·开发语言·前端·后端·学习·cookie
蜡笔小新星3 小时前
MySQL添加时间戳字段并且判断插入或更新时间
数据库·经验分享·学习·mysql
CrazyZ1263 小时前
c++primer第十三章 类继承
开发语言·c++·笔记·学习
我命由我123454 小时前
8.使用 VSCode 过程中的英语积累 - Help 菜单(每一次重点积累 5 个单词)
ide·经验分享·笔记·vscode·学习·编辑器·学习方法