【线性序列机-05】- 带请求保持计数优先的线性序列机之二
1. 功能介绍
在上一篇文章中,对带请求保持计数优先的线性序列机予以了介绍。然而,应当注意的是,此过程仅仅留存了请求信号,却未保留与请求同步发出的计数起始值。这种情况在计数器工作时起始值处于准静态,即起始值在计数器工作时不会发生变化,或许是可行的。比如说,当计数器的起始值始终保持恒定,没有任何变动。但是,如果计数器的起始值是动态的,也就是处于伴随请求信号变化的状态,那么必然会产生问题。
为了解决此问题,本文将通过设立一个 Buffer 来实现。尽管这样做会付出额外的芯片面积作为代价。Buffer(缓冲区)可以用于存储计数器的起始值等相关信息。当计数器的起始值为动态时,通过 Buffer 对起始值进行缓存和管理,能够确保在需要时可以正确获取到相应的起始值,从而避免出现问题。然而,使用 Buffer 会占用一定的硬件资源,导致芯片面积增加,但为了保证系统的正常功能和性能,这种额外的开销在某些情况下是可以接受的。
2. 结构框图
3. 源码实现
module lsm_ctrl4 #(
parameter CW = 4 ,
parameter QW = 4
)(
input wire clk ,
input wire rstn ,
input wire req ,
input wire hold ,
output wire full ,
input wire [CW-1:0] cnt_in ,
output wire [CW-1:0] cnt_nxt ,
output reg [CW-1:0] cnt_cur ,
output wire cnt_eq0
);
reg [QW-1:0] req_cnt;
reg [QW-1:0] req_rptr;
reg [QW-1:0] req_wptr;
reg [CW-1:0] req_buf[0:(1<<QW)-1];
wire cnt_ne0 = |cnt_cur;
wire req_ne0 = |req_cnt;
wire req_max = &req_cnt;
wire req_all = req | (|req_cnt);
wire cnt_ena = ~hold & (req_all | cnt_ne0);
wire req_inc = req & cnt_ne0 & ~req_max;
wire req_dec = ~req & ~cnt_ne0 & req_ne0;
wire req_ena = req_inc | req_dec;
wire wptr_inc = req & (cnt_ne0 | req_ne0) & ~req_max;
wire rptr_inc = ~cnt_ne0 & req_ne0;
wire [QW-1:0] req_nxt = req_cnt + {{(QW-1){req_dec}}, req_ena};
wire [QW-1:0] cnt_mux = rptr_inc ? req_buf[req_rptr] : cnt_in;
assign full = req_max;
assign cnt_eq0 = ~cnt_ne0;
assign cnt_nxt = cnt_ne0 ? cnt_cur - 1'b1 : {CW{req_all}} & cnt_mux;
always @(posedge clk or negedge rstn)
begin
if(!rstn)
cnt_cur <= {CW{1'b0}};
else if(cnt_ena)
cnt_cur <= cnt_nxt;
end
always @(posedge clk or negedge rstn)
begin
if(!rstn)
req_cnt <= {QW{1'b0}};
else if(req_ena)
req_cnt <= req_nxt;
end
always @(posedge clk or negedge rstn)
begin
if(!rstn)
req_wptr <= {QW{1'b0}};
else if(wptr_inc)
req_wptr <= req_wptr + 1'b1;
end
always @(posedge clk or negedge rstn)
begin
if(!rstn)
req_rptr <= {QW{1'b0}};
else if(rptr_inc)
req_rptr <= req_rptr + 1'b1;
end
always @(posedge clk)
begin
if(wptr_inc)
req_buf[req_wptr] <= cnt_in;
end
endmodule
4. 仿真结果
4.1 仿真顶层
module test_top;
reg clk;
reg rstn;
reg req;
reg hold;
reg [3:0] cnt_in;
initial begin
clk = 1'b0;
forever #5 clk = ~clk;
end
initial begin
rstn = 1'b0;
#1_001;
rstn = 1'b1;
end
lsm_ctrl4 #(.CW(4)) dut (
.clk (clk ),
.rstn (rstn ),
.req (req ),
.hold (hold ),
.full ( ),
.cnt_in (cnt_in ),
.cnt_nxt ( ),
.cnt_cur ( ),
.cnt_eq0 ( )
);
initial begin
req = 1'b0;
hold = 1'b0;
cnt_in = 4'd0;
#100_000;
for(integer i=0; i<16; i=i+1) begin
@(posedge clk) #1;
req = 1'b1;
cnt_in = i[3:0];
@(posedge clk) #1;
req = 1'b0;
#100_000;
end
for(integer i=0; i<32; i=i+1) begin
@(posedge clk) #1;
req = 1'b1;
cnt_in = $urandom_range(8, 15);
@(posedge clk) #1;
req = 1'b0;
repeat(3) @(posedge clk) #1;
end
#100_000;
$finish();
end
endmodule
4.2 仿真结果
- 单次请求,正常计数
- 重复请求,计数器持续之前的计数
从上图中可以看出,单次请求的情形之下,线性序列机能够正常运作并且能够即刻进行处理。在多次请求的状况下,计数器会保持先前的计数,与此同时记录新的请求以及计数起始值,待到当前计数周期完结之后,即刻着手处理新的请求。在上一篇文章里的计数器起始值是静态的,而本篇文章中所阐述的能够支持动态的,在功能和性能方面具有极大的优势。
5. 综合结果
在参数CW=4,QW=4的情况下,以某90nm的数字标准单元库工艺综合的结果如下所示
5.1 面积
Number of ports: 98
Number of nets: 381
Number of cells: 313
Number of combinational cells: 192
Number of sequential cells: 101
Number of macros/black boxes: 0
Number of buf/inv: 23
Number of references: 47
Combinational area: 690.782421
Buf/Inv area: 48.686402
Noncombinational area: 1360.396782
Macro/Black Box area: 0.000000
Net Interconnect area: undefined (No wire load specified)
Total cell area: 2051.179203
Total area: undefined
5.2 功耗
Internal Switching Leakage Total
Power Group Power Power Power Power ( % ) Attrs
--------------------------------------------------------------------------------------------------
io_pad 0.0000 0.0000 0.0000 0.0000 ( 0.00%)
memory 0.0000 0.0000 0.0000 0.0000 ( 0.00%)
black_box 0.0000 0.0000 0.0000 0.0000 ( 0.00%)
clock_network 0.0000 0.0000 0.0000 0.0000 ( 0.00%)
register 0.0000 0.0000 0.0000 0.0000 ( 0.00%)
sequential 3.7489e-02 1.4221e-04 1.7945e+06 3.9426e-02 ( 85.91%)
combinational 3.8533e-03 2.1211e-03 4.9050e+05 6.4649e-03 ( 14.09%)
--------------------------------------------------------------------------------------------------
Total 4.1342e-02 mW 2.2633e-03 mW 2.2850e+06 pW 4.5891e-02 mW
5.3 时序
Point Incr Path
-----------------------------------------------------------
req_cnt_reg_2_/CK (DFFRQXL) 0.00 0.00 r
req_cnt_reg_2_/Q (DFFRQXL) 0.19 0.19 f
U152/Y (NOR4XL) 0.35 0.54 r
U159/Y (NAND3XL) 0.14 0.68 f
U321/Y (OAI2B2XL) 0.09 0.78 r
U326/Y (OAI32XL) 0.07 0.85 f
U328/Y (AOI32XL) 0.07 0.91 r
cnt_nxt[0] (out) 0.00 0.91 r
data arrival time 0.91
-----------------------------------------------------------
6. 总结
本篇带请求保持计数优先的线性序列机乃是在前一篇同类型线性序列机的基础之上展开了优化与改进。其主要提升之处在于,当接受请求时,能够同时对计数器的初始值予以记录。倘若计数器的起始值需要依据不同的状况进行动态调整,然而直接获取动态起始值存在困难或者会引发其他问题,那么便可以借助 Buffer 来暂时存储这些起始值。待到需要使用起始值的时候,再从 Buffer 中进行读取,以此确保计数器能够依照预期正常工作。这种方式在化解问题的同时,也造成了额外的面积耗费。在实际的设计过程中,需要全面考量问题的严重程度、性能要求以及芯片资源等各类因素,权衡究竟是否采用此种方式来处理问题。