8-3优先编码器Verilog实现:从原理到FPGA实战

1次阅读
没有评论

共计 1679 个字符,预计需要花费 5 分钟才能阅读完成。

image.webp

背景与需求

优先级编码器是数字电路中的经典模块,在总线仲裁、中断控制器等场景下起到关键作用。比如当多个设备同时请求总线访问时,需要根据预设优先级快速响应最高优先级请求。传统实现采用 if-else 级联结构,但随着输入位数增加会导致:

8- 3 优先编码器 Verilog 实现:从原理到 FPGA 实战

  • 组合逻辑路径过长,影响最大时钟频率
  • 优先级判决延迟不均匀(高位信号路径更长)
  • 综合后可能出现毛刺(Glitch)

实现方案对比

1. case 语句实现

casex (input)
  8'b1xxxxxxx: code = 3'b111;
  8'b01xxxxxx: code = 3'b110;
  // ... 其他优先级
  default:    code = 3'b000;
endcase

特点
– 综合后生成多路选择器结构
– Xilinx 工具通常映射到 LUT4 资源
– 代码可读性最佳

2. if-else 级联实现

if (input[7]) code = 3'b111;
else if (input[6]) code = 3'b110;
// ... 后续判断

特点
– 产生链式组合逻辑
– 7 系列 FPGA 中每级增加约 0.3ns 延迟

3. 查找表实现

wire [2:0] code = lookup_table[input];

特点
– 预计算所有 256 种输入组合
– 消耗 256×3=768bit 存储资源
– 延迟恒定但面积代价大

优化后的 Verilog 实现

可配置参数化设计

module pri_encoder #(parameter WIDTH = 8) (input  [WIDTH-1:0] din,
  output reg [2:0]   dout
);

always @(*) begin
  dout = 3'b000;  // 默认值

  // 独热码优先级判决
  for (int i = WIDTH-1; i >=0; i--) begin
    if (din[i]) begin
      dout = $clog2(WIDTH)'(i);
      break;
    end
  end
end

endmodule

关键设计点
1. 使用 SystemVerilog 的 $clog2 自动计算输出位宽
2. always @(*)确保组合逻辑完整性
3. break语句避免优先级覆盖

配套 Testbench

module tb_encoder;
  reg [7:0] stimuli;
  wire [2:0] code;

  pri_encoder uut (.din(stimuli), .dout(code));

  initial begin
    $monitor("T=%0t input=%b output=%d", $time, stimuli, code);

    stimuli = 8'b0000_0001; #10;
    stimuli = 8'b0000_0010; #10;
    // 补充所有边界测试

    $finish;
  end
endmodule

综合优化策略

时序约束示例(XDC)

create_clock -period 5 [get_ports clk]
set_input_delay 1.5 -clock clk [all_inputs]

资源占用对比(Artix-7)

实现方式 LUT 数量 最大频率(MHz)
case 语句 4 450
if-else 7 380
查找表 16 500

常见问题解决

  1. 警告:incomplete case
  2. 解决方案:添加 default 分支或使用unique case

  3. 异步复位导致优先级失效

  4. 现象:复位期间输出错误编码
  5. 修复:复位信号同步化处理

  6. 毛刺问题

  7. 现象:输入变化时输出短暂跳动
  8. 优化:插入输出寄存器

验证方法

ModelSim 波形检查要点

  1. 输入变化到输出稳定的延迟时间
  2. 同时多个有效输入时的优先级判定
  3. 全 0 输入时的默认输出

覆盖率策略

covergroup encoder_cg;
  coverpoint stimuli {bins single_hot[] = {[1:255]};
    bins multi_hot = default;
  }
endgroup

扩展思考

如何设计带使能端(enable)和级联信号(cascade)的版本?建议考虑:

  1. 增加 enable 输入控制编码功能
  2. 添加 valid 输出指示有效编码
  3. 通过 cascade_in/cascade_out 实现多级扩展

实际部署前,推荐使用 Xilinx 的 CLB 资源估算工具(通过 Vivado 的 report_utilization 命令)验证设计规模是否满足目标器件要求。

正文完
 0
评论(没有评论)