system-verilogflip-flop

How to make 4 bit ring counter with 4 flip flops?


I have this 4 bit ring counter that I'm trying to make, and I feel like I'm so close, but I can't figure out how to make one input depend on the previous state's output. Here's what I have:

`default_nettype none
// Empty top module

module top (
  // I/O ports
  input  logic hz100, reset,
  input  logic [20:0] pb,
  output logic [7:0] left, right
);

  // Your code goes here...
  q[3:0];
  
  assign q[3:0] = right[3:0];
  
  hc74_set setFF(.c(pb[0]), .d(pb[1]), .q(right[0]), .sn(pb[16]));
  hc74_reset resetFF1(.c(pb[0]), .d(pb[1]), .q0(right[1]), .rn(pb[16]));
  hc74_reset resetFF2(.c(pb[0]), .d(pb[1]), .q1(right[2]), .rn(pb[16]));
  hc74_reset resetFF3(.c(pb[0]), .d(pb[1]), .q2(right[3]), .rn(pb[16]));
  
  
endmodule

// Add more modules down here...
// This is a single D flip-flop with an active-low asynchronous set (preset).
// It has no asynchronous reset because the simulator does not allow it.
// Other than the lack of a reset, it is half of a 74HC74 chip.
module hc74_set(input logic d, c, sn,
                  output logic q, qn);
  assign qn = ~q;
  always_ff @(posedge c, negedge sn)
    if (sn == 1'b0)
      q <= 1'b1;
    else
      q <= d;
endmodule

// This is a single D flip-flop with an active-low asynchronous reset (clear).
// It has no asynchronous set because the simulator does not allow it.
// Other than the lack of a set, it is half of a 74HC74 chip.

module hc74_reset(input logic d, c, rn,
                  output logic q, qn);
  assign qn = ~q;
  always_ff @(posedge c, negedge rn)
    if (rn == 1'b0)
      q <= 1'b0;
    else
      q <= d;
endmodule

This is on an FPGA simulator, which is why there are a few things like pb (these are push buttons) and left, right outputs which are sets of 8 LEDs each.


Solution

  • Let's first make sure we are on the same page

    Based on wikipedia description of a ring counter

    This could be implemented as follows:

    module top (
      // I/O ports
      input  logic reset_n,
      input  logic clk,
      output logic [3:0] ring
    );
    
      // Your code goes here...
      always @(posedge clk or negedge reset_n) begin
        if(~reset_n) begin
          ring = 4'b0001;
        end
        else begin
          ring[0] <= ring[3];
          ring[1] <= ring[0];
          ring[2] <= ring[1];
          ring[3] <= ring[2];
        end
      end
    endmodule
    
    

    The output ring is a 4-bit one hot vector, reset_n = 0 makes ring = 0001 every clock with reset_n = 1 rolls the ring to the right, [0001, 0010, 0100, 1000, 0001, ...].

    But you want to use instances of the flops you defined. Notice that in an assignment a <= b, a is the output of the flop (q port), and b is the input of the flop (d port).

    module top (
      // I/O ports
      input  logic reset_n,
      input  logic clk,
      output logic [3:0] ring
    );
    
      // Your code goes here...
      
      hc74_set setFF(.c(clk), .d(ring[3]), .q(ring[0]), .sn(reset_n));
      hc74_reset resetFF1(.c(clk), .d(ring[0]), .q0(ring[1]), .rn(reset_n));
      hc74_reset resetFF2(.c(clk), .d(ring[1]), .q1(ring[2]), .rn(reset_n));
      hc74_reset resetFF3(.c(clk), .d(ring[2]), .q2(ring[3]), .rn(reset_n));  
    endmodule
    
    

    You have to connect the ports accordingly, I just used clk for the clock and reset_n for the negated reset signal.