找回密码
 注册
关于网站域名变更的通知
查看: 246|回复: 1
打印 上一主题 下一主题

multi-cycle

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2020-9-4 16:30 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
引言( w% U/ {4 z- s1 b% H# Q
前面我们介绍了流水线的写法(pipeline的写法),流水线是数字设计中很常用的一种设计方法,可以提高运行频率,提高吞吐量。4 d* l1 c4 ^6 j, |

7 X; W9 ?  M( T& ]6 I" c% h- f如果组合逻辑延迟较大,一个时钟周期完成不了时,除了插入寄存器将组合逻辑拆分成流水线外,还可以采用multi-cycle的方式。
6 t  _4 x" R% R7 d# W7 i5 ?# E* ?
1 R7 |- E# q' k, T+ G: A* ymulti-cycle的工作机制很简单,从给定输入之后,等待多个周期之后,再去采样输出结果。
$ {% f7 u$ j  r8 _  |/ r' @6 ?
本小节我们将通过一个小实验来说明multi-cycle的具体RTL实现。
/ |$ v6 B8 f: ~  X! `+ Y9 ^6 K  Y- V% A7 C5 }& K3 t; X
, Q* P- V* {$ R9 d% e
. }  t: g" [$ d0 i
1,功能介绍
% C8 ?) l; B. g6 }+ r假设有某个模块,其计算量很大,以致延迟较大,一个周期完成不了,需要3个cycle才行。
5 Y  P6 ]" p8 l. \' I5 X( U7 s5 Q. i9 R& @) N
假设时钟周期是10,这个模块的运算分为“加法,左移,减法”三个操作,分别用时7,8,9。
4 m/ p4 Z' K; D& C
1 ], z& }, [3 o" ]3 t% |( k/ P9 G! Z# t% J/ m
' I' X, h, {( S4 H( F$ C9 u- \* e
2,RTL实现6 z: m# l$ Y8 a0 l3 A, L- c6 N: l, d
5 c6 F0 ]  R4 K4 U: ~- ~
如果在数字设计时,遇到上述模块描述的情况时,可以考虑multi-cycle实现。
" E7 @+ |# U' }' E( d
2 o5 I/ R0 _* S" Z- z, p具体RTL如下:mc.v
1 }' T1 M3 Y" M! G0 l8 O. k/ F0 O- E2 Y' l6 W' y6 C4 Z, c
其中关于状态机的写法,我们之前有专门介绍,如有疑问,请参考(你知道状态机的四种写法都是什么吗?)。
9 \2 s3 w0 d- x% R' ~( z2 z% i6 ~6 k$ f: F7 J
  • /*
  • * multi-cycle example
  • * Rill 2015-05-29
  • */

  • / l) ?) ], |7 o3 H4 _" t- U
  • module Mmulti_cycle
  • (
  •         input clk,
  •         input rst_n,
  •         input en_i,
  •         input [7:0] data_i,
  •         output en_o,
  •         output [7:0] data_o,
  •         output idle
  • );
  • 6 V! K) p4 S. O: ]/ a- ]6 o
  •         //===================
  •         // control path, fsm
  •         //===================
  • ' X) J7 F9 b1 a6 p6 b4 x0 P) a1 i
  •         localparam S_IDLE = 4'd0;
  •         localparam S_CYCLE1 = 4'd1;
  •         localparam S_CYCLE2 = 4'd2;
  •         localparam S_CYCLE3 = 4'd3;
  •         reg [3:0] c_state_r;
  •         wire [3:0] n_state;
  •         wire state_changed;
  •         wire cs_idle = (c_state_r == S_IDLE);
  •         wire cs_cycle1 = (c_state_r == S_CYCLE1);
  •         wire cs_cycle2 = (c_state_r == S_CYCLE2);
  •         wire cs_cycle3 = (c_state_r == S_CYCLE3);
  •         wire ns_idle = cs_cycle3;
  •         wire ns_cycle1 = cs_idle & en_i;
  •         wire ns_cycle2 = cs_cycle1;
  •         wire ns_cycle3 = cs_cycle2;
  •         assign state_changed = ns_idle | ns_cycle1 | ns_cycle2 | ns_cycle3;
  •         assign n_state = (         {4{ns_idle}} & S_IDLE
  •                                                 | {4{ns_cycle1}} & S_CYCLE1
  •                                                 | {4{ns_cycle2}} & S_CYCLE2
  •                                                 | {4{ns_cycle3}} & S_CYCLE3
  •                                         );
  •         always @(posedge clk)
  •                 if(~rst_n)
  •                         c_state_r <= S_IDLE;
  •                 else
  •                         c_state_r <= n_state;
  •         //=================
  •         // data path,calc
  •         //=================
  •         wire [7:0] data1;
  •         wire [7:0] data2;
  •         wire [7:0] data3;
  •         assign #7 data1 = data_i + 1'b1;
  •         assign #8 data2 = data1 << 1'b1;
  •         assign #9 data3 = data2 - 1'b1;
  •         assign en_o = cs_cycle3;
  •         assign data_o = data3;
  •         assign idle = cs_idle;
  • endmodule

  • . Y5 V6 X$ |) z/ ~% D
   
* O) k; E- c7 a* x- T) Q. F( p  L7 P5 ?: O. ~$ w  [
3,testbench
; Y* o( S1 r# E6 A8 w6 O( ?  }4 \; c% W, E* q% |" |6 E
具体multi-cycle模块是如何工作的呢,我们需要写个简单的TB验证一下:tb.v1 x( l7 i5 g$ n+ I" z7 ~& s2 A* f: r
6 r: z4 m6 ?. g; B6 x0 u9 {
  • /*
  • * multi-cycle example
  • * Rill 2015-05-29
  • */
  • module Ttb;
  •         reg clk;
  •         reg rst_n;
  •         reg en_i_r;
  •         reg [7:0] data_i_r;
  •         wire en_o;
  •         wire [7:0] data_o;
  •         wire idle;
  •         Mmulti_cycle mc0
  •         (
  •         .clk (clk),
  •         .rst_n (rst_n),
  •         .en_i (en_i_r),
  •         .data_i (data_i_r),
  •         .en_o (en_o),
  •         .data_o (data_o),
  •         .idle (idle)
  •         );
  •         initial
  •                 begin
  •                         clk = 1'b0;
  •                         rst_n = 1'b0;
  •                         en_i_r = 1'b0;
  •                         data_i_r = 8'b0;
  •                         fork
  •                                 forever #5 clk = ~clk;
  •                         join_none
  •                         repeat(10) @(posedge clk);
  •                         rst_n = 1'b1;
  •                         repeat(10) @(posedge clk);
  •                         @(posedge clk);
  •                         en_i_r = 1'b1;
  •                         data_i_r = 8'h1;
  •                         repeat(10) @(posedge clk);
  •                         $finish();
  •                 end
  • endmodule3 R) I& R1 P! ]/ ]% H7 s
7 C# I4 z+ s  D/ P5 S$ R, x+ Z

0 I8 ]" z6 _1 F4 ?9 M* q
) E* N( w- x& P/ z' t- r( S/ `! d* @- x" X
4,nc脚本和vflist7 S! y# U0 o0 h" N9 B

& @" u& V+ L/ }' W( W( ~4 Umc.sh:1 r! P+ }" y+ U: d

7 A$ a& j1 K: Q  n
  • #! /bin/bash
  • ) G1 p8 T! s4 }! o& U$ H) r
  • . R$ Z: j; x$ ?4 k, t7 t$ a
  • #
  • # mc.sh
  • # usage: ./mc.sh c/w/r
  • # Rill create 2014-09-03
  • #

  • # U) }- T) j/ S& f7 i( ]9 ^$ o* r$ I

  • 6 b8 \" _7 N( M* a
  • TOP_MODULE=Ttb
  • 2 |9 \. b8 b. z3 P
  • export SRC_DIR=$(pwd)
  • tcl_file=run.tcl

  •   i+ [  V' t1 K
  • if [ $# != 1 ];then
  • echo "args must be c/w/r"
  • exit 0
  • fi

  • 1 y! M4 q$ ?# z" b: ]& f6 m
  • if [ $1 == "c" ]; then
  • echo "compile lib..."
  • ncvlog -f ./vflist -sv -update -LINEDEBUG;
  • #ncelab -delay_mode zero -access +rwc -timescale 1ns/10ps ${TOP_MODULE}
  • ncelab -delay_mode distribute -access +rwc -timescale 1ns/10ps ${TOP_MODULE}
  • exit 0
  • fi

  • . _, v. D$ L& f% C# q- o2 r0 y0 O% F3 G  E

  • ! u0 S  s+ ~1 G* H
  • if [ -e ${tcl_file} ];then
  • rm ${tcl_file} -f
  • fi
  • touch ${tcl_file}

  • ' F- ~3 K( B2 r) ~" s
  • if [ $1 == "w" ];then
  • echo "open wave..."
  • echo "database -open waves -into waves.shm -default;" >> ${tcl_file}
  • echo "probe -shm -variable -all -depth all;" >> ${tcl_file}
  • echo "run" >> ${tcl_file}
  • echo "exit" >> ${tcl_file}
  • fi
  • + M' Q( u- s( j) q1 R' a
  • if [ $1 == "w" -o $1 == "r" ];then
  • echo "sim start..."
  • ncsim  ${TOP_MODULE} -input ${tcl_file}
  • fi
  • ' c7 b7 j9 A7 ]) Y0 S+ s
  • echo "$(date) sim done!"
    ; D/ M# N$ ^: M6 `, P
            
& N. k( l& g4 |7 q
9 c  U% y( M+ Q& Z, C6 e" cvflist:4 U9 \0 {& F6 Z2 ~: s$ j3 @# Z
0 S" |  l; s3 m1 a
  • -incdir ${SRC_DIR}
  • 6 K* j, J) R/ ^6 Z: i8 U
  • ${SRC_DIR}/mc.v
  • ${SRC_DIR}/tb.v
    - R; S& P  {6 D! R3 h5 ?9 @6 C- A

% P" u  [/ t' s0 t& D# B! d" M# M8 v

6 K0 ]! r2 r3 \2 S5,验证2 Z% v3 G. I' B: `1 H& h8 N
& G+ [) ^3 U. x& X1 D
运行mc.sh c; mc.sh w即可得到仿真波形:, {9 [/ b9 d# M  r' q5 c5 _# r

% k1 x) F: X+ A$ U/ n# [* u ; w# o7 D4 O( @6 V/ H9 b, W
2 [: `: Z3 r* c/ v/ n6 a

# K9 u2 Y! T0 B4 C$ N1 r通过波形可以看出,mc模块在经过3个cycle之后输出了运算结果3。
6 Q: H# Z: y. }& i+ }- C
. E2 o6 x6 `" @1 r# g/ T
: D8 U5 r: q- C; z2 Y$ j* U5 a, C$ X0 Z# Z1 D" {
6,小结2 \6 O: [, O  }" h

( ^" F! W; ^% z6 C6 j* m0 x# Kpipeline和multi-cycle是处理长延迟逻辑常用的两种方式,我们都介绍过了。
# M% {& [3 F" W3 ~- P& M1 r+ J$ |' x9 X, w, Z
Enjoy!4 F1 V9 C! n2 J' W# ?

+ n1 @0 v/ Y* U/ _; \1 v
  • TA的每日心情
    慵懒
    2020-6-13 15:46
  • 签到天数: 1 天

    [LV.1]初来乍到

    2#
    发表于 2020-9-4 17:25 | 只看该作者
    multi-cycle
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-6-27 22:48 , Processed in 0.093750 second(s), 26 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表