Verilog HDL code work

profileboboboom
FIFOmemorysystem.docx

Implementation of FIFO memory system with verilog memory declaration:

The size of the FIFO buffer greatly depends on the number of address bits. As the number of words in fifo = 2^(number of address bits). The FIFO I will be coding here will consist of 16 memory elements ( 4 bits in each memory element and 3 address bits). This can be easily changed by changing the parameters in the code, by doing so you can create a buffer of any size. The parameters can be changed from the following line:

odule

module fifo # (parameter abits = 4, dbits = 3)

At reset the empty flag is set to high whereas the full flag is set to low to allow new data to be written. The positions of the read and write pointers are also initialized to 0. The verilog code is shown below. It has been commented in detail so I hope each step is clear.

module fifo # (parameter abits = 4, dbits = 3)(

    input clock,

    input reset,

    input wr,

    input rd,

  input [dbits-1:0] din,

    output empty,

    output full,

  output [dbits-1:0] dout

    );

wire db_wr, db_rd;

reg dffw1, dffw2, dffr1, dffr2;

reg [dbits-1:0] out;

always @ (posedge clock) dffw1 <= wr;

always @ (posedge clock) dffw2 <= dffw1;

assign db_wr = ~dffw1 & dffw2; //monostable multivibrator to detect only one pulse of the button

always @ (posedge clock) dffr1 <= rd;

always @ (posedge clock) dffr2 <= dffr1;

assign db_rd = ~dffr1 & dffr2; //monostable multivibrator to detect only one pulse of the button

reg [dbits-1:0] regarray[2**abits-1:0]; //number of words in fifo = 2^(number of address bits)

reg [abits-1:0] wr_reg, wr_next, wr_succ; //points to the register that needs to be written to

reg [abits-1:0] rd_reg, rd_next, rd_succ; //points to the register that needs to be read from

reg full_reg, empty_reg, full_next, empty_next;

assign wr_en = db_wr & ~full; //only write if write signal is high and fifo is not full

//always block for write operation

always @ (posedge clock)

begin

  if(wr_en)

   regarray[wr_reg] <= din; //at wr_reg location of regarray store what is given at din

end

  

//always block for read operation

always @ (posedge clock)

begin

  if(db_rd)

   out <= regarray[rd_reg];

end

always @ (posedge clock or posedge reset)

begin

  if (reset)

   begin

   wr_reg <= 0;

   rd_reg <= 0;

   full_reg <= 1'b0;

   empty_reg <= 1'b1;

   end

else

   begin

   wr_reg <= wr_next; //created the next registers to avoid the error of mixing blocking and non blocking assignment to the same signal

   rd_reg <= rd_next;

   full_reg <= full_next;

   empty_reg <= empty_next;

   end

end

always @(*)

begin

  wr_succ = wr_reg + 1; //assigned to new value as wr_next cannot be tested for in same always block

  rd_succ = rd_reg + 1; //assigned to new value as rd_next cannot be tested for in same always block

  wr_next = wr_reg; //defaults state stays the same

  rd_next = rd_reg; //defaults state stays the same

  full_next = full_reg; //defaults state stays the same

  empty_next = empty_reg; //defaults state stays the same

   

   case({db_wr,db_rd})

    //2'b00: do nothing LOL..

     

    2'b01: //read

     begin

      if(~empty) //if fifo is not empty continue

       begin

        rd_next = rd_succ;

        full_next = 1'b0;

       if(rd_succ == wr_reg) //all data has been read

         empty_next = 1'b1; //its empty again

       end

     end

     

    2'b10: //write

     begin

       

      if(~full) //if fifo is not full continue

       begin

        wr_next = wr_succ;

        empty_next = 1'b0;

        if(wr_succ == (2**abits-1)) //all registers have been written to

         full_next = 1'b1;   //its full now

       end

     end

      

    2'b11: //read and write

     begin

      wr_next = wr_succ;

      rd_next = rd_succ;

     end

     //no empty or full flag will be checked for or asserted in this state since data is being written to and read from together it can not get full in this state.

    endcase

e

module fifo # (parameter abits = 4, dbits = 3)

At reset the empty flag is set to high whereas the full flag is set to low to allow new data to be written. The positions of the read and write pointers are also initialized to 0. The verilog code is shown below. It has been commented in detail so I hope each step is clear.

module fifo # (parameter abits = 4, dbits = 3)(

    input clock,

    input reset,

    input wr,

    input rd,

  input [dbits-1:0] din,

    output empty,

    output full,

  output [dbits-1:0] dout

    );

wire db_wr, db_rd;

reg dffw1, dffw2, dffr1, dffr2;

reg [dbits-1:0] out;

always @ (posedge clock) dffw1 <= wr;

always @ (posedge clock) dffw2 <= dffw1;

assign db_wr = ~dffw1 & dffw2; //monostable multivibrator to detect only one pulse of the button

always @ (posedge clock) dffr1 <= rd;

always @ (posedge clock) dffr2 <= dffr1;

assign db_rd = ~dffr1 & dffr2; //monostable multivibrator to detect only one pulse of the button

reg [dbits-1:0] regarray[2**abits-1:0]; //number of words in fifo = 2^(number of address bits)

reg [abits-1:0] wr_reg, wr_next, wr_succ; //points to the register that needs to be written to

reg [abits-1:0] rd_reg, rd_next, rd_succ; //points to the register that needs to be read from

reg full_reg, empty_reg, full_next, empty_next;

assign wr_en = db_wr & ~full; //only write if write signal is high and fifo is not full

//always block for write operation

always @ (posedge clock)

begin

  if(wr_en)

   regarray[wr_reg] <= din; //at wr_reg location of regarray store what is given at din

end

  

//always block for read operation

always @ (posedge clock)

begin

  if(db_rd)

   out <= regarray[rd_reg];

end

always @ (posedge clock or posedge reset)

begin

  if (reset)

   begin

   wr_reg <= 0;

   rd_reg <= 0;

   full_reg <= 1'b0;

   empty_reg <= 1'b1;

   end

else

   begin

   wr_reg <= wr_next; //created the next registers to avoid the error of mixing blocking and non blocking assignment to the same signal

   rd_reg <= rd_next;

   full_reg <= full_next;

   empty_reg <= empty_next;

   end

end

always @(*)

begin

  wr_succ = wr_reg + 1; //assigned to new value as wr_next cannot be tested for in same always block

  rd_succ = rd_reg + 1; //assigned to new value as rd_next cannot be tested for in same always block

  wr_next = wr_reg; //defaults state stays the same

  rd_next = rd_reg; //defaults state stays the same

  full_next = full_reg; //defaults state stays the same

  empty_next = empty_reg; //defaults state stays the same

   

   case({db_wr,db_rd})

    //2'b00: do nothing LOL..

     

    2'b01: //read

     begin

      if(~empty) //if fifo is not empty continue

       begin

        rd_next = rd_succ;

        full_next = 1'b0;

       if(rd_succ == wr_reg) //all data has been read

         empty_next = 1'b1; //its empty again

       end

     end

     

    2'b10: //write

     begin

       

      if(~full) //if fifo is not full continue

       begin

        wr_next = wr_succ;

        empty_next = 1'b0;

        if(wr_succ == (2**abits-1)) //all registers have been written to

         full_next = 1'b1;   //its full now

       end

     end

      

    2'b11: //read and write

     begin

      wr_next = wr_succ;

      rd_next = rd_succ;

     end

     //no empty or full flag will be checked for or asserted in this state since data is being written to and read from together it can not get full in this state.

    endcase

end

assign full=full_reg;

assign empty=empty_reg;

assign dout=out;

endmodule

--------------------------------------------------------

FIFO code with enqueue and dequeue commands:

#include<stdio.h>

#define SIZE 5

void enQueue(int);

void deQueue();

void display();

int items[SIZE],front=-1,rear=-1;

int main()

{

//deQueue is not possible in empty queue.

deQueue();

//enQueue 5 elements

enQueue(1);

enQueue(2);

enQueue(3);

enQueue(4);

enQueue(5);

//6th element can't be added to queue because queue is full

enQueue(6);

display();

//deQueue removes element entered first i.e. 1

deQueue();

//Now we have just 4 elements

display();

return 0;

}

void enQueue(int value){

if(rear == SIZE-1)

printf("\nQueue is Full!!");

else {

if(front == -1)

front = 0;

rear++;

items[rear] = value;

printf("\nInserted -> %d", value);

}

}

void deQueue(){

if(front == -1)

printf("\nQueue is Empty!!");

else{

printf("\nDeleted : %d", items[front]);

front++;

if(front > rear)

front = rear = -1;

}

}

void display(){

if(rear == -1)

printf("\nQueue is Empty!!!");

else{

int i;

printf("\nQueue elements are:\n");

for(i=front; i<=rear; i++)

printf("%d\t",items[i]);

}

}