[Documentation]. Amy electronic-FIFO cache

Source: Internet
Author: User
ArticleDirectory
    • Implementation Based on cyclic queue
Reader's assumptions

Mastered:

    • Programmable Logic Basics
    • Base on OpenGL
    • Verilog us II Getting Started Guide designed with OpenGL
    • ModelSim Getting Started Guide designed with OpenGL
Content

The FIFO cache is an elastic memory between two subsystems. Its concept is shown in Figure 1. It has two control signals, WR and RD, used for read and write operations. When Wr is inserted, the input data is written to the cache, And the read operation is ignored. The head of the FIFO cache is always valid, so it can be read at any time. The RD signal is actually like the "Remove" signal. When it is inserted, the first item (I .e. head) in the FIFO cache is removed, and the next item becomes available.

Figure 1 concept diagram of FIFO Cache

In many applications, the FIFO cache is a critical component and its implementation optimization is quite complicated. In this section, we will introduce a simple and realistic FIFO cache based on the cyclic sequence design. More effective FIFO caching based on specified devices can be found in the relevant manuals of Altera or Xilinx.

Implementation Based on cyclic queue

One way to implement FIFO caching is to add a control circuit to the register file. Register files use two pointers to arrange registers like a cyclic queue. Write poniter points to the head of the queue; read poniter points to the tail of the queue ). Each read or write operation moves the Pointer Forward. 8-operation 2 of the word loop queue.

Figure 2 FIFO cache based on cyclic queue

The FIFO cache usually contains two flag signals: full and empty, which indicate that the FIFO is full (that is, not writable) or the FIFO is empty (that is, not readable ). These two situations occur when the Read and Write pointers are equal, as shown in 2 (a), (f), and (I. The most difficult design task of the controller is to obtain a mechanism to distinguish the two situations. One solution is to use a trigger to track the empty and full flags. When the system is initialized, the trigger is set to 1 and 0, and then modified according to the WR and RD values in each clock cycle.

CodeFIFO Cache

Module FIFO # (parameter B = 8, // number of bits in a word w = 3 // Number of address bits) (// global clock and aysn reset input CLK, input rst_n, // FIFO interface // FIFO control signnal input Rd, input WR, // FIFO status signal output empty, output full, // FIFO Data Bus input [B-1: 0] w_data, output [B-1: 0] r_data); // signal declarationreg [B-1: 0] array_reg [2 ** W-1: 0]; // register arrayreg [W-1: 0] W_ptr_reg, w_ptr_next, reg; Reg [W-1: 0] r_ptr_reg, r_ptr_next, r_ptr_succ; Reg full_reg, empty_reg, full_next, empty_next; wire wr_en; // body // register file write operationalways @ (posedge CLK) if (wr_en) array_reg [w_ptr_reg] <= w_data; // Register File Read operationassign r_data = array_reg [r_ptr_reg]; // write enabled only when FIFO is not fullassign wr_en = WR &~ Full_reg; // FIFO control logic // register for read and write pointersalways @ (posedge CLK, negedge rst_n) if (! Rst_n) Begin iterator <= 0; r_ptr_reg <= 0; full_reg <= 1 'b0; empty_reg <= 1 'b1; end else begin iterator <= w_ptr_next; r_ptr_reg <= r_ptr_next; full_reg <= full_next; empty_reg <= empty_next; end // next-state logic for read and write pointersalways @ * begin // successive pointer values w_ptr_succ = w_ptr_reg + 1; r_ptr_succ = r_ptr_reg + 1; // default: Keep old values w_ptr_next = w_ptr_reg; r_pt R_next = r_ptr_reg; full_next = full_reg; empty_next = empty_reg; Case ({WR, RD}) // 2 'b00: No OP 2 'b01: // read if (~ Empty_reg) // not empty begin r_ptr_next = r_ptr_succ; full_next = 1 'b0; If (r_ptr_succ = w_ptr_reg) empty_next = 1 'b1; end 2 'b10: // write if (~ Full_reg) // not full begin w_ptr_next = w_ptr_succ; empty_next = 1 'b0; If (w_ptr_succ = r_ptr_reg) full_next = 1 'b1; end 2 'b11: // write and read begin w_ptr_next = w_ptr_succ; r_ptr_next = r_ptr_succ; end endcaseend // outputassign full = full_reg; assign empty = empty_reg; endmodule

The code is divided into two parts: register file and FIFO controller. The controller consists of two pointers and two sign triggers. Their sub-state logic detects WR and RD signals to take corresponding actions. For example, under the "10" condition, only write operations are indicated. First check the flag trigger to ensure that the cache is not full. If the conditions are met, we will write the Pointer Forward one digit and clear the null flag. Storing one more word (the data corresponding to the offset address is 1) may make the FIFO cache full, that is, the new write pointer catches up with the read pointer, we use the w_ptr_succ = r_ptr_reg expression to describe this situation.

According to figure 2, I wrote the following testbench, and its RTL simulation result is consistent with figure 2.

Testbench cached by code FIFO

'Timescale 1ns/1 nsmodule export o_tb; localparam T = 20; // clock period // global clock and Asyn resetreg CLK, rst_n; // FIFO interfacereg Rd, wR; wire empty, full; Reg [7:0] w_data; wire [7:0] r_data; // FIFO instantiationfifo #(. B (8 ),. W (3) 1_o_inst (. CLK (CLK ),. rst_n (rst_n ),. rd (RD ),. WR (WR ),. empty (empty ),. full (full ),. w_data (w_data ),. r_data (r_data); // clcokalwaysbegin CLK = 1' B0; # (T/2); CLK = 1' B1; #(T/2 ); end // resetinitialbegin rst_n = 1' B0; # (T/2) rst_n = 1' B1; end // stimulus bodyinitial begin // initial input; empty RD = 0; wR = 0; w_data = 8 'h00; @ (posedge rst_n); // wait to deassert rst_n @ (negedge CLK ); // wait for a clock // 1 Write wR = 1; w_data = 8' H11; @ (negedge CLK); // wait to assert WR wR = 0; @ (negedge CLK); // wait to deassert WR // 3 writes wR = 1; repeat (3) Begin w_data = w_data + 8' H11; @ (negedge CLK ); end wR = 0; @ (negedge CLK); // 1 read RD = 1; @ (negedge CLK); // wait to assert rd = 0; @ (negedge CLK) // wait to deassert RD // 4 writes wR = 1; repeat (4) Begin w_data = w_data + 8 'h11; @ (negedge CLK); End wR = 0; @ (negedge CLK); // 1 write; full wR = 1; w_data = 8' haa; @ (negedge CLK); wR = 0; @ (negedge CLK ); // 2 reads RD = 1; repeat (2) @ (negedge CLK); RD = 0; @ (negedge CLK); // 5 reads RD = 1; repeat (5) @ (negedge CLK); RD = 0; @ (negedge CLK); // 1 read; empty RD = 1; @ (negedge CLK); RD = 0; @ (negedge CLK); $ stop; endendmodule

Figure 3 RTL-level simulation waveform

Reference

1 Pong P. Chu. FPGA prototyping by Xilinx examples: Xilinx Spartan-3 version. Wiley

See also

[Study FPGA/FPGA with Amy]. [logical experiment document serialization plan]

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.