数字IC面试手撕代码(一)

1、最近看别人有面试说遇到这样一个问题。用状态机实现类似序列检测的题目:生成01011011101111…依次类推。针对这个问题,我设计如下的三段式状态机代码,用了4个状态,2个计数器。
在这里插入图片描述设计之初,本来是没有START这个状态的,在第三段时候,用c_state作为判断量。但是会出现011011101111…这样的情况,而且done信号是不符合自己设计之初的思路。所以改成用n_state去做判断量,但是又会由于IDLE不会进入,导致出错,所以加了一个START,即赋初值的状态。

module data(
	input clk,
	input rst_n,
	output reg data
);


parameter IDLE = 2'b00;
parameter S1 = 2'b01;
parameter S2 = 2'b10;
parameter START = 2'b11;

reg [1:0] c_state;
reg [1:0] n_state;

reg [5:0] cnt;       //作为本次1的个数的计数器,递减
reg [5:0] cnt_temp;    //计算下一次循环时候1的个数
reg done;
always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		c_state <= IDLE;
	end
	else begin
		c_state <= n_state;
	end
end

always @ (*) begin
	case(c_state) 
		IDLE : begin
				n_state = START;
				end
		START : begin
				n_state = S1;
				end
		S1 : begin
				n_state = S2;
			end
		S2 : begin
				if(done) begin
					n_state = S1;
				end
				else begin
					n_state = S2;
				end
			end
		default : begin
				end
	endcase
end

always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		data <= 1'b0;
		cnt <= 6'd0;
	end
	else begin
		case(n_state)
			START : begin
					cnt <= 6'd0;
					data <= 1'b0;
					cnt_temp <= 6'd1;
					end
			S1 : begin
					cnt <= cnt_temp;
					cnt_temp <= cnt_temp + 1'b1;
					data <= 1'b0;
					done <= 1'b0;
				end
			S2 : begin
					cnt <= cnt - 1'b1;
					data <= 1'b1;
					if(cnt==6'b1) begin
						done <= 1'b1;
					end
					else begin
						done <= 1'b0;
					end
				end
			default : begin
					end
		endcase
	end
end

endmodule

测试代码:

`timescale 1ps/1ps
module tb();
reg clk;
reg rst_n;
wire data;

data inst(
	.rst_n(rst_n),
	.clk(clk),
	.data(data)
);

initial begin
	clk = 0;
	rst_n = 0;
	#22;
	rst_n = 1;
end

always #5 clk = ~clk;
endmodule

仿真代码如下:
在这里插入图片描述总共用了18个寄存器。
如果有什么别的思路或者更好的设计方法麻烦留言。

猜你喜欢

转载自blog.csdn.net/weixin_43727437/article/details/106882473
今日推荐