Contador arriba-abajo sin envoltura

0

Estoy intentando implementar un contador ascendente y descendente síncrono en verilog con las siguientes reglas:

  • El contador solo cambia en el flanco ascendente del reloj
  • Cuando se restablece = 1, el conteo pasa a 00, operación normal cuando se restablece = 0
  • el conteo está habilitado cuando en = 1 y deshabilitado cuando en = 0 cuenta hacia arriba cuando dir = 0 cuenta hacia atrás cuando dir = 1
  • el conteo NO se ajusta. Cuando se realiza una cuenta regresiva, NO va de 00 a 11 (es decir, se mantiene en 00). Al contar, NO va de 11 a 00 (es decir, se mantiene en 11)

Hasta ahora mi código es:

module counter
(
    input               clock,
    input               reset,
    input               en,
    input               dir,
    output reg [1:0]    count
);

  always @ (posedge clock) begin
    if (reset==1'b1 || en==1'b0) begin 
      count=2'b0; 
    end

    else if(en==1 && dir==0) begin //up count when dir=0
      count <= count+1;
    end

    else begin //down count when dir=1
      count <=count-1; 
    end

  end

endmodule

Esto lo hace todo, excepto los envoltorios de conteo. ¿Cómo lo haría no envolver?

Testbench a continuación (los comentarios dicen lo que debería estar haciendo el código)

'timescale 1 ns / 1 ns    // Time for each step, time precision
'define CLOCK_PERIOD        10

module main;          
    reg         clock;      // Free running clock
    reg         reset;      // Input - reset
    reg         en;         // Input - enable counting
    reg         dir;        // Input - direction (0=up)
    wire [1:0]  count;      // Output - Counter output

    // Instantiate module
    counter    u1( clock, reset, en, dir, count );

    initial                 // Done once at start up 
    begin
        $display( "Up/Down Counter (no wrap)" );
        $dumpfile( "dump.vcd" ); 
        $dumpvars;

        // Set initial values for inputs, asset reset
        clock = 0;          
        reset = 1;              
        en = 0;
        dir = 0;

        // Turn off reset after one clock
        #('CLOCK_PERIOD * 1)
        reset = 0;

        // Wait for a while to make sure it does not count
        #('CLOCK_PERIOD * 2)

        // Assert enable, should count up to 3 and stop
        en = 1;
        #('CLOCK_PERIOD * 5)

        // Make sure does not count if we now deassert enable
        en = 0;
        #('CLOCK_PERIOD * 2)

        // Set dir=1 but en=0, so should not change
        dir = 1;
        #('CLOCK_PERIOD * 2)

        // Now enable, should count down and stop at 0
        en = 1;

        // Count back down, check if reset is ignored if not asserted 
        // at a clock edge
        dir=1;
        #7
        reset = 1;
        #6
        reset = 0;

        #('CLOCK_PERIOD * 5)
        reset = 0;

        // Leave time to stabilize
        #('CLOCK_PERIOD * 4)
        $finish;
   end
    
pregunta tlb

1 respuesta

3

No envolver es simplemente una cuestión de agregar controles para ver si se envuelven, e inhibir el conteo en ese caso:

module counter
(
    input               clock,
    input               reset,
    input               en,
    input               dir,
    output reg [1:0]    count
);

  always @ (posedge clock) begin
    if (reset == 1'b1) begin 
      count <= 2'b0; 
    end else if (en == 1'b1) begin
      if (dir == 0) begin
        // up count when dir=0 AND count < max value (all ones)
        if (count != 2'b11) count <= count + 1;
      end else begin
        // down count when dir=1 AND count > min value (all zeros)
        if (count != 2'b00) count <= count - 1;
      end
    end
  end

endmodule

P.S. No estoy seguro de por qué restableciste count cuando en == 0 , así que lo he eliminado aquí.

    
respondido por el Dave Tweed

Lea otras preguntas en las etiquetas