引言
本文将结合橙汁提供代码,介绍四个经实践验证的参数化基础模块:可配置延迟单元(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;i<DELAY_MAX;i=i+1) shift_reg[i] <= 'd0; else for(i=0;i<DELAY_MAX;i=i+1) shift_reg[i] <= pause ? shift_reg[i] : (i>0 ? 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状态下继续计数以实现帧间隔。