一天一道Verilog编程题(三)

有一个16bit序列每个clk向左移一位,要求检测5的倍数

题目要求检测出5的倍数,如若不是5的倍数那除以5必然会产生余数,所以我们可以检测16个周期后是是否有余数产生。这里用状态机来实现是比较合理的,状态定义如下:
S0:余数为0;
S1:余数为1;
S2:余数为2;
S3:余数为3;
S4:余数为4;
状态转换如图所示
一天一道Verilog编程题(三)_第1张图片

module devide_5#(
	parameter WIDTH_D	=	16
)(
	input serial_in,
	input clk,rst_n,
	output [2:0] remain
	);
	
	localparam 	S0=3'b000,
				S1=3'b001,
				S2=3'b010,
				S3=3'b011,
				S4=3'b100;
				
	reg [2:0] current_state,next_state;
	reg [4:0] counter;
	
	always @ (posedge clk or negedge rst_n)
	begin
		if (!rst_n)
			current_state<=S0;
		else 
			current_state<=next_state;
	end
	
	always @ (*)
	begin
		next_state=S0;
		if (counter==WIDTH_D)
			next_state=S0;
		else begin
		case (current_state)
		S0:begin
			if (serial_in)
				next_state=S1;
			else 
				next_state=S0;
		end
			
		S1:begin
			if (serial_in)
				next_state=S3;
			else 
				next_state=S2;
		end
		
		S2:begin
			if (serial_in)
				next_state=S0;
			else 
				next_state=S4;
		end
		
		S3:begin
			if (serial_in)
				next_state=S2;
			else 
				next_state=S1;
		end
		
		S4:begin
			if (serial_in)
				next_state=S4;
			else 
				next_state=S3;
		end
		
		default:next_state=S0;
		endcase
		end
	end

	always @ (posedge clk or negedge rst_n)
	begin
		if (!rst_n)
			counter<=0;
		else if (counter==WIDTH_D)
			counter<=0;
		else 
			counter <=counter+1'b1;
	end
	
	assign remain=(counter==WIDTH_D)?current_state:3'b000;
endmodule 

module devide_5_t;
	reg clk;
	reg serial_in;
	reg rst_n;
	wire [2:0] remain;
	
	devide_5 U1(.clk(clk),.rst_n(rst_n),.remain(remain),.serial_in(serial_in));
	
	initial begin
		clk=1'b0;
		forever # 10 clk=~clk;
	end
	
	initial serial_in=1'b0;
	
	initial begin
		rst_n=1'b1;
	    #3 rst_n=1'b0;
		#3 rst_n=1'b1;
	end
	
	always @(posedge clk)
		serial_in=~serial_in;
endmodule 

你可能感兴趣的:(数字电路设计,Verilog,HDL)