他山之石可以攻玉系列(05):数字IC基础模块库设计:延迟单元、边沿检测、SPI接口与信号锁存器
引言本文将结合橙汁提供代码,介绍四个经实践验证的参数化基础模块:可配置延迟单元(delay_unit)、边沿检测器(get_edge)、SPI接口控制器(spi_interface)以及信号变化锁存器(signal_lock)。文中将着重分析各模块的功能特性、创新设计点,并结合关键代码阐述其实现原理。1. 可配置延迟单元delay_unit功能概述该模块通过移位寄存器链实现0至DELAY_MAX-1个时钟周期的可调延迟,主要提供两个控制维度:动态抽头选择:输入sel_delay实时选择输出对应的延迟级数,零延迟时直通输入信号,超出最大值则输出末级寄存器值。数据流暂停:当pause信号有效时,所有移位寄存器保持当前值,流水线暂停但不丢失数据,适合用于后级反压或等待场景。创新点分析传统延迟线一般仅固定延迟周期,本设计将多路选择器与移位寄存器耦合,实现单模块覆盖可变延迟需求,减少组合逻辑层级。pause机制的引入使延迟单元兼具有效数据保持能力,避免了外部流控逻辑与寄存器组间的复杂握手,简化流水线控制。关键代码剖析always @(posedge i_clk) begin if(i_rst) for(i=0;iDELAY_MAX;i=i+1) shift_reg[i] = 'd0; else for(i=0;iDELAY_MAX;i=i+1) shift_reg[i] = pause ? shift_reg[i] : (i0 ? shift_reg[i-1] : din); end assign dout = (sel_delay == 0) ? din : (sel_delay = DELAY_MAX) ? shift_reg[DELAY_MAX-1] : shift_reg[sel_delay-1];上述代码中,pause控制寄存器的更新使能:当pause为高时,三目运算符选择维持原值,否则执行级联移位。输出组合逻辑根据sel_delay选择正确的抽头,并处理了输入直通与边界情况。2. 边沿检测器get_edge功能概述get_edge模块对并行输入信号signal进行边沿检测,输出脉冲信号signal_edge。其可配置参数包括:SEL_1POS_0NEG:选择上升沿、下降沿或双边沿检测模式。IGNORE_FIRST:使能后忽略复位后首次边沿,避免上电毛刺。IF_IOB:用于适配输入输出寄存器(IOB)后的额外延迟,保证时序对齐。创新点分析该设计将去毛刺、模式选择、IOB补偿、首次忽略等特性集成于同一模块,通过参数化轻松适配不同场景。利用内部例化的delay_unit实现灵活延迟,无需手动构建多级寄存器,增强了可维护性。IGNORE_FIRST功能通过一个带延迟的使能信号实现,当该信号为低时屏蔽输出,直到首次延迟周期结束,从而滤除复位后不确定态产生的伪边沿。核心实现assign signal_edge = ~rst (IGNORE_FIRST ? ignore_first_done : 1'b1) ((SEL_1POS_0NEG 1) ? ( signal_temp ^ signal_temp_d1) : ((SEL_1POS_0NEG == 1) ? ( signal_temp ~signal_temp_d1) : (~signal_temp signal_temp_d1)));通过简单的组合逻辑实现边沿判断,并利用ignore_first_done信号(由另一个延迟单元生成)屏蔽初始阶段。signal_temp与signal_temp_d1均由例化的delay_unit提供,确保了延迟周期可控。3. SPI接口控制器spi_interface功能概述该模块实现了一个主机端SPI接口,支持参数化的地址宽度(WIDTH_ADDR)和数据宽度(WIDTH_DATA)。读帧长度自动填充至字节边界(LEN_FRAME_RD),写帧则在此基础上追加数据段。接口包含标准SPI信号:sck、csb、sda_tx、sda_rx,并支持三态输出控制tri_1i0o。状态机包含四个状态:IDLE、TX(发送地址/数据)、RX(接收数据)和GAP(帧间间隔),可通过gap_clk参数配置最小帧间隔,以满足不同外设的时序要求。创新点分析参数化帧结构:根据WIDTH_ADDR自动计算读帧长度并向上取整至8的倍数,简化了非标准位宽寄存器的访问协议适配。间隙时钟支持:gap_clk参数控制CS释放后的空闲周期数,可保证SPI从设备有足够时间完成内部操作,设计中将GAP状态独立出来,逻辑清晰且易于调整。SCK时钟优化:assign sck = ~(clk | csb);当CS无效时SCK保持高电平,减少了信号翻转带来的功耗与电磁干扰。三态控制:tri_1i0o信号在读操作期间置高,使SDA为输入;其他时刻置低,输出使能,由sda_tx驱动总线,符合典型SPI半双工协议。状态机与位计数always @(posedge i_clk) begin if(i_rst) cnt_bit = 'd0; else if(state_c == P_ST_IDLE) cnt_bit = 'd0; else if(state_c == P_ST_TX) cnt_bit = cnt_bit + 'd1; else if(state_c == P_ST_RX tri_1i0o_pos) cnt_bit = cnt_bit; // 等待三态切换稳定 else if(state_c == P_ST_RX tri_1i0o_pos == 'd0) cnt_bit = cnt_bit + 'd1; else if(state_c == P_ST_GAP) cnt_bit = cnt_bit + 'd1; end位计数器在TX状态每个时钟递增,RX状态则等待三态切换完成的上升沿后再递增,避免了总线切换期间的误采样。GAP状态下继续计数以实现帧间隔。数据采样逻辑