FPGA手撕系列(1)——同步FIFO

目录

一、设计原理

时钟同步:

内部指针:

数据存储:

空满状态检测:

读写控制:

二、架构框图

三、参考代码

四、仿真结果

五、总结


一、设计原理

        FIFO是一种先进先出的数据缓存器,与普通存储器的区别在于没有外部读写地址线,只能顺序写入和读取数据。同步FIFO(First In First Out,先进先出)指的是读时钟和写时钟为同一个时钟,即读写操作在同一时钟沿发生。

时钟同步:

  • 同步FIFO的核心在于读写操作都在同一个时钟信号的控制下进行。这意味着读使能、写使能、数据输入、数据输出以及满/空状态信号等都在时钟的同一沿(如上升沿或下降沿)发生变化。

内部指针:

  • 同步FIFO内部通常包含两个指针:读指针(Read Pointer)和写指针(Write Pointer)。读指针指向下一个要读取的数据位置,写指针指向下一个要写入的数据位置。
  • 读写指针在时钟的驱动下自动递增,以追踪数据的读写位置。当写指针追上读指针时(考虑到FIFO的循环特性),表示FIFO已满;当读指针追上写指针时,表示FIFO为空。

数据储存:

  • FIFO通常使用双口RAM(Random Access Memory)或类似的存储结构来存储数据。双口RAM允许在同一时间内进行读写操作,适合FIFO的应用场景。

空满状态检测:

  • 设计同步FIFO时,需要解决的一个重要问题是如何准确检测FIFO的空和满状态。这通常通过比较读写指针的位置来实现。为了避免读写指针在FIFO满或空时重叠导致的混淆,有时会在指针设计中加入额外的位(如格雷码中的MSB位)来区分这种情况。

读写控制:

  • 写操作:当写使能有效且FIFO未满时,数据被写入由写指针指示的位置,随后写指针递增。
  • 读操作:当读使能有效且FIFO非空时,数据从由读指针指示的位置读出,随后读指针递增。

二、架构框图

 简单同步fifo,仅供参考

三、参考代码

top

// -----------------------------------------------------------------------------
// Item:
// ----
### 动实现线程安全的同步FIFO队列 为了实现一个线程安全的同步FIFO(先进先出)数据结构,可以利用Java中的`ReentrantLock`以及条件变量来完成。这种方式相较于直接使用`BlockingQueue`接口下的具体实现类更加底层,有助于理解并发编程的核心原理。 以下是基于`ReentrantLock`的动实现: #### 实现代码 ```java import java.util.LinkedList; import java.util.Queue; public class ThreadSafeFifoQueue<T> { private final Queue<T> queue; // 使用LinkedList作为内部存储 private final int capacity; // 定义队列容量 private final ReentrantLock lock = new ReentrantLock(); // 可重入锁 private final Condition notEmpty = lock.newCondition(); // 非空条件 private final Condition notFull = lock.newCondition(); // 非满条件 public ThreadSafeFifoQueue(int capacity) { this.queue = new LinkedList<>(); this.capacity = capacity; } /** * 添加元素到队列尾部 */ public void enqueue(T element) throws InterruptedException { lock.lock(); try { while (queue.size() >= capacity) { // 如果队列已满,则等待 notFull.await(); } queue.add(element); // 添加元素 notEmpty.signal(); // 唤醒正在等待非空状态的线程 } finally { lock.unlock(); } } /** * 移除并返回队列头部的元素 */ public T dequeue() throws InterruptedException { lock.lock(); try { while (queue.isEmpty()) { // 如果队列为空,则等待 notEmpty.await(); } T result = queue.poll(); // 获取并移除头元素 notFull.signal(); // 唤醒正在等待非满状态的线程 return result; } finally { lock.unlock(); } } /** * 返回当前队列大小 */ public int size() { lock.lock(); try { return queue.size(); } finally { lock.unlock(); } } } ``` 上述代码实现了以下几个功能: - **线程安全性**:通过`ReentrantLock`确保多个线程访问共享资源时不会发生竞争条件[^1]。 - **阻塞操作**:当队列为空或达到最大容量时,生产者和消费者会分别被挂起直到满足特定条件[^2]。 - **公平性支持**:如果需要更严格的顺序执行保障,可以通过构造函数指定`ReentrantLock(true)`启用公平模式。 此设计遵循了经典的生产者-消费者模型原则,在多线程环境下提供了可靠的 FIFO 行为。 --- ###
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱看小黄鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值