`timescale 1 ns/100 ps
// Behavioral description of FIFO with:
// active high write enable
// active high read  enable
// active low asynchronous clear
// rising edge clock
// active high full  flag
// active low  empty flag

module reg_fifo (Data, Q, Aclr, Clock, WE, RE, FF, EF);

parameter width = 8;
parameter depth = 8;
parameter addr  = 3;

input Clock, WE, RE, Aclr;
input [width-1:0] Data;
output FF, EF; //Full & Empty Flags
output [width-1:0] Q;
reg    [width-1:0] Q;
reg    [width-1:0] mem_data [depth-1:0];
reg    [addr -1:0] WAddress, RAddress;
reg    FF, EF;

// Write functional section
always @ (posedge Clock or negedge Aclr)
begin
  if(!Aclr)
    WAddress = #2 0;
  else if(WE)
    WAddress = #2 WAddress + 1;
end

// Write reg
always @ (posedge Clock)
begin
  if(WE)
    mem_data[WAddress] = Data;
end

// Read functional section
always @ (posedge Clock or negedge Aclr)
begin
  if(!Aclr)
    RAddress = #1 0;
  else if (RE)
    RAddress = #1 RAddress + 1;
end

// Read reg
always @ (posedge Clock)
begin
  if(RE)
    Q = mem_data[RAddress];
end

// Full Flag
always @ (posedge Clock or negedge Aclr)
begin
  if(!Aclr)
    FF = #1 1'b0;
  else if
  (
    (WE & !RE) && //Write operation
      ( //Next cycle is full 
        (WAddress == RAddress-1) || 
        ( (WAddress == depth-1) && (RAddress == 1'b0) )
      )
  )
    FF = #1 1'b1;
  else
    FF = #1 1'b0;
end

// Empty Flag
always @ (posedge Clock or negedge Aclr)
begin
  if(!Aclr)
    EF = #1 1'b0;
  else if
  (
    (!WE & RE) && //Read operation
      ( //Next cycle is empty 
        (WAddress == RAddress+1) || 
        ( (RAddress == depth-1) && (WAddress == 1'b0) )
      )
  )
    EF = #1 1'b0;
  else
    EF = #1 1'b1;
end

endmodule



[ [ [ 'module',
      'reg_fifo',
      '(',
      [['Data'], ['Q'], ['Aclr'], ['Clock'], ['WE'], ['RE'], ['FF'], ['EF']],
      ')',
      ';'],
    [ ['parameter', ['width', '=', '8'], ';'],
      ['parameter', ['depth', '=', '8'], ';'],
      ['parameter', ['addr', '=', '3'], ';'],
      ['input', 'Clock', 'WE', 'RE', 'Aclr', ';'],
      ['input', '[', ['width'], '-', '1', ':', '0', ']', 'Data', ';'],
      ['output', 'FF', 'EF', ';'],
      ['output', '[', ['width'], '-', '1', ':', '0', ']', 'Q', ';'],
      ['reg', '[', ['width'], '-', '1', ':', '0', ']', ['Q'], ';'],
      [ 'reg',
        '[',
        ['width'],
        '-',
        '1',
        ':',
        '0',
        ']',
        ['mem_data', '[', ['depth'], '-', '1', ':', '0', ']'],
        ';'],
      [ 'reg',
        '[',
        ['addr'],
        '-',
        '1',
        ':',
        '0',
        ']',
        ['WAddress'],
        ['RAddress'],
        ';'],
      ['reg', ['FF'], ['EF'], ';'],
      [ 'always',
        ['@', '(', ['posedge', ['Clock'], 'negedge', ['Aclr']], ')'],
        [ 'begin',
          [ [ 'if',
              ['(', '!', ['Aclr'], ')'],
              [[['WAddress'], '=', ['#', '2'], '0'], ';'],
              'else',
              [ 'if',
                ['(', ['WE'], ')'],
                [ [['WAddress'], '=', ['#', '2'], ['WAddress'], '+', '1'],
                  ';']]]],
          'end']],
      [ 'always',
        ['@', '(', ['posedge', ['Clock']], ')'],
        [ 'begin',
          [ [ 'if',
              ['(', ['WE'], ')'],
              [[['mem_data', ['[', ['WAddress'], ']']], '=', ['Data']], ';']]],
          'end']],
      [ 'always',
        ['@', '(', ['posedge', ['Clock'], 'negedge', ['Aclr']], ')'],
        [ 'begin',
          [ [ 'if',
              ['(', '!', ['Aclr'], ')'],
              [[['RAddress'], '=', ['#', '1'], '0'], ';'],
              'else',
              [ 'if',
                ['(', ['RE'], ')'],
                [ [['RAddress'], '=', ['#', '1'], ['RAddress'], '+', '1'],
                  ';']]]],
          'end']],
      [ 'always',
        ['@', '(', ['posedge', ['Clock']], ')'],
        [ 'begin',
          [ [ 'if',
              ['(', ['RE'], ')'],
              [[['Q'], '=', ['mem_data', ['[', ['RAddress'], ']']]], ';']]],
          'end']],
      [ 'always',
        ['@', '(', ['posedge', ['Clock'], 'negedge', ['Aclr']], ')'],
        [ 'begin',
          [ [ 'if',
              ['(', '!', ['Aclr'], ')'],
              [[['FF'], '=', ['#', '1'], "1 'b 0"], ';'],
              'else',
              [ 'if',
                [ '(',
                  '(',
                  [['WE'], '&', '!', ['RE']],
                  ')',
                  '&&',
                  '(',
                  [ '(',
                    [['WAddress'], '==', ['RAddress'], '-', '1'],
                    ')',
                    '||',
                    '(',
                    [ '(',
                      [['WAddress'], '==', ['depth'], '-', '1'],
                      ')',
                      '&&',
                      '(',
                      [['RAddress'], '==', "1 'b 0"],
                      ')'],
                    ')'],
                  ')',
                  ')'],
                [[['FF'], '=', ['#', '1'], "1 'b 1"], ';'],
                'else',
                [[['FF'], '=', ['#', '1'], "1 'b 0"], ';']]]],
          'end']],
      [ 'always',
        ['@', '(', ['posedge', ['Clock'], 'negedge', ['Aclr']], ')'],
        [ 'begin',
          [ [ 'if',
              ['(', '!', ['Aclr'], ')'],
              [[['EF'], '=', ['#', '1'], "1 'b 0"], ';'],
              'else',
              [ 'if',
                [ '(',
                  '(',
                  ['!', ['WE'], '&', ['RE']],
                  ')',
                  '&&',
                  '(',
                  [ '(',
                    [['WAddress'], '==', ['RAddress'], '+', '1'],
                    ')',
                    '||',
                    '(',
                    [ '(',
                      [['RAddress'], '==', ['depth'], '-', '1'],
                      ')',
                      '&&',
                      '(',
                      [['WAddress'], '==', "1 'b 0"],
                      ')'],
                    ')'],
                  ')',
                  ')'],
                [[['EF'], '=', ['#', '1'], "1 'b 0"], ';'],
                'else',
                [[['EF'], '=', ['#', '1'], "1 'b 1"], ';']]]],
          'end']]],
    'endmodule']]
