HDL Compiler:parallel_case综合指令的使用
相关阅读
HDL Compilerhttps://blog.csdn.net/weixin_45791458/category_12893238.html?spm=1001.2014.3001.5482
综合指令(Synthesis Directives)是一些特殊注释,用于影响综合工具如何处理RTL代码,这些注释会被综合工具识别,但会被其他工具(如仿真器)忽略。关于综合指令相关概念的更多介绍,可以参考下面的博客。
HDL Compiler:综合指令https://chenzhang.blog.csdn.net/article/details/148695750
在阅读本文之前,建议先学习case语句的使用,如下面这篇博客所示。
Verilog基础:case类语句(case、casex和casez)https://chenzhang.blog.csdn.net/article/details/130125464在学习parallel_case综合指令前,首先来看一下什么是平行(parallel)和不平行的case语句。
平行的case语句
平行的case语句指的是每个可能的case expression的取值只有一个case item与之匹配。一般来说,如果case语句平行,则不会综合出优先级结构(优先级结构是确保最先匹配的分支优先执行)。
例1展示了一个平行的case语句,case item之间是互斥的,sel信号最多取其中一种,图1是例1的综合结果。
// 例1 module mux(y, a, b, c, sel); output reg y; input [1:0] sel; input a, b, c; always@(*) case (sel) 2'b00: y = a; 2'b01: y = b; 2'b10: y = c; 2'b11: y = 1'b0; endcase endmodule图1 例1的综合结果
例2展示了一个平行的casez语句,并在case item中使用了?表示对该位不关心(效果就象是通配符),case item之间是互斥的,图2是例2的综合结果。
// 例2 module mux(y, a, b, c, sel); output reg y; input [2:0] sel; input a, b, c; always@(*) casez (sel) 3'b1??: y = a; 3'b01?: y = b; 3'b001: y = c; default: y = 1'b0; endcase endmodule图2 例2的综合结果
实际上,例2中的casez语句的综合结果相当于一个如例3所示的case语句。
// 例3 module mux(y, a, b, c, sel); output reg y; input [2:0] sel; input a, b, c; always@(*) case (sel) 3'b100, 3'b101, 3'b110, 3'b111: y = a; 3'b010, 3'b011: y = b; 3'b001: y = c; default: y = 1'b0; endcase endmodule不平行的case语句
不平行的case语句指的是每个可能的case expression的取值存在多个case item与之匹配。一般来说,如果case语句不平行,则会综合出优先级结构(优先级结构是确保最先匹配的分支优先执行)。
例4展示了一个不平行的case语句,case item之间出现了重合,sel信号可能满足多个分支的要求,图3是例4的综合结果。
// 例4 module mux(y, a, b, c, sel); output reg y; input [2:0] sel; input a, b, c; always@(*) casez (sel) 3'b1??: y = a; 3'b?1?: y = b; 3'b??1: y = c; default: y = 1'b0; endcase endmodule图3 例4的综合结果
实际上,例4中的casez语句的综合结果相当于一个如例5所示的case语句。
// 例5 module mux(y, a, b, c, sel); output reg y; input [2:0] sel; input a, b, c; always@(*) case (sel) 3'b100, 3'b101, 3'b110, 3'b111: y = a; 3'b010, 3'b011, 3'b110, 3'b111: y = b; 3'b001, 3'b011, 3'b101, 3'b111: y = c; default: y = 1'b0; endcase endmoduleparallel_case综合指令
parallel_case综合指令的语法如下所示。
case(***) //synopsys parallel_case ***:*** ***:*** endcase每个parallel_case指令会导致其指定的case语句被认为是平行的,如果case语句本不平行,那些重合的分支中,信号将被视为不关心,此时重合部分的综合结果(即sel为101、110、111、011时)由综合工具决定,图4是例6的综合结果。
// 例6 module mux(y, a, b, c, sel); output reg y; input [2:0] sel; input a, b, c; always@(*) casez (sel) //synopsys parallel_case 3'b1??: y = a; 3'b?1?: y = b; 3'b??1: y = c; default: y = 1'b0; endcase endmodule图4 例6的综合结果
实际上,例6中的casez语句的综合结果相当于一个如例7所示的case语句。
// 例7 module mux(y, a, b, c, sel); output reg y; input [2:0] sel; input a, b, c; always@(*) case (sel) 3'b100: y = a; 3'b010: y = b; 3'b001: y = c; 3'b101, 3'b110, 3'b111, 3'b011: y = 1'bx; default: y = 1'b0; endcase endmodule如果读者熟悉显式赋x带来的问题,就一定知道为什么建议谨慎使用parallel_case综合指令,它们都会造成前后仿真的不一致:对于显式赋x而言,仿真时结果为x,但综合后结果取决于综合工具,但绝不会是x;对于使用parallel_case综合指令,仿真时表现为优先级结构,但综合后结果不会出现优先级结构。
例8展示在一个反向case语句中使用parallel_case指令,图5是例8的综合结果,如果不使用parallel_case综合指令,当current_state为4'b1001时优先考虑第一个分支,这会导致综合结果出现优先级结构。
// 例8 module one_hot_fsm (current_state, next_state); input [3:0] current_state; output [3:0] next_state; reg [3:0] next_state; parameter STATE1 = 4'b0001; parameter STATE2 = 4'b0010; parameter STATE3 = 4'b0100; parameter STATE4 = 4'b1000; always @(*) case (1) // synopsys parallel_case current_state[0]: next_state = STATE1; current_state[1]: next_state = STATE2; current_state[2]: next_state = STATE3; current_state[3]: next_state = STATE4; default: next_state = 4'b0000; endcase endmodule图5 例8的综合结果
写在最后
如果读者非常明白parallel_case指令的工作机制,且明确自己的意图,那么可以使用它。