题意整理

       题目要求编写一个十六进制计数器,即输出数值number每次变化1,在0-15之间循环。set信号的值为一时,将输出数值num置为set_num。

题解主体

       首先明确number的取值逻辑,声明number变量为4位无符号数,数值每个时钟加一,则每次数值达到15,下一个时钟因为位宽的限制,自动变为1,可以实现十六进制计数。当set信号为1时,将set_num的值赋给number。

              always @(posedge clk or negedge rst_n)

              if (!rst_n)

                     begin

                            number<= 4'b0;

                     end

              else if(set)

                     begin

                            number<= set_num;

                     end

              else

                     begin

                            number<= number+ 1'd1;

                     end

然后确定zero的取值逻辑,在默认情况下为0,当number=0时,zero值为1。

always @(posedge clk or negedge rst_n)

              if (!rst_n)

                     begin

                            zero <= 1'd0;

                     end

              else if (number == 4'd0)

                     begin

                            zero <= 1'b1;

                     end

              else

                     begin    

                            zero <= 1'b0;

                     end

按照以上代码,因为判断number==4’d0需要一个时钟,zero信号为1,总是滞后number==0一个时钟周期。所以可以考虑将number延迟一个时钟再输出。使用num变量代替上述的number,再通过以下语句实现number延迟一个时钟输出。

reg [3:0]num;

       always @(posedge clk or negedge rst_n)

              if (!rst_n)

                     begin

                            number <= 4'd0;

                     end

              else

                     begin    

                            number <= num;

                     end

参考答案

`timescale 1ns/1ns

module count_module(
	input clk,
	input rst_n,
	input set,
	input [3:0] set_num,
	output reg [3:0]number,
	output reg zero
	);
	reg [3:0]num;
	
	always @(posedge clk or negedge rst_n)
		if (!rst_n)
			begin 
				zero <= 1'd0;
			end
		else if (num == 4'd0)
			begin
				zero <= 1'b1;
			end
		else 
			begin	
				zero <= 1'b0;
			end
		
	always @(posedge clk or negedge rst_n)
		if (!rst_n)
			begin 
				num <= 4'b0;
			end
		else if(set)
			begin
				num <= set_num;
			end
		else 
			begin
				num <= num + 1'd1;
			end

	always @(posedge clk or negedge rst_n)
		if (!rst_n)
			begin 
				number <= 1'd0;
			end
		else 
			begin
				number <= num;
			end			

endmodule