Saturday, May 2, 2020

Stack or LIFO Verilog Code

The Last In First Out (LIFO) or Stack is a data arrangement structure in which the data that enters the last is the one that is removed first. Let us see how to implement the concept of Stack using Verilog.


For a normal memory, we provide the address for reads and writes. But here we know where to write and what to read for stack operation. So address is not required to access a stack location.

Procedure to implement stack:
  1. Create a normal memory in Verilog.
  2. When the data and push signal is given, write to the memory starting from first address.
  3. When pop signal is given, read from the memory from last written address.
  4. When stack becomes empty, assert empty and if it becomes full, assert full signal.
We just require one index variable (internal variable) to control a stack because we are writing to and reading from the same address. However this is not the case for FIFO.

Verilog Code Logic:
  1. Use a variable index to point to the memory location to read or write.
  2. During push signal, write to the memory and increment index.
  3. During pop, read from the memory from last written memory index and decrement index.
  4. Empty occurs when index equals 0.
  5. Full occurs when index equals depth.
For empty and full, I have used  a shortcut logic to perform comparison as == operator will realize more hardware. 

Verilog Code:

module Stack(
 clk,
 rstn,
 pop,
 push,
 empty,
 full,
 din,
 dout
    );

parameter WIDTH = 8;
parameter DEPTH = 8;

input clk;
input rstn;
input pop;
input push;
input [WIDTH-1:0]din;

output [WIDTH-1:0]dout;
output empty;
output full;

reg [WIDTH-1:0]stack[DEPTH-1:0]; //memory
reg [WIDTH-1:0]index, next_index; 
reg [WIDTH-1:0]dout, next_dout;

wire empty, full;

always @ (posedge clk) //Sequential block
begin
  if(!rstn)
  begin
    dout  <= 8'd0;
    index <= 1'b0;
  end
  else
  begin
    dout  <= next_dout;
    index <= next_index;
  end
end

assign empty = !(|index);
assign full  = !(|(index ^ DEPTH));

always @ (*) //Combinational Block
begin
  if(push) //write
  begin
  stack[index] = din;
  next_index   = index+1'b1;
  end
  else if(pop)  //read
  begin
  next_dout  = stack[index-1'b1];
  next_index = index-1'b1;
  end
  else
  begin
  next_dout  = dout;
  next_index = index;
  end
 
end
endmodule

Testbench:


module Stack_tb;

 // Inputs
 reg clk;
 reg rstn;
 reg pop;
 reg push;
 reg [7:0] din;

 // Outputs
 wire empty;
 wire full;
 wire [7:0] dout;

 // Instantiate the Unit Under Test (UUT)
 Stack uut (
  .clk(clk), 
  .rstn(rstn), 
  .pop(pop), 
  .push(push), 
  .empty(empty), 
  .full(full), 
  .din(din), 
  .dout(dout)
 );

 always #5 clk = ~clk;
 
 task reset();  //reset task
 begin
 clk = 1'b1;
 rstn = 1'b0;
 pop = 1'b0;
 push = 1'b0;
 din = 8'd0;
 #30 rstn = 1'b1;
 end
 endtask

 task read_stack();  //read task
 begin
 pop = 1'b1;
 #10
 pop = 1'b0;
 end
 endtask
   
 task write_stack([7:0]din_tb); //write task
 begin
 push = 1'b1;
 din = din_tb;
 #10 push = 1'b0;
 end
 endtask
  
  // Main code
 initial
 begin
 reset();
 #10;
 repeat(2)
 begin
 write_stack(8'h11);
 #10;
 write_stack(8'h22);
 #10;
 write_stack(8'h33);
 #10;
 write_stack(8'h44);
 #40;
 end
 read_stack();
 #20;
 read_stack();
 #20;
 write_stack(8'hAA);
 #10;
 write_stack(8'hBB);
 #40;
 read_stack();
 #20;
 $finish;
 end
      
endmodule

Simulation Result:

Stack/LIFO simulation waveform





From the simulation result,
  1. We see that the Stack is initially empty as there is no data.
  2. Data is pushed into it until it becomes full.
  3. Two data are popped and then two data are pushed again to make it full again
Thus we have verified the basic operation of a stack.

7 comments:

  1. Hello, Thank you for the article. Could you please elaborate more on the shortcut you used for empty and full signal?

    ReplyDelete
    Replies
    1. Hello,
      empty = (!(|index);
      Here, we OR each bit of index whose result will be 0 only if all bits are zero. Invert it to make it 1 and assign to empty.

      For the full case, EXOR result will be 0 when both variables are equal. So invert and assign to full.

      Delete
    2. Thank you so much :)

      Delete
  2. hello can i get the algorithm and complete logic of the code
    plzzzz.

    ReplyDelete
    Replies
    1. Hi, I have mentioned the logic of the code on top. Can help if any portion is not clear.

      Delete
  3. i want to know how many bytes or word this stack program

    ReplyDelete
    Replies
    1. The stack is configured as WIDTH=8 (8-bit data) and DEPTH=8 (8 locations).
      It can be modified as per requirement during instantiation.

      Delete