← 数字电路笔试题目总结

推荐答案 测试一下

用verilog/vhdl写一个fifo控制器(包括空,满,半满信号)

编程题 中等 笔试真题

参考答案

FIFO控制器核心是管理读写指针,产生空、满、半满标志。以下以同步FIFO为例,深度为16(4位指针,实际用5位区分满状态)。 Verilog代码: ```verilog module fifo_ctrl #(parameter DEPTH=16, PTR_WID=4) ( input clk, rst_n, wr_en, rd_en, output reg full, empty, half_full ); localparam PTR = PTR_WID + 1; // 多一位用于满判断 reg [PTR-1:0] wr_ptr, rd_ptr; wire [PTR_WID-1:0] wr_addr = wr_ptr[PTR_WID-1:0]; wire [PTR_WID-1:0] rd_addr = rd_ptr[PTR_WID-1:0]; wire [PTR-1:0] wr_next = wr_ptr + 1; wire [PTR-1:0] rd_next = rd_ptr + 1; // 写指针递增 always @(posedge clk or negedge rst_n) if (!rst_n) wr_ptr <= 0; else if (wr_en && !full) wr_ptr <= wr_next; // 读指针递增 always @(posedge clk or negedge rst_n) if (!rst_n) rd_ptr <= 0; else if (rd_en && !empty) rd_ptr <= rd_next; // 空标志:复位时空,或读写指针相等且未写(实际复位后指针相等,但需要小心) wire same_ptr = (wr_ptr == rd_ptr); always @(posedge clk or negedge rst_n) if (!rst_n) empty <= 1; else if (wr_en && rd_en) empty <= empty; // 同时读写,空不变 else if (wr_en) empty <= 0; else if (rd_en) empty <= (wr_ptr == rd_next); // 读后指针追上写指针 // 满标志:写入后写指针追上读指针(高一比特不同,其余相同) wire almost_full = (wr_next == rd_ptr) && (wr_ptr[PTR-1] != rd_ptr[PTR-1]); always @(posedge clk or negedge rst_n) if (!rst_n) full <= 0; else if (wr_en && rd_en) full <= full; else if (wr_en) full <= almost_full; else if (rd_en) full <= 0; // 半满:数据量 > DEPTH/2 (读写指针差 > DEPTH/2) // 用减法器或比较,这里用差值 wire signed [PTR:0] diff = {1'b0, wr_ptr} - {1'b0, rd_ptr}; // 注意位宽 always @(posedge clk or negedge rst_n) if (!rst_n) half_full <= 0; else half_full <= (diff >= (DEPTH/2)); endmodule ``` 解析: - 使用双指针(wr_ptr, rd_ptr),位宽比地址宽度多1位以区分满和空。 - 空:复位后空,且读写指针相等且无写操作时为空。实际电路用读写指针相等且最近一次操作是读(或复位)判定空。更严谨做法:设置empty_reg由两个条件决定:指针相等且没有写操作(或写使能无效)。先写后读逻辑,常见写法用wr_en和rd_en的时序关系。 - 满:写指针的下一个值等于读指针,且两指针最高位相反(表明写指针绕了一圈)。 - 半满:读写指针差值大于等于深度一半。简单减法实现,注意有符号处理。 易错点: 1. 空满判断必须考虑指针绕回,不能仅靠地址相等。 2. 半满信号若用组合逻辑,需注意毛刺;通常用寄存器打拍。 3. 同时读写时状态不变。 4. 复位时指针清零,空信号置1,满信号置0。

涉及知识点

  • verilog
  • Verilog
  • 复位
← 上一题
登录后反馈错题
下一题 →