-1
\$\begingroup\$

I am currently working through FPGA4FUN's tutorial on quadrature decoding using an FPGA. I am currently just trying to simulate the decoders behavior by using a testbench that essentially drives the A and B inputs of the encoder high and low (out of phase) jsut like a normal encoder would. I am new to Verilog, and have a question about the following code:

module quad(clk, quadA, quadB, count);
input clk, quadA, quadB;
output [7:0] count;
reg [7:0] count = 8'b00000000;

reg [2:0] quadA_delayed;
reg [2:0] quadB_delayed;


always @(posedge clk) quadA_delayed <= {quadA_delayed[1:0], quadA};
always @(posedge clk) quadB_delayed <= {quadB_delayed[1:0], quadB};

wire count_enable = quadA_delayed[1] ^ quadA_delayed[2] ^ quadB_delayed[1] ^ quadB_delayed[2];
wire count_direction = quadA_delayed[1] ^ quadB_delayed[2];

always @(posedge clk) begin
  if(count_enable)
  begin
    if(count_direction) count<=count+1; else count<=count-1;
  end
end


endmodule

This was recommended by FPGA4FUN because it is asynchronous, so the encoder doesn't have tot ick in sync with the clock - which is realistic. However, I notice something strange in the code. the reg [2:0] QuadA_delayed is not initialized. input quadA is coming from the encoder itself. We then have this statement:

always @(posedge clk) quadA_delayed <= {quadA_delayed[1:0], quadA};

What is the value of quadA_delayed[1:0]? Since the first bit is not initialized, it is currently just floating, and thus the rest of the variables in the code will not be determinable. This is seen on my waveform, as I get just a bunch of x's. I was wondering if anyone knows how I should initiliaze this, and why I need it. FPGA4FUN offers two examples for quadrature decoding. The first one is synchronous, and I managed to get that working. However, I can't get the asynchronous one working due to this quadA_delayed being 2 bits and having an undetermined bit.

To add extra information, I have attached what the circuit diagram looks like.enter image description here

Any help would be greatly appreciated.

Thanks

Here is my testbench for reference:

`timescale 1 ns/10 ps

module testbench;
    
    reg clk, quadA, quadB;
    wire [7:0] count ;

    quad dut(.clk(clk),.quadA(quadA),.quadB(quadB),.count(count));
    
    initial begin
        clk = 0;
        forever begin
        #5
        clk = ~clk;
        end
    end
    
    initial begin
    
    #10;
    quadA = 1'b0;
    quadB = 1'b0;
    #5
    quadA = 1'b1;
    #5
    quadB = 1'b1;
    #5
    quadA = 1'b0;
    #5
    quadB = 1'b0;
    #5
    quadA = 1'b1;
    #5
    quadB = 1'b1;
    #5
    quadA = 1'b0;
    #5
    quadB = 1'b0;
    #5
    quadA = 1'b1;
    #5
    quadB = 1'b1;
    #5
    quadA = 1'b0;
    #5
    quadB = 1'b0;
    #5
    quadA = 1'b1;
    #5
    quadB = 1'b1;
    #5
    quadA = 1'b0;
    #5
    quadB = 1'b0;
    #5
    quadA = 1'b1;
    #5
    quadB = 1'b1;
    #5
    quadA = 1'b0;
    #5
    quadB = 1'b0;
    #5
    quadA = 1'b1;
    #5
    quadB = 1'b1;
    /*
    quadA = 1'b0;
    //quadB = 1'b1;
    #10
    quadA = 1'b1;
    //quadB = 1'b0;
    */
    #10
    $finish;
    end

endmodule

Edit 2:

I have somehow managed to get the counter incrementing now. I simply increased the timing interval in the testbench to 15 as opposed to 5. Thus quadA and quadB were held high and low for 3 times as long. There is still some weird behaviour, where the counter seems to lose track for 4 or 5 clock cyles, and then gets back on track. I also don't know why holding the signals for longer makes a difference, and whether or not this is a realistic simulation of a real encoder.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

As you show in your circuit diagram, the line always @(posedge clk) quadA_delayed <= {quadA_delayed[1:0], quadA}; describes a shift register with 3 bits. As it mentions in the tutorial, this is there to prevent metastability in cases where the external async input violates setup and hold times. Since there is no reset line coming into the module, there is no way for quadA_delayed to have an initialization value, since there is no indication of when the initial value should be loaded into the shift register. So for the first 3 clock pulses, uninitialized values will be present in quadA_delayed. However, after that time has passed your waveform should show valid data.

\$\endgroup\$
9
  • \$\begingroup\$ Hi Don, thanks for the comment, I have edited my original post to include the testbench I wrote for this verilog. Unfortunately I cannot get the counter to increment, despite setting the quadA and quadB signals high and low out of phase with each other. Do you have any thoughts? \$\endgroup\$ Oct 11, 2021 at 0:45
  • \$\begingroup\$ Looking at the verilog again, your counter does not have an initial value so any time it is incremented or decremented it stays as an uninitialized value. The only way to correct this is to add a reset line to the module that initializes count to 0. \$\endgroup\$
    – Don
    Oct 11, 2021 at 2:54
  • \$\begingroup\$ That makes sense, but is the counter not initialized when I do reg[7:0] counter = 8’b00000000 \$\endgroup\$ Oct 11, 2021 at 4:29
  • \$\begingroup\$ Some body mentioned that using = on my wires is not good for continuous assignment. So instead of using “wire_count_direction = “ I should use an assign statement so that the value is continuously updated. However, I am not sure this is correct \$\endgroup\$ Oct 11, 2021 at 4:31
  • \$\begingroup\$ Assign is used outside of always blocks, and = is used inside always blocks when modeling combinational logic using flow control syntax (switch, if, else, etc...). Either way, count is a register and can't be assigned to continuously, which is why the counter isn't initialized in your example. I haven't tested this code but I think it will work and it shows the idea behind using a reset for the counter. Note that this still allows the inputs to change asynchronously to the clock. gist.github.com/DonDrews/cd14d55def2f3abf6d5aed5ac0b41703 \$\endgroup\$
    – Don
    Oct 11, 2021 at 15:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.