Undefined output on Verilog Testbench - Page 1
Forum section: electronics / beginners

author: Alberto
author_rank: Regular Contributor
timestamp: January 18, 2016, 10:37:29 pm
content: Hey guys,Try as I might I can't find a fix to this problem, this verilog code is designed to make the FPGA act like a simple 4026 Decade Counter. However when I run the testbench all I get is undefined values on the outputs. Previous simpler code I have written for things like counters, in exactly the same way, has been fine. But this doesn't seem to work! My untrained eye cannot spot the mistakes or fundamental errors I have made, please can you help me?Here's the code:// This is the Verilog Code for a 4026 Decade Counter, complete with all of it's functionality including enables, etc.// This shall be a work in progress as I learn more about verilog code, eventually this should end in some highly efficient Verilog code,// as I become more profficient with the language.// Creating Initial Modulemodule ic (clock, a, b, c, d, e, f, g);// Defining Input and Output Portsinput clock;output a, b, c, d, e, f, g;// Defining Port Typesreg a, b, c, d, e, f, g;// Creating Tracking Variablesreg [4:0] counter, counter_n;// Main behavoural codealways @ (posedge clock) begincounter_n = counter + 1;if (counter == 0) begina = 1; b = 1; c = 1; d = 1; e = 1; f = 1; g = 0;end else if (counter == 1) begina = 0; b = 1; c = 1; d = 0; e = 0; f = 0; g = 0;end else if (counter == 2) begina = 1; b = 1; c = 0; d = 1; e = 1; f = 0; g = 1;end else if (counter == 3) begina = 1; b = 1; c = 1; d = 1; e = 0; f = 0; g = 1;end else if (counter == 4) begina = 0; b = 1; c = 1; d = 0; e = 0; f = 1; g = 1;end else if (counter == 5) begina = 1; b = 0; c = 1; d = 1; e = 0; f = 1; g = 1;end else if (counter == 6) begina = 1; b = 0; c = 1; d = 1; e = 1; f = 1; g = 1;end else if (counter == 7) begina = 1; b = 1; c = 1; d = 0; e = 0; f = 0; g = 0;end else if (counter ==begina = 1; b = 1; c = 1; d = 1; e = 1; f = 1; g = 1;end else if (counter == 9) begina = 1; b = 1; c = 1; d = 1; e = 0; f = 1; g = 1;endcounter = counter_n;endendmodule// Testbenchmodule ic_tb;reg clock;wire a, b, c, d, e, f, g;initial begin$monitor ("clock=%b, a=%b, b=%b, c=%b, d=%b, e=%b, f=%b, g=%b", clock, a, b, c, d, e, f, g);clock = 0;#5;#10;#10;#10;#10;#10 $finish;endalways begin#5 clock = !clock;endic ic_1 (.clock(clock), .a(a), .b(b), .c(c), .d(d), .e(e), .f(f), .g(g));endmoduleThanks very much for any help in advance!Alberto

author: langwadt
author_rank: Super Contributor
timestamp: January 18, 2016, 10:48:17 pm
content: you don't have a reset or at least a initial value for your registers

author: Alberto
author_rank: Regular Contributor
timestamp: January 19, 2016, 07:16:34 pm
content: Oh ok so I need to define the state of the counter at the start. Seems obvious now! Doh!Thank's very much for the help!

author: Alberto
author_rank: Regular Contributor
timestamp: January 19, 2016, 08:08:28 pm
content: Hey,I tried to implement some form of reset but I'm still getting the same output! Is there anything I'm doing wrong still?Here's the new code:// This is the Verilog Code for a 4026 Decade Counter, complete with all of it's functionality including enables, etc.// This shall be a work in progress as I learn more about verilog code, eventually this should end in some highly efficient Verilog code,// as I become more profficient with the language.// Creating Initial Modulemodule ic (clock, reset, chip_enable, display_enable, a, b, c, d, e, f, g);// Defining Input and Output Portsinput clock, chip_enable, display_enable, reset;output a, b, c, d, e, f, g;// Defining Port Typesreg a, b, c, d, e, f, g;// Creating Tracking Variablesreg [4:0] counter, counter_n;// Main behavoural codealways @ (posedge clock) begincounter_n = counter + 1;if (counter == 0) begina = 1; b = 1; c = 1; d = 1; e = 1; f = 1; g = 0;end else if (counter == 1) begina = 0; b = 1; c = 1; d = 0; e = 0; f = 0; g = 0;end else if (counter == 2) begina = 1; b = 1; c = 0; d = 1; e = 1; f = 0; g = 1;end else if (counter == 3) begina = 1; b = 1; c = 1; d = 1; e = 0; f = 0; g = 1;end else if (counter == 4) begina = 0; b = 1; c = 1; d = 0; e = 0; f = 1; g = 1;end else if (counter == 5) begina = 1; b = 0; c = 1; d = 1; e = 0; f = 1; g = 1;end else if (counter == 6) begina = 1; b = 0; c = 1; d = 1; e = 1; f = 1; g = 1;end else if (counter == 7) begina = 1; b = 1; c = 1; d = 0; e = 0; f = 0; g = 0;end else if (counter ==begina = 1; b = 1; c = 1; d = 1; e = 1; f = 1; g = 1;end else if (counter == 9) begina = 1; b = 1; c = 1; d = 1; e = 0; f = 1; g = 1;end else if (counter == 10) begincounter <= 0;endcounter <= counter_n;if (reset == 0) begincounter <= 0;endendendmodule// Testbenchmodule ic_tb;reg clock, chip_enable, display_enable, reset;wire a, b, c, d, e, f, g;ic ic_1 (.clock(clock), .reset(reset), .chip_enable(chip_enable), .display_enable(display_enable), .a(a), .b(b), .c(c), .d(d), .e(e), .f(f), .g(g));initial begin$monitor ("clock=%b, reset=%b, a=%b, b=%b, c=%b, d=%b, e=%b, f=%b, g=%b", clock, reset, a, b, c, d, e, f, g);clock = 0;reset = 0;#5 reset = 1;#10;#10;#10;#10;#10 $finish;endalways begin#5 clock = !clock;endendmoduleThanks for any help in advance!Alberto

author: Alberto
author_rank: Regular Contributor
timestamp: January 19, 2016, 09:02:36 pm
content: Ok, an even further update, I am sort of spamming this with reply's :SI have managed to get an output with this code:// This is the Verilog Code for a 4026 Decade Counter, complete with all of it's functionality including enables, etc.// This shall be a work in progress as I learn more about verilog code, eventually this should end in some highly efficient Verilog code,// as I become more profficient with the language.// Creating Initial Modulemodule ic (clock, reset, enable, a, b, c, d, e, f, g);// Defining Input and Output Portsinput clock, reset, enable;output a, b, c, d, e, f, g;// Defining Port Typesreg a, b, c, d, e, f, g;// Creating Tracking Variablesreg [3:0] counter, counter_n;// Main behavoural codealways @ (posedge clock) beginif (counter == 4'b0000) begina = 1; b = 1; c = 1; d = 1; e = 1; f = 1; g = 0;endif (counter == 4'b0001) begina = 0; b = 1; c = 1; d = 0; e = 0; f = 0; g = 0;endif (counter == 4'b0010) begina = 1; b = 1; c = 0; d = 1; e = 1; f = 0; g = 1;endif (counter == 4'b0011) begina = 1; b = 1; c = 1; d = 1; e = 0; f = 0; g = 1;endif (counter == 4'b0100) begina = 0; b = 1; c = 1; d = 0; e = 0; f = 1; g = 1;endif (counter == 4'b0101) begina = 1; b = 0; c = 1; d = 1; e = 0; f = 1; g = 1;end else if (counter == 4'b0110) begina = 1; b = 0; c = 1; d = 1; e = 1; f = 1; g = 1;endif (counter == 4'b0111) begina = 1; b = 1; c = 1; d = 0; e = 0; f = 0; g = 0;endif (counter == 4'b1000) begina = 1; b = 1; c = 1; d = 1; e = 1; f = 1; g = 1;endif (counter == 4'b1010) begincounter <= 0;endelse begina = 1; b = 1; c = 1; d = 1; e = 0; f = 1; g = 1;endif (reset == 1'b1) begincounter <= 4'b000;endif (enable == 1'b1) begincounter_n <= counter + 1'b1;endcounter <= counter_n;endendmodule// Testbench code beginning heremodule ic_tb;reg clock, reset, enable;wire a, b, c, d, e, f, g;ic ic_1 (.clock(clock), .reset(reset), .enable(enable), .a(a), .b(b), .c(c), .d(d), .e(e), .f(f), .g(g));initial begin$monitor ("clock=%b, reset=%b, enable=%b, a=%b, b=%b, c=%b, d=%b, e=%b, f=%b, g=%b", clock, reset, enable, a, b, c, d, e, f, g);clock = 0;reset = 0;enable = 0;#5 reset = 1;#10 reset = 0;enable = 1;#10;#10;#10;#10;#10 $finish;endalways begin#5 clock = !clock;endendmoduleHowever it is a constant output from the else statement at the end of the behavioral code! I still don't know what I am doing wrong!Here is the output for reference:clock=0, reset=0, enable=0, a=x, b=x, c=x, d=x, e=x, f=x, g=xclock=1, reset=1, enable=0, a=1, b=1, c=1, d=1, e=0, f=1, g=1clock=0, reset=1, enable=0, a=1, b=1, c=1, d=1, e=0, f=1, g=1clock=1, reset=0, enable=1, a=1, b=1, c=1, d=1, e=0, f=1, g=1clock=0, reset=0, enable=1, a=1, b=1, c=1, d=1, e=0, f=1, g=1clock=1, reset=0, enable=1, a=1, b=1, c=1, d=1, e=0, f=1, g=1clock=0, reset=0, enable=1, a=1, b=1, c=1, d=1, e=0, f=1, g=1clock=1, reset=0, enable=1, a=1, b=1, c=1, d=1, e=0, f=1, g=1clock=0, reset=0, enable=1, a=1, b=1, c=1, d=1, e=0, f=1, g=1clock=1, reset=0, enable=1, a=1, b=1, c=1, d=1, e=0, f=1, g=1clock=0, reset=0, enable=1, a=1, b=1, c=1, d=1, e=0, f=1, g=1clock=1, reset=0, enable=1, a=1, b=1, c=1, d=1, e=0, f=1, g=1clock=0, reset=0, enable=1, a=1, b=1, c=1, d=1, e=0, f=1, g=1$finish called from file "design.sv", line 83.$finish at simulation time 65V C S S i m u l a t i o n R e p o r tTime: 65 nsCPU Time: 0.240 seconds; Data structure size: 0.0MbTue Jan 19 20:54:50 2016DoneOnce again thanks for any help in advance!

author: langwadt
author_rank: Super Contributor
timestamp: January 19, 2016, 09:50:27 pm
content: I'll give you a few hints.your always@ only get evaluated on the posedge clock so unless reset overlap a positive clock edge you will never get to your resetusually you would do something like this to get an asynchronous reset :always@(posedge clock or posedge reset)beginif(reset)begin...endelsebegin...endendyou are mixing = and <= , that is badcounter <= counter_n overrides the counter = 0 in the if(counter == 10) (which should probably have been in the counter == 9)the code would probably be easier to read with a case statement instead of the long if-else

author: Alberto
author_rank: Regular Contributor
timestamp: January 20, 2016, 07:21:57 pm
content: Once again thanks very much for your reply, this is all really helpful!I will make the amendments you suggested, should have remembered not to mix <= and =, I've seen that that's not really a great thing to do in a tutorial. However, why does the counter <= counter_n override the counter = 0 ? I thought the <= operator meant that you were applying things in parallel, or am I just getting confused?I tried to use a case statement when I first wrote the code, however for some reason it would not let me change the value of more than one of the outputs. Again this is probably just me being stupid.Thanks for your patience, I'm just learning so all of this is super helpful!Alberto

author: langwadt
author_rank: Super Contributor
timestamp: January 20, 2016, 08:58:07 pm
content: Quote from: Alberto on January 20, 2016, 07:21:57 pmI find there is rarely a good reason to use = in a clocked always blocksee the differences here:http://www.asic-world.com/tidbits/blocking.htmlcounter <= counter_n override the counter <= 0 because for <= assignments it is only the last that takes effectbasically if you stick to <= everything you read is what is was before the clock edge and the last assignmentyou make is what you will read on the next clock edgei.e. for 0-9 counteralways@(posedge clk)begincnt <= cnt + 1;if(cnt == 9) cnt <= 0;endyou probably forgot the begin-end for multiline casesi.e.case(cnt)4'd0: begina <= 1'b1;b <= 1'b0;end4'd1: begina <= 1'b0;b <= 1'b1;end....endcase

author: Alberto
author_rank: Regular Contributor
timestamp: January 21, 2016, 04:42:05 pm
content: Again super helpful, thanks so much! A slightly more broad question if I may? How would you say it is best to learn Verilog? Should I do it by example and complete little projects where I learn something new each time, but not in a particularly set order. Or should I read the text based tutorials through and try some projects at the end?Again thanks so much for all the help, I wouldn't have got this far without it!Alberto

author: marshallh
author_rank: Unknown
timestamp: January 21, 2016, 08:07:22 pm
content: Code:module ic (inputwireclk,inputwirereset_n,inputwireenable,outputwirea, b, c, d, e, f, g);reg [6:0] out;assign {a, b, c, d, e, f, g} = out;reg [3:0] counter;always @(posedge clk or negedge reset_n) beginif(~reset_n) begin// reset stuff put herecounter <= 0;end else begin// normal opoerationcase(counter)0: out <= 7'b1111110;1: out <= 7'b0110000;2: out <= 7'b1101101;3: out <= 7'b1111001;4: out <= 7'b0110011;5: out <= 7'b1011011;6: out <= 7'b1011111;7: out <= 7'b1110000;8: out <= 7'b1111111;9: out <= 7'b?; //whatdefault: out <= 9lendcaseif(enable) counter <= counter + 1'b1;endendendmoduleYou might need to add the counter extra reg and flesh out the case statement. 90% of the verilog stuff out there is garbage. There is very little good code on Opencores that I would recommend for learning. But even if it sucks you can still learn something from it.You can join ##fpga on freenode IRC and ask questions. Getting expert direction while doing independent work is the quickest way to success. Don't waste time with Verilog books, focus on synthesizable verilog (the bit that isn't can be used for testbenches, but not much is needed there)

author: azer
author_rank: Regular Contributor
timestamp: January 22, 2016, 01:40:26 pm
content: It was missing the forced rollover of the counter, looks like it runs ok now.Code:module ic (input wire clk,input wire reset_n,input wire enable,output wire a, b, c, d, e, f, g);reg [6:0] out;assign {a, b, c, d, e, f, g} = out;reg [3:0] counter;always @(posedge clk or negedge reset_n) beginif(!reset_n) begin// reset stuff put herecounter <= 3'd0;out <= 7'b1111110;end else begin// normal opoerationcase(counter)0: out <= 7'b1111110;1: out <= 7'b0110000;2: out <= 7'b1101101;3: out <= 7'b1111001;4: out <= 7'b0110011;5: out <= 7'b1011011;6: out <= 7'b1011111;7: out <= 7'b1110000;8: out <= 7'b1111111;9: out <= 7'b1111011;default: out <= 7'b1111110;endcaseif(enable) beginif (counter == 4'd9)counter <= 4'd0;elsecounter <= counter + 4'd1;endendendendmodule

author: Alberto
author_rank: Regular Contributor
timestamp: January 22, 2016, 05:16:08 pm
content: Awesome thanks for the example code, that will be great to reference with mine to see what's different. I will carry on doing independent projects and keep asking questions!Speaking of which! In the case statement, is the "default" case the value the code goes to if it has no other specific orders (one of the other cases)? I was told that I need to make sure I define a starting position, so is this a good way to do it?Also, to define a starting state for your outputs, is it best to use a reset section and when testing activate the reset for the first few seconds of testing?Thanks again for all the help!Alberto

author: azer
author_rank: Regular Contributor
timestamp: January 26, 2016, 01:15:12 pm
content: The default is there to handle if the counter has a value other than 0-9. Since the counter is 4 bits it can be 0-15.It is mostly to tell the synthesizer what to wire up for the remaining cases.You need to set reset low for a clock cycle at startup to bring the counter to a defined value. Since the output is defined by the value of the counter, it will have a defined starting position after reset has been set high again.We also put a reset value for the output so it will have a defined value while we are in reset and in the first cycle after.

author: Alberto
author_rank: Regular Contributor
timestamp: January 26, 2016, 04:42:53 pm
content: Ok so I need a reset in everything I do, or some other way of making everything has a definition on startup. That was the problem I was essentially running into before.Again, thanks very much for all the help, this has cleared a lot of things up for me!Alberto

author: langwadt
author_rank: Super Contributor
timestamp: January 26, 2016, 10:40:06 pm
content: Quote from: azer on January 26, 2016, 01:15:12 pmyou don't have to put in a default: but it is a good habit, especially for combination cases because if you don't cover all case you risk inferinglatches which you almost never want.if it is going to match a 4026 the reset has to by async so it doesn't have to be high for a whole clock cycleand the outputs can't be registered, the have to be done combinatorical from the the counter and enablesomething along the lines of:Code:module cd4026(input clock,input reset,input clockinhibit,input enablein,output A,output B,output C,output D,output E,output F,output G,output Cungated,output reg carryout);reg [3:0] cnt;reg [6:0] out;assign {A,B,C,D,E,F,G} = enablein ? out : 7'b0000000;assign Cungated = out;always@(posedge clock or posedge reset)beginif(reset)begincnt <= 4'd0;carryout <= 1'b1endelse if(~clockinhibit)begincnt <= cnt + 4'd1;if(cnt == 4'd9)begincnt <= 0;carryout <= 1'b1;endif(cnt == 4) carryout <= 1'b0;endendalways@(*)begincase(cnt)4'd0: out <= 7'b1111110;4'd1: out <= 7'b0110000;4'd2: out <= 7'b1101101;4'd3: out <= 7'b1111001;4'd4: out <= 7'b0110011;4'd5: out <= 7'b1011011;4'd6: out <= 7'b1011111;4'd7: out <= 7'b1110000;4'd8: out <= 7'b1111111;4'd9: out <= 7'b1111011;default: out <= 7'b1111110;endcaseendendmodule

author: Alberto
author_rank: Regular Contributor
timestamp: January 27, 2016, 05:10:29 pm
content: So from what I understand, the outputs have to be wires that immediately respond to the change in the value of the counter? But they will only do so when the enable pin is not active.So does the counter advance even though the output does not, and when the enable pin is deactivated the output will jump to the value of the counter?Also you have used the syntax: always @(*) when putting in the case command. Do you mind me asking what this means?Thanks for all the help again!Edit: Also another question!If I put the code:a = 2;a = 3;Would a be 2 or 3 on the next clock edge? Would it be 2 on the first and then 3 on the second?Sorry for going back to this, just need to understand exactly what's going on here!

author: langwadt
author_rank: Super Contributor
timestamp: January 28, 2016, 12:28:21 am
content: Quote from: Alberto on January 27, 2016, 05:10:29 pmthe out immediately respond to the counter, but when the enable pin is low the outputs are all 0,the counter advance when clockinhibit is lowalways@(*) means when any of the relevant signals change, could have written always@(cnt)(*) is shorter and you don't forget anya = 2;a = 3;doesn't make much sense it set a = 3 there's no clocks involvedlook at it this way, what is inside an always block happens instantly when ever the always@() "triggers"

author: andre_teprom
author_rank: Regular Contributor
timestamp: January 28, 2016, 01:25:24 pm
content: Quote from: langwadt on January 28, 2016, 12:28:21 amPerhaps not strictly...Compiler should issue an Warning due to the fact that it involves not a syncronous operation (<=), but a combinational assignment for 2 values attempting to load onto the same variable at same time, that's not right ?

author: Alberto
author_rank: Regular Contributor
timestamp: January 28, 2016, 04:40:50 pm
content: Ok I think I get it now! I think I was looking at it as though it would make something different happen on the rising clock edge. But having read the original link you posted again it makes sense to me. From what I understand, this code:always @ (posedge clk) begina = 2;a = 3;endwould set the value of a to 3 always, a would never take the value of 2.Is this not a synchronous operation because you are essentially "blocking" the code from continuing instead of letting it flow like you would with a non blocking statement?

author: langwadt
author_rank: Super Contributor
timestamp: January 28, 2016, 07:41:03 pm
content: Quote from: andre_teprom on January 28, 2016, 01:25:24 pmthe a =2 won't have any affect so it shouldn't give you a warning,<= or = doesn't make it synchronous or combinatorical, it just makes it blocking or non-blockingto make it synchronous you have to put it in an clocked always block

author: langwadt
author_rank: Super Contributor
timestamp: January 28, 2016, 07:55:45 pm
content: Quote from: Alberto on January 28, 2016, 04:40:50 pmit is synchronous because it is a clocked always blockblocking vs. non-blocking is something elsehttp://www.asic-world.com/tidbits/blocking.htmlDon't look at verilog as if it is code, it is not, it is a description of hardwareunless you have a very specific reason don't use blocking statements, it probably won't what you want

author: Alberto
author_rank: Regular Contributor
timestamp: January 28, 2016, 10:34:43 pm
content: Ok awesome, that's cleared it all up for me now. Thanks very much for your help, everything has been really informative! Time to finish up the other parts of this project such as the display enable, etc. If I need anymore help then I know where to come!Thanks again,Alberto