BCD and 7segment decoder show strange result

8.8k views Asked by At

I'm trying to create connection from BCD to 7-segment decoder.
When I press button UP_* or DOWN_*, it should counting up or counting down. But my simulation only displays 0000001 even when I press button UP or DOWN.

BCD module code:

module BCDcountmod(
  input Clock, Clear, up, down,
  output reg [3:0] BCD1, 
  output reg [3:0] BCD0);
//reg [3:0] BCD1_1, BCD0_0;

  always @(posedge Clock or negedge Clear) begin
    //---- IS IT CLEAR? --------------
    if (~Clear) begin
      BCD1 <= 'b0;
      BCD0 <= 'b0;
    end
    //---- IS IT UP? --------------
    else if (up == 1'b1)  begin
      if (BCD0 == 4'b1001) begin
        BCD0 <= 0;
        if (BCD1 == 4'b1001)
          BCD1 <= 0;
        else
          BCD1 <= BCD1 + 1;
      end
    end
    //---- IS IT DOWN? --------------
    else if (down==1'b1) begin
      if (BCD0 == 4'b0000) begin
        BCD0 <= 4'b1001;
        if (BCD1 == 4'b0000)
          BCD1 <= 4'b1001;
        else
          BCD1 <= BCD1 - 1;
      end
      else
        BCD0 <= BCD0 - 1;
    end
  end

endmodule

7-segment module:

module segment7dec (output reg [6:0] display, input [3:0] bcd);
always @* begin
  case(bcd)
  4'b0000: display = 7'b1111110;
  4'b0001: display = 7'b0110000;
  4'b0010: display = 7'b1101101;
  4'b0011: display = 7'b1111001;
  4'b0100: display = 7'b0110011;
  4'b0101: display = 7'b1011011;
  4'b0110: display = 7'b1011111;
  4'b0111: display = 7'b1110000;
  4'b1000: display = 7'b1111111;
  4'b1001: display = 7'b1111011;
  default: display = 7'b0000000; 
  endcase
  display = ~display; 
end
endmodule

My testbench:

module scoreboard_testbench;

    // Inputs
    reg UP_A;
    reg DOWN_A;
    reg UP_B;
    reg DOWN_B;
    reg Reset;
    reg CLK;

    // Outputs
    wire [6:0] disp1A;
    wire [6:0] disp0A;
    wire [6:0] disp1B;
    wire [6:0] disp0B;

    // Instantiate the Unit Under Test (UUT)
    socreboard_top uut (
        .UP_A(UP_A), 
        .DOWN_A(DOWN_A), 
        .UP_B(UP_B), 
        .DOWN_B(DOWN_B), 
        .Reset(Reset), 
        .CLK(CLK), 
        .disp1A(disp1A), 
        .disp0A(disp0A), 
        .disp1B(disp1B), 
        .disp0B(disp0B)
    );

    initial begin
        // Initialize Inputs
        UP_A = 0;
        DOWN_A = 0;
        UP_B = 0;
        DOWN_B = 0;
        Reset = 1;
        CLK = 0;

        // Wait 100 ns for global reset to finish
        #100;
         Reset = 0;
         UP_A = 1'b1;
        #500
         UP_A='b0;
        #500
         UP_A=1'b1;
        #500
         DOWN_A=1'b1;

        #4000 $finish;
        // Add stimulus here


    end
     always #5 CLK=!CLK;
endmodule

Simulation picture:
Simulation Picture Result-Click Here

Any suggestions?

3

There are 3 answers

2
AudioBubble On

The stimulus you are using is not consistent with how you designed your module to work. The problem is in your testbench. Since this is homework I'll let you take it from there.

EDIT: I'm going to assume that the homework deadline has passed. For the benefit of future readers, note that the Verilog module uses an active-low Clear signal that resets everything when it is at a logic 0. The testbench incorrectly assumes an active-high Reset signal, so Reset (and hence Clear) are being held low for almost the entire testbench. There's no way the Verilog module can do anything useful...it's being continuously cleared.

3
Greg On

General entry level debugging procedure

  1. Always run code in simulation before loading it onto a FPGA.
  2. Determiner which module has a bug(s):
    1. Make sure the stimulus for the module matches your intentions.
    2. Make sure the output for a module makes sense for its input.
  3. Step through line-by-line:
    1. Make sure each branch is reachable and executing as intended.
    2. Dump everything in the debug scope into waveform.
    3. Add debug messages using $display.
    4. Add small delays such as #0.1 into the design. This may require changing the time precision of the time scale.
  4. After the potential bug is found:
    1. Correct it and add a note on the same line with a searchable keyword (ex: //FIXED). Run simulation to validate the fix.
    2. If the bug seems resolved. Comment-out (not remove) the debug messages and injected delays. Run simulation again.
  5. Repeat step 4 until all the bugs are resolved.
  6. It is now safe to remove the commented-out messages and delays.
  7. RUN SIMULATION AGAIN!

Hint:

There is one design bug and one potential test bench issue.

0
Michael Ushakov On

Actually i've already implemented such connection, you could see it in my github project: https://github.com/MossbauerLab/RomChipReader It works not only in simulation but also in hardware (i made short video with demo). You could see my impl of output to 7-seg in https://github.com/MossbauerLab/RomChipReader/blob/master/RomReader/src/address_display.v don't forget to see testbenches also and it is important to use debouncer (https://github.com/MossbauerLab/RomChipReader/blob/master/RomReader/src/debouncer.v) if you are planning to change codes from buttons.