Testing verilog code

  • Thread starter polaris90
  • Start date
  • #1
45
0

Main Question or Discussion Point

I have a verilog code for a simple 8-bit counter. I'm trying to build a testbench but for some reason it doesn't work. I'm using xilinx and when I run the simulation, the inputs work but the output doesn't work. It stays as XXX. Here is my verilog code and testbench.

Code:
module counter(enable, reset, clk, out, AN, style);

input style; //to count up or down
input clk;
input reset;
input enable;
output [6:0] out; //output to display

reg[3:0] first; //to hold the output for first seven-seg
reg[3:0] second;//to hold the outputfor second seven-seg
reg[24:0] CLKCNTR;  //clock counter
output [3:0] AN;//to indicate which seven-seg to use

	always @(posedge clk)begin//mak it count when the clock ticks
		
		CLKCNTR = CLKCNTR+1;    //increment the clock counter by one until 
		if (CLKCNTR==25000000) //it reaches 25000000
		begin
			CLKCNTR=0;	//reset the counter to loop
			if (reset)		//occurs only when reset is high
			begin
				first=0;		//reset seven segment displasy if 
				second=0;	//reset is high
			end
			
			else if (enable)	
			begin
				if (style)  //if counting up
				begin
					first = first+1;//increment first digit
				
					if(first==10) //if it reaches 10, reset and increment next digit
					begin
						first=0;
				
						second = second+1;	
				
						if(second==6) //if second digit reaches 6(one minute), reset
							second=0;
				
					end	
				end
				
				else if (!style)//if counting down
				begin
					if (first>0)//decrement the first digit unitl it reaches zero
						first=first-1;
					else
					begin
						first=9;
						if (second>0)
							second=second-1;
						else
							second=5;
					end
				end
			end
		 end
	end
	
	//instantiate the display module with the inputs and output
	display D1(.clk(clk), .out(out),.AN1(AN), .ones(first), .tens(second));
	
	
endmodule


module display(clk, out,AN1, ones, tens);


input clk;
output reg[6:0] out;
//output reg[6:0] out2;
input [3:0]ones; //first digit(seven segment display)
input [3:0]tens; //second digit(seven segment display)
output reg [3:0] AN1; //to tell which seven segment display is to be turned on
reg[20:0] DSPCNTR; //display counter

 initial begin
	AN1[3:0] =4'b1011;//initialize the seven-seg displays
	end
	always@(posedge clk) 
	begin
		DSPCNTR = DSPCNTR +1;//increment the counter of display counter until it reaches 25MHz
		if(DSPCNTR == 250000)//that way the seven-segs are refreshed and we are able to see them change
		begin
			DSPCNTR = 0; //reset counter
			
			AN1[2]=~AN1[2];
			AN1[1]=~AN1[1];
			if (AN1[1])
			begin
				case (ones)//case for first digit
						0: out=7'b1000000;
						1: out=7'b1111001;
						2: out=7'b0100100;
						3: out=7'b0110000;
						4: out=7'b0011001;
						5: out=7'b0010010;
						6: out=7'b0000010;
						7: out=7'b1111000;
						8: out=7'b0000000;
						9: out=7'b0010000;
					default: out=7'b1111111;
					endcase
			end
			
		  else if (AN1[2])//case for second digit
			begin
				case (tens)
						0: out=7'b1000000;
						1: out=7'b1111001;
						2: out=7'b0100100;
						3: out=7'b0110000;
						4: out=7'b0011001;
						5: out=7'b0010010;
						6: out=7'b0000010;
						7: out=7'b1111000;
						8: out=7'b0000000;
						9: out=7'b0010000;
					default: out=7'b1111111;
					
				endcase		
			end
		  
		end
	end
	
endmodule
testbench

Code:
module counter_tb;

	// Inputs
	reg enable;
	reg reset;
	reg clk;
	reg style;

	// Outputs
	wire [6:0] out;
	wire [3:0] AN;

	// Instantiate the Unit Under Test (UUT)
	counter uut (
		.enable(enable), 
		.reset(reset), 
		.clk(clk), 
		.out(out), 
		.AN(AN), 
		.style(style)
	);

	initial begin
		// Initialize Inputs
		enable = 0;
		reset = 0;
		clk = 0;
		style = 0;

		// Wait 100 ns for global reset to finish
		#100;
        
		// Add stimulus here
	#3 reset =1;
	#2reset = 0;
	#2 style = 1;
	#2 enable = 1;
	#100 enable = 0;
	#4 reset = 1;
	#4 reset = 0;
	end

always begin
	#1 clk = ~clk;	//clock toggles every strike
end

endmodule
I can't seem to find the reason why the output is no being displayed. I have tested someone else's code and the same happened. Could someone kindly give me a clue on what I'm doing wrong?
 
Last edited:

Answers and Replies

  • #2
meBigGuy
Gold Member
2,323
405
I think you are not resetting the counter. X + 1 = X

On another note, when you synthesize RTL flops, they should be of the form
// for sync reset
Code:
always @ (posedge clk) begin
   if (reset) begin
      counter <= 0;
      //always reset EVERYTHING in this block here ---- get in the habit
   end else begin
      if (enable) begin
         counter <= counter + 1;
      end
   end
end
//for async reset

Code:
always @ (posedge clk or posedge reset) begin
   if (reset) begin
      counter <= 0;
      //always reset EVERYTHING in this block here ---- get in the habit
   end else begin
      if (enable) begin
         counter <= counter + 1;
      end
   end
end
The separation of the reset block is important in some cases, expecially if you do gate level sims after synthesis. For "normal" synthesis tools you need to follow that structure. Again, get in the habit.
 
  • #3
45
0
I don't think I'm following you completely. If there is a block describing the procedure to be done when reset happens, why do I have to check at the edge of reset?
 
  • #4
meBigGuy
Gold Member
2,323
405
Sorry, maybe I confused you. I showed two different examples, one for sync reset flops and one for async reset flops. In order to map (synthesize) to an async reset flop you need to follow the form of the second example.

The first example is good form for synchromous reset in clocked blocks, but is not mandatory. It is structured that way because reset should be the highest priority. This eliminates problems with X at the beginning of simulation (X propagation) that can happen in gate-level simulations. Sometimes thare are two resets. A power-on reset at the beginning of operation, and a soft-reset that can occur anytime. Sometimes you want them to do different things.

But there is another problem in your design. Simulations begin with all elements set to X.

CLKCNTR starts as X. When you add 1, it is still X. It will always be X. So reset will never be seen.
 
  • #5
45
0
I don't see how the reset would never be seen. I tried initializing CLKCNTR but I get the same result. The compiler doesn't give me any warnings/errors about that. Also. I was able to test my code on an FPGA and it worked perfectly. I don't understand why it wouldn't work with the simulator. Here is a screenshot from the simulator.

I also tried initializing the outputs but they remain with that value all the way through.
 

Attachments

  • #6
meBigGuy
Gold Member
2,323
405
The x problem is a simulation thing, since x doesn't exist in real life. Show the values for all the internal signals.

Try initializing DSPCNTR
 
  • #7
58
1
to expand on what meBigGuy wrote, you never initialize CLKCNTR. It is defined as a register, but it's initial value is never given -- you start incrementing it right after the Always statement, without initializing it first. Your reset block is never seen because the counter never increments from X in the first place -and your if(reset) test only is seen if CLKCNTR==25000000. Like he said, you are better off always starting with an initialization clause within the Always blocks that resets all registers to their initial conditions (he showed two ways of doing this)

I would suggest the following:

always @ (posedge clk)
if (reset || (CLKCNTR==25000000) ) // synchronous reset under either condition....
begin
counter <= 0;
end
else if (reset)
begin
first <=0;
second <=0;
end
else if (enable)
begin
counter <= counter + 1;
end
end //always block
 
Last edited:

Related Threads on Testing verilog code

  • Last Post
Replies
1
Views
6K
  • Last Post
Replies
5
Views
1K
  • Last Post
Replies
9
Views
4K
Replies
3
Views
8K
  • Last Post
Replies
2
Views
4K
  • Last Post
Replies
9
Views
6K
  • Last Post
Replies
2
Views
3K
  • Last Post
Replies
2
Views
4K
  • Last Post
Replies
2
Views
3K
  • Last Post
Replies
11
Views
3K
Top