集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 967|回复: 1

Verilog HDL 建模技巧 低级建模 仿顺序操作·思路篇 10 - 组织模块和两义性问题

[复制链接]
羽蒙 发表于 2014-8-15 15:34:32 | 显示全部楼层 |阅读模式
4.2 “


低级功能模块”封装 和“两义性”或者“多义性”的问题
点击浏览下一页
如上的示意图。当我们要封装2个“低级功能模块”在一次,如果两个“低级功能模块”使用同一个输入(重用输入连线)或者同一个输出(重用输出连线)就会出现两义性的问题。为了解决这个问题,使用“多路选择器”便可以。

1.module flashing_module
2.(
3.    CLK, RSTn,
4.    Right_Start_Sig, Left_Start_Sig, Right_Done_Sig, Left_Done_Sig,
5.    Q
6.);
7.  
8.     input CLK;
9.     input RSTn;
10.    input Right_Start_Sig;
11.    input Left_Start_Sig;
12.   
13.    output Right_Done_Sig;
14.    output Left_Done_Sig;
15.    output [7:0]Q;
16.   
17.    /*******************************/
18.   
19.    wire [7:0]Q_U1;
20.   
21.    flashing_to_right U1
22.    (
23.        .CLK( CLK ),       // input - from top
24.        .RSTn( RSTn ), // input - from top
25.        .Start_Sig( Right_Start_Sig ),  // input - from top
26.        .Done_Sig( Right_Done_Sig ),  // output - to top
27.        .Q( Q_U1 ) // output - to wire
28.    );
29.   
30.    /********************************/
31.   
32.    wire [7:0]Q_U2;
33.   
34.    flashing_to_left U2
35.    (
36.        .CLK( CLK ),              // input - from top
37.        .RSTn( RSTn ),             // input - from top
38.        .Start_Sig( Left_Start_Sig ),   // input - from top
39.        .Done_Sig( Left_Done_Sig ), // output - to top
40.        .Q( Q_U2 ) // output - to wire
41.    );
42.   
43.    /*************************************/
44.     
45.    reg [7:0]rQ;
46.   
47.    always @ ( * )
48.    if( Right_Start_Sig ) rQ = Q_U1;
49.    else if( Left_Start_Sig ) rQ = Q_U2;
50.    else rQ = 3'dx;
51.      
52.    assign Q = rQ;  
53.   
54.    /*************************************/
55.   
56.endmodule   

为了解决多“两义性”或者“多义性”的问题多路选择器常常被使用。如上述代码中在45~52行(从第27,第40行引出“连线”)“Q_U1”和“Q_U2”被if控制着输出。这样的写法是最优化的,生成的RTL图也非常的整洁。

点击浏览下一页

当然还有其他的写法:

assign Q = Right_Start_Sig ? Q_U1 : Q_U2 ;

虽然如上的写法和,第45到52行的写法相比,更为简洁,而且生成的 RTL图也一样。但是这样的写法有如下的弱点:

1. 解读性很差。
2. 只能解决两义性的问题而已。

所以不怎么推荐使用。

还有一中更糟糕的写法:

    reg [7:0]rQ;
   
    always @ ( * )
    case( { Right_Start_Sig, Left_Start_Sig } )
        2'b10   : rQ = Q_U1;
        2'b01   : rQ = Q_U2;
        default : rQ = 3'bxxx;
    endcase
      
assign Q = rQ;


虽然该写法的解读性很高效果也一样,但是却很浪费资源。生成的RTL图如下:

点击浏览下一页

和上述两个写法相比,它可差多了,所以不推荐使用。

/**********************************************************/

    reg [7:0]rQ;
   
    always @ ( * )
    if( Right_Start_Sig ) rQ = Q_U1;
    else if( Left_Start_Sig ) rQ = Q_U2;
    else rQ = 3'dx;
      
assign Q = rQ;  

接下来,我们来分析上面的代码。


    always @ ( * )


“always @ ( * )”这样的写法在Verilog HDL 2001 中已经被支持(好像是这个版本)。在敏感包中的“*”,可以理解为“任何状况都有效”。


    if( Right_Start_Sig ) rQ = Q_U1;
    else if( Left_Start_Sig ) rQ = Q_U2;
else rQ = 3'dx;  //不能省略掉


而“else rQ = 3'dx”,这行不能被省略掉。不要问我为什么,这是V语言的编程规则。你尝试注释掉后,再编译看看,你会发现会很多“Warning”。

   
       always @ ( * )
   x   if( Right_Start_Sig ) Q = Q_U1;//连线 Q,Q_U1 和 Q_U2 之间没有
   x   else if( Left_Start_Sig ) Q = Q_U2; //寄存器驱动
   x   else Q = 3'dx;


还有一点请注意,因为“Q_U1”和“Q_U2”是连线的关系,所以必须使用寄存器来驱动。如上的代码中“rQ”便是扮演这样的角色。如果该寄存器被省略了,会出现编译错误。

总结:
“两义性”或者“多义性”的问题,不仅在“低级建模”中出现,日常的建模也会出现它们的踪影,然而“低级建模”出现的频率比较高罢了。“多路选择器”在设计的时候应该经多方面的考虑,亦即取得最平衡的效果。
Sunlife 发表于 2014-8-15 21:41:51 | 显示全部楼层
,使用“多路选择器”便可以。
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2024-12-26 13:24 , Processed in 0.058052 second(s), 20 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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