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

multi-cycle

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
引言
5 }% o# Q# @: e# }0 F, n前面我们介绍了流水线的写法(pipeline的写法),流水线是数字设计中很常用的一种设计方法,可以提高运行频率,提高吞吐量。
, y- o" `6 _" }! A$ ~+ X0 V" x# v( Z0 j6 G
如果组合逻辑延迟较大,一个时钟周期完成不了时,除了插入寄存器将组合逻辑拆分成流水线外,还可以采用multi-cycle的方式。: T# ~. `# \& x, B$ X
; y" X' O' Z) J$ p! {- `
multi-cycle的工作机制很简单,从给定输入之后,等待多个周期之后,再去采样输出结果。9 H$ L4 R7 @. n+ g; ^

; W9 O" L8 }0 b8 `本小节我们将通过一个小实验来说明multi-cycle的具体RTL实现。
% a3 U( U- g- s. V9 y4 P6 Z$ {3 k1 b& y  j9 A' a
& a2 D. N& q# O: j
9 A9 }* e1 A, h' h4 ?% K
1,功能介绍
2 o) c6 d! \9 t" F2 ?假设有某个模块,其计算量很大,以致延迟较大,一个周期完成不了,需要3个cycle才行。/ N' K4 k8 Q% A) @; v# {4 A

( M4 i, j# \2 C) X* H假设时钟周期是10,这个模块的运算分为“加法,左移,减法”三个操作,分别用时7,8,9。& z* W8 D7 A) w; ?

: u9 b  n, ?( Z/ r; h
: @% a, ]- W3 a2 ?/ Y( D" A5 }- `- c6 Y0 d1 F
2,RTL实现
* y" s. m" w, Z) r, ]2 P- \  n0 y; ]  J/ S2 C* s( |' I3 {
如果在数字设计时,遇到上述模块描述的情况时,可以考虑multi-cycle实现。
. ?7 d+ R( V0 \9 v. e5 X# E6 t; C: W4 c# [
具体RTL如下:mc.v& Y) ?+ U. S- q
. \# g& Q2 M. z+ ?, p
其中关于状态机的写法,我们之前有专门介绍,如有疑问,请参考(你知道状态机的四种写法都是什么吗?)。* ~) r- M0 y+ `4 [1 P4 `
! Z9 U( x9 b# ~% Q
  • /*
  • * multi-cycle example
  • * Rill 2015-05-29
  • */
  • 7 }: c& v0 R& W% o
  • 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
  • );

  • 5 k# {7 ?2 h8 |: r2 |# K% t# e
  •         //===================
  •         // control path, fsm
  •         //===================
  • " w7 b7 ^  Z7 g# F9 j/ u2 s' L
  •         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
  • ' {" s5 b' x' f& ]2 d# H
   7 o, W2 r4 F: b' l

' E; O3 R$ c  t3,testbench
5 F9 L8 h3 X+ W/ S0 L& }' o
9 U: |, V! O# w$ A* X& W& y& {9 _具体multi-cycle模块是如何工作的呢,我们需要写个简单的TB验证一下:tb.v' @, K& X7 S# |* S/ Z

$ L3 {/ X& l" ?9 Q+ f
  • /*
  • * 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
  • endmodule
    0 h2 h' N0 ]& X9 y/ h& i
  D; r2 A- O" v: l3 q
7 h# q* R3 T7 ]% g- {3 r7 m2 Y: o3 d

9 u8 q0 r% G& S/ v( B; ]* p: E
- L, Q) u1 c) o/ `% L4,nc脚本和vflist, E- i3 J! s& Q+ Z8 ]+ {
* i0 P8 E. C' ?* I( }2 p+ @: f7 o3 Z
mc.sh:
9 ~  E2 \1 r' Y% c/ f5 k0 k; \. Y8 I
  • #! /bin/bash
  • 8 s9 H. Z. V0 n- H( @
  • $ F+ W' }- [2 j+ z! K) k
  • #
  • # mc.sh
  • # usage: ./mc.sh c/w/r
  • # Rill create 2014-09-03
  • #
  • 9 w; F" ?: U7 n- z- b

  • 1 x  T8 e/ x# ~$ r
  • TOP_MODULE=Ttb

  • / V7 P' k1 r' v3 V
  • export SRC_DIR=$(pwd)
  • tcl_file=run.tcl

  • ) p8 t! ]2 }1 |# @9 F7 `
  • if [ $# != 1 ];then
  • echo "args must be c/w/r"
  • exit 0
  • fi
  • & k' C) d# c3 p! ]4 ^9 U/ G/ B  B
  • 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

  • % L' d5 R0 v+ W# J. ]% B

  • : j& {: Y' L, a4 U. K
  • if [ -e ${tcl_file} ];then
  • rm ${tcl_file} -f
  • fi
  • touch ${tcl_file}

  • ' \/ F, z* K, g0 l
  • 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

  • ' `+ a) f' T" P# {5 B% a2 o
  • if [ $1 == "w" -o $1 == "r" ];then
  • echo "sim start..."
  • ncsim  ${TOP_MODULE} -input ${tcl_file}
  • fi
  • 5 g' @' D! b1 K4 \% p' P
  • echo "$(date) sim done!"
      ?8 C* M3 o& v
            9 z( F) B+ R- x( ?3 y

; |& N- ]6 B; e- mvflist:
! S" I$ d) H+ F. o' Y
7 ^6 k4 @9 N+ D
  • -incdir ${SRC_DIR}

  • 4 Z" L% G7 H) z: Q" C3 Q. ?# Z9 v
  • ${SRC_DIR}/mc.v
  • ${SRC_DIR}/tb.v& H+ z  K4 P  x. }

% _: T0 _  Z2 V0 ?) g  q! W$ I6 G0 _
$ `) b, i% b, p5 Z
5,验证4 Z, p# x, F& i& [7 n# }$ k# B
$ ]. n5 m; t* ]  p
运行mc.sh c; mc.sh w即可得到仿真波形:
4 d8 j6 G" M- N) I6 M4 P, `+ Y7 k$ i4 K6 U) M7 N, R

: w3 k0 P1 f0 i" k! ?
  {7 Z0 D+ H/ f8 f2 n1 z6 ]+ `' F/ M2 u; i/ N: P# D# |# {* s' z
通过波形可以看出,mc模块在经过3个cycle之后输出了运算结果3。$ s! @. y3 u! d/ Q% y, D+ Z
5 T& |! q; j" B
9 L+ }6 e) M" ~. V7 m9 A

  f% }4 K( s6 D; I- \# L3 h, p6,小结' y8 }$ M" y) x: K
1 L3 \$ m8 V* K# S0 z
pipeline和multi-cycle是处理长延迟逻辑常用的两种方式,我们都介绍过了。
: ?' a0 ^6 ^/ I, e3 O+ C
& Y( f' {  \: J$ G3 `( E6 d) hEnjoy!
9 ^6 r3 d/ O0 O- ]( w
5 N$ x; N4 f, Q7 a6 U, `
  • 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-11-24 23:50 , Processed in 0.171875 second(s), 26 queries , Gzip On.

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

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

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