Electrical – Verilog Shift Register with Two Inputs

verilog

I am attempting to create a 32-bit shift register in Verilog with two inputs, DATA0 and DATA1. DATA0 is driven low to input a 0 to the register and DATA1 is driven low to input a 1 to the register. DATA0 and DATA1 are held high when they are not being used.

The issue that I am running into is when I drive DATA0 low, it replaces all of the bits in the register with zeroes. DATA1 works fine, shifting the register and adding a one to the end. My code is as follows:

module shift(
databits,   //The register
reset   ,   // reset Input
DATA0   ,   //Input for a 0
DATA1           //Input for a 1
);

//------------Output Ports--------------
    output [31:0] databits;
//------------Input Ports--------------
     input reset, DATA0, DATA1;
//------------Internal Variables--------
     reg [31:0] databits;
//-------------Code Starts Here-------

always @(posedge reset or negedge DATA0 or negedge DATA1) begin

    if(reset) begin
        databits <= 0;
    end

    //If DATA0 triggered this, write a 0
    else if (~DATA0) begin
        databits <= databits << 1;
    end

    //If DATA1 triggered this, write a 1
    else if (~DATA1) begin
        databits <= { databits[30:0], 1'b1 };
    end

end

endmodule

I tried using DATA0 to also input ones to the register, but it overwrote the entire reigsters with ones. It is my understanding that the always block should execute once when DATA0 goes low, so I do not understand why it is doing this.

Best Answer

As it stands you have a shift register whose clock is both DATA0 and DATA1. This cannot be synthesised as FPGAs don't have dual-clock flip flops.

To make it work you will need two things:

  1. A single clock sufficiently fast to sample the DATA0 and DATA1 signals
  2. Edge detection logic for the DATA0 and DATA1 signals.

Edge detection is a pretty straight forward thing to do:

module fallingEdge (
    input clock,
    input signal,

    output reg edge
);

reg signalDly;

always @ (posedge clock) begin
    signalDly <= signal; //Delay signal by one clock cycle.
    edge <= signalDly && !signal; //If the signal was high in the last cycle but low now, it must be a falling edge
end

endmodule

The output of that block will be high for exactly one clock cycle when there is a falling edge of the data signal.

You will need an edge detector for each of DATA0 and DATA1 which will result in two new signals (say EDGE0 and EDGE1).

Your shift register is then clocked by your 'clock' signal (1), and you simply check the edge signals in that block. If EDGE0 is high, clock in a 0. If EDGE1 is high, clock in a 1. If they are both high at the same time, you'll need to decide whether 0 or 1 takes priority.