Guest User

Untitled

a guest
Mar 26th, 2020
307
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VeriLog 10.18 KB | None | 0 0
  1. //--------------------------------------------------------------------------
  2. //
  3. // $Id: $
  4. //
  5. // $Change: $
  6. //
  7. // Notes:     This module is the control logic for a Virage RAM FIFO. It has
  8. //            a 3 cycle we -> ~empty latency. This block works with the Virage
  9. //            RAMs that have both inputs, outputs, and outreg_enable signale
  10. //            pipelined internal to the RAM. There is a SKID rank of flops and
  11. //            an output mux to account for the outreg_enable signal being
  12. //            pipelined. It is important to realize the output timing of this
  13. //            block is CLK->Q + MUX delay.
  14. //        ,
  15. //            FIFO_*, SKID_WORDS, and SKID_FULL are the parameters which
  16. //            are user adjustable. SKID_WORDS is the number of SKID entries
  17. //            in the FIFO. SKID_FULL says whether or not the FULL signal should
  18. //            de-assert if the FIFO has entered the SKID entries, but is being
  19. //            read from. Setting SKID_WORDS=0 and SKID_FULL=0 causes this module
  20. //            to act as a FIFO without any SKID entries. This is the default.  
  21. //
  22. // Copyright: Trade secret of ATI Technologies, Inc.
  23. //            (C) Copyright 2001-2005, ATI Technologies, Inc., (unpublished)
  24. //
  25. //        All rights reserved.  This notice is intended as a precaution against
  26. //        inadvertent publication and does not imply publication or any waiver
  27. //        of confidentiality.  The year included in the foregoing notice is the
  28. //        year of creation of the work.
  29. //
  30. // Author: Brian Rerecich
  31. //
  32. //--------------------------------------------------------------------------
  33. `ifdef SIMULATION
  34. `include "msgio_defines.vh"
  35. `endif
  36.  
  37. module ati_fifo_ctrl_pipe (// Outputs
  38.               read_data,
  39.               full,
  40.               empty,
  41.               busy,
  42.               mem_waddr,
  43.               mem_we,
  44.               mem_raddr,
  45.               mem_re,
  46.              
  47.               // Inputs
  48.               we,
  49.               re,
  50.               mem_data,
  51.               clk,
  52.               reset
  53.               );
  54.    
  55.    //**************
  56.    //* Parameters *
  57.    //**************
  58.    parameter FIFO_WIDTH = 1;
  59.    parameter FIFO_DEPTH = 2;
  60.    parameter SKID_WORDS = 0;
  61.    parameter SKID_FULL  = 0;
  62.    parameter FIFO_NAME  = "";
  63.    parameter ADDR_WIDTH = ((FIFO_DEPTH <= 4) ? 2 :
  64.                            (FIFO_DEPTH <= 8) ? 3 :
  65.                            (FIFO_DEPTH <= 16) ? 4 :
  66.                            (FIFO_DEPTH <= 32) ? 5 :
  67.                            (FIFO_DEPTH <= 64) ? 6 :
  68.                            (FIFO_DEPTH <= 128) ? 7 :
  69.                            (FIFO_DEPTH <= 256) ? 8 :
  70.                            (FIFO_DEPTH <= 512) ? 9 :
  71.                (FIFO_DEPTH <= 1024) ? 10 :
  72.                (FIFO_DEPTH <= 2048) ? 11 : 12);  // Bigger than 4096???  i hope not.
  73.    
  74.    //***********************
  75.    //* Output Declarations *
  76.    //***********************
  77.    output [FIFO_WIDTH-1:0] read_data;     // Flopped data from Virage RAM
  78.    output          full;          // FIFO Full signal
  79.    output          empty;         // FIFO Empty signal
  80.    output          busy;
  81.    output [ADDR_WIDTH-1:0] mem_waddr;     // Write Address for RAM
  82.    output          mem_we;        // Write Enable
  83.    output [ADDR_WIDTH-1:0] mem_raddr;     // Read Address for RAM
  84.    output          mem_re;        // Read Enable for RAM
  85.                  
  86.    //**********************
  87.    //* Input Declarations *
  88.    //**********************
  89.    input           we;            // Write Enable
  90.    input           re;            // Read Enable
  91.    input [FIFO_WIDTH-1:0]  mem_data;      // Data from Virage MEM  
  92.    input           clk;            
  93.    input           reset;
  94.    
  95.    //***************************
  96.    //* Output REG Declarations *
  97.    //***************************
  98.    reg [FIFO_WIDTH-1:0]    read_data;
  99.    reg             full;
  100.    reg             empty;
  101.    reg             busy;
  102.    reg [ADDR_WIDTH-1:0]    mem_waddr;
  103.    reg             mem_we;        
  104.    reg [ADDR_WIDTH-1:0]    mem_raddr;
  105.    reg             mem_re;        
  106.  
  107.    //*****************************
  108.    //* Internal REG Declarations *
  109.    //*****************************  
  110.    reg [ADDR_WIDTH-1:0]    read_ptr_q;              // Read Pointer
  111.    reg [ADDR_WIDTH-1:0]    write_ptr_q;             // Write Pointer
  112.    
  113.    reg [ADDR_WIDTH-1:0]    read_ptr_d;            
  114.    reg [ADDR_WIDTH-1:0]    write_ptr_d;
  115.  
  116.    reg             full_d;
  117.    reg             int_empty_d;
  118.    reg             int_empty_q;
  119.    reg             mem_empty_q;
  120.    reg             read_mem;
  121.    reg             read_fifo;
  122.    
  123.    reg [ADDR_WIDTH:0]      cnt_q;
  124.    reg [ADDR_WIDTH:0]      cnt_d;
  125.  
  126.    reg             write_last;              // Write Pointer is at last location in FIFO
  127.    reg             read_last;               // Read Pointer is at last location in FIFO
  128.  
  129.    reg             cnt_gt_skid_limit;
  130.    reg             cnt_eq_skid_limit;
  131.  
  132.    reg [FIFO_WIDTH-1:0]    skid_flop_d;             // SKID flop
  133.    reg [FIFO_WIDTH-1:0]    skid_flop_q;
  134.    
  135.    reg         ld_skid_flop;
  136.    reg             skid_flop_vld_d;        
  137.    reg             skid_flop_vld_q;
  138.  
  139.    reg             mem_re_q;
  140.                
  141.    //*********************
  142.    //* Wire Declarations *
  143.    //*********************
  144.    wire empty_d;  
  145.    wire mem_empty_d;
  146.      
  147.    //***********************
  148.    //* Combinatorial Logic *
  149.    //***********************  
  150.  
  151.    always_comb begin
  152.  
  153.       // NOTE: Instead of putting the burden of knowing the internal latency
  154.       //       of the FIFO, we delay the de-assertion of empty to the outside
  155.       //       world by the internal latency of the FIFO so that whenever
  156.       //       (~empty & re) is true (as seen by the outside world) the read_data
  157.       //       is valid on the output
  158.       //        
  159.       read_mem  = re | empty;
  160.       read_fifo = read_mem | mem_empty_q;
  161.       mem_re    = read_fifo & ~int_empty_q;
  162.       busy      = ~(int_empty_q & mem_empty_q & empty);
  163.      
  164.       // Easy assignments....
  165.       mem_waddr = write_ptr_q;
  166.       mem_raddr = read_ptr_q;          
  167.       mem_we    = we;
  168.  
  169.       ld_skid_flop     = mem_re_q & ~empty & ~re;
  170.       skid_flop_vld_d  = ((mem_re_q & ~empty) | skid_flop_vld_q) & ~re; // (set | hold) & ~clr;
  171.       skid_flop_d      = skid_flop_vld_q ? skid_flop_q : mem_data;
  172.       read_data        = skid_flop_d;
  173.      
  174.    end
  175.    
  176.    always_comb begin
  177.      
  178.    // Logic for Read and Write Pointers
  179.       read_last = (read_ptr_q == (FIFO_DEPTH-1));
  180.       casez({mem_re,read_last})
  181.     2'b0?: read_ptr_d = read_ptr_q;
  182.     2'b10: read_ptr_d = read_ptr_q + 1;
  183.     2'b11: read_ptr_d = 0;
  184.       endcase // casez({re,read_last})
  185.  
  186.       write_last = (write_ptr_q == (FIFO_DEPTH-1));
  187.       casez({we,write_last})
  188.     2'b0?: write_ptr_d = write_ptr_q;
  189.     2'b10: write_ptr_d = write_ptr_q + 1;
  190.     2'b11: write_ptr_d = 0;
  191.       endcase // casez({we,write_last})
  192.    
  193.    end // always @ (...
  194.  
  195.    always_comb begin
  196.      
  197.       cnt_gt_skid_limit = (cnt_q >  (FIFO_DEPTH - SKID_WORDS - 1));
  198.       cnt_eq_skid_limit = (cnt_q == (FIFO_DEPTH - SKID_WORDS - 1));
  199.      
  200.       // Logic for FULL is based on the different SKID parameters
  201.      
  202.       // Toggle FULL once in SKID territory if an entry is read
  203.       if (SKID_FULL)
  204.     full_d = (cnt_eq_skid_limit & ~mem_re & we) |  // hit limit, writing, and not reading
  205.          (cnt_gt_skid_limit & ~mem_re);        // over limit and not reading.
  206.      
  207.       // Keep FULL asserted once FIFO has entered the SKID entries
  208.       else if (SKID_WORDS > 0)
  209.     full_d = (cnt_eq_skid_limit & ~mem_re & we) |  // hit limit, writing, and not reading
  210.          cnt_gt_skid_limit;                    // over limit
  211.      
  212.       // No SKID entries in FIFO
  213.       else
  214.     full_d = (cnt_eq_skid_limit & ~mem_re & we) |  // hit limit, writing, and not reading
  215.          (full & ~we & ~mem_re) |              // store value (no read, no write)
  216.          (full &  we &  mem_re);               // store value (read, write)
  217.      
  218.      // Logic for Full, Empty, and Count
  219.       casez({we, mem_re})
  220.     // both or none, do the same
  221.     2'b00,
  222.     2'b11: begin
  223.        cnt_d   = cnt_q;
  224.        int_empty_d = int_empty_q;
  225.     end
  226.     // read, no write
  227.     2'b01: begin
  228.        cnt_d   = cnt_q - 1;
  229.        int_empty_d = (cnt_q == 1);
  230.     end
  231.     // write, no read
  232.     2'b10: begin
  233.        cnt_d   = cnt_q + 1;
  234.        int_empty_d = 0;
  235.     end
  236.       endcase // casez({we, re})
  237.    
  238.    end // always @ (...
  239.    
  240.    // Determine if empty should be updated or left the same.
  241.    assign empty_d     = read_mem  ? mem_empty_q : empty;
  242.    assign mem_empty_d = read_fifo ? int_empty_q : mem_empty_q;
  243.        
  244.    //******************
  245.    //* FFs with reset *
  246.    //******************
  247.         always @ (posedge clk) begin
  248.             if (reset) begin
  249.                 read_ptr_q       <= {ADDR_WIDTH{1'b0}};
  250.                 write_ptr_q      <= {ADDR_WIDTH{1'b0}};
  251.                 int_empty_q      <= 1'b1;
  252.                 empty            <= 1'b1;
  253.                 mem_empty_q      <= 1'b1;
  254.                 full             <= 1'b0;
  255.                 cnt_q            <= {(ADDR_WIDTH+1){1'b0}};
  256.                 skid_flop_vld_q  <= 1'b0;
  257.             end // if (reset) begin
  258.             else begin
  259.             if (mem_re) begin
  260.                 read_ptr_q       <= read_ptr_d;
  261.             end
  262.             if (we) begin
  263.                 write_ptr_q      <= write_ptr_d;
  264.             end
  265.             if (mem_re | we) begin
  266.                 cnt_q            <= cnt_d;
  267.                 int_empty_q      <= int_empty_d;
  268.             end
  269.             skid_flop_vld_q  <= skid_flop_vld_d;
  270.             empty            <= empty_d;
  271.             full             <= full_d;
  272.             mem_empty_q      <= mem_empty_d;
  273.             end // else begin
  274.         end // always @ (posedge clk)
  275.    
  276.    //*********************
  277.    //* FFs without reset *
  278.    //*********************
  279. `ifdef SIMULATION
  280. // VCS coverage off
  281.    reg [ADDR_WIDTH:0] cnt_q_fix;
  282. // VCS coverage on
  283. `endif
  284.  
  285.    always @ (posedge clk) begin
  286.       mem_re_q <= mem_re;
  287.      
  288. `ifdef SIMULATION
  289. // VCS coverage off
  290.       // error checking
  291.        cnt_q_fix <= {(ADDR_WIDTH+1){!reset}} & cnt_d;
  292.        if (!reset && we && (cnt_q_fix == FIFO_DEPTH))
  293.      // leda DCVER_274 off
  294.         `MSGIO_DISPLAY("ATI_Fifo ERROR (%m): %s fifo written when full -- data dropped at time %t", FIFO_NAME, $time);
  295.      // leda DCVER_274 on
  296. // VCS coverage on
  297. `endif
  298.      
  299.    end
  300.    
  301.    always @ (posedge clk)
  302.    begin
  303.      if (ld_skid_flop)   // only load skid when valid
  304.        skid_flop_q <= skid_flop_d;
  305.    end
  306. endmodule // ati_fifo_circular
Advertisement
Add Comment
Please, Sign In to add comment