verilogcounterupdown

Can't fit settability in counter Verilog


I have written up/down counter and created code for settable starting point. So far so good but I can't think of how to add it to the counter. I have to highlight that I'm completely new to Verilog and similar languages.

//UTILS

reg  [2:0] delay;
wire clock;


reg[3:0] tens;
reg[3:0] units;


wire[5:0] number; 
reg[13:0] shift;    
integer i;


//ASSIGNS
assign number[5:0] = SW[5:0];
assign up = SW[7];
assign start = SW[6];



//PRESCALER
always@ (posedge MCLK)
 begin
    delay <= delay + 1;
 end

assign clock = &delay;


//MAIN COUNTER 
always@ (posedge clock)
begin
     if (start)
        begin
            if (up) //going up
                begin
                    if (units == 4'd3 && tens == 4'd6)
                        begin       //63 reached
                            units <= 0;
                            tens <=0;
                        end
                    if (units==4'd9) 
                       begin        //x9 reached                
                            units <= 0;
                            tens <= tens + 1;
                       end
                    else
                        units <= units + 1; //typical case
                end
            else    //goin down
                begin
                    if (units == 4'd0)      
                        if ( tens ==4'd0)   //00 reached back to 63
                            begin
                                units <= 4'd3;
                                tens <= 4'd6;
                            end
                        else
                            begin           //x0 reached
                                tens <= tens-1;
                                units <= 4'd9;
                            end
                    else
                        begin               //typical case
                            units <= units -1;
                        end
                end
        end 
end             //MAIN COUNTER END  

Here I don't know how to merge this two pieces, I would love to have it like this if start always@ posedge clock /counting/ else /* change number nearly functionally(immediately when change occurs)*/

Adding it into if(start) else seems to do the work but only on positive edge of quite low frequency clock. As far as I know i can't use one reg in two different ALWAYS@.

 /* // Clear previous number and store new number in shift register
          shift[13:6] = 0;
          shift[5:0] = number;

          //BINARY TO BCD                               
          for (i=0; i<6; i=i+1) 
            begin
                 if (shift[9:6] >= 5)
                    shift[9:6] = shift[9:6] + 3;

                 if (shift[13:10] >= 5)
                    shift[13:10] = shift[13:10] + 3;
                 shift = shift << 1; 
            end
        units <=  shift[9:6];
        tens <= shift[13:10];

*/

dek7seg Is 7-segment display which is 100% fine (professor's code).

dek7seg ss1(
 .bits(units[3:0]),
 .seg(DISP1[6:0])
);

dek7seg ss10(
 .bits(tens[3:0]),
 .seg(DISP2[6:0])
);



endmodule

Solution

  • You are using a derived clock to control your MAIN COUNTER. Instead use the main clock MCLK and use the logic for delay as a conditional statement.

    Since you want store an new values on the change of number, then you will need to store the the previous number value and compare.

    Based on your description, your code should look something like this:

    //MAIN COUNTER 
    always@ (posedge MCLK)
    begin
      if (start && &delay)
      begin
          /* your up/down logic here */
      end
      else if (number != prev_number)
      begin // Clear previous number and store new number
        prev_number <= number;
        units <= new_units;
        tens  <= new_tens;
      end
    end
    
    // Calculate new units and tens from number
    always @* begin
      shift[13:6] = 0;
      shift[5:0] = number;
    
      //BINARY TO BCD                               
      for (i=0; i<6; i=i+1) begin
        if (shift[9:6] >= 5)
          shift[9:6] = shift[9:6] + 3;
    
        if (shift[13:10] >= 5)
          shift[13:10] = shift[13:10] + 3;
    
        shift = shift << 1; 
      end
    
      new_units = shift[9:6];
      new_tens  = shift[13:10];
    end