热度 2| ||
本文是针对在写项目中遇到的verilog代码写法错误,多对一和一对多赋值问题,从逻辑赋值的角度理解为何会编译出错。并在后续讨论了if-else和case的电路结构和区别。在此处列出来供大家一起交流学习。
always @(posedge clk or negedge rstn)begin
if(!rstn)begin
REG1 <= 'd0;
REG2 <= 'd0;
end
else begin
if(write) begin
case(paddr)
'h54321 : REG1 <= pwdata; //在32'h54321写入pwdata
'h12345 : REG2 <= pwdata; //在32'h12345写入pwdata
default begin
REG1 <= REG1 ;
REG2 <= REG2 ;
end
endcase
//另一种写法
//REG1 <= (paddr == 'h54321) ? pwdata : REG1; //在32'h54321写入pwdata
//REG2 <= (paddr == 'h12345) ? pwdata : REG2; //在32'h12345写入pwdata
end
else begin
REG1 <= REG1;
REG2 <= REG2;
end
end
end
always @(posedge clk or negedge rstn)begin
if(!rstn)begin
prdata <= 'd0;
end
else begin
if(read) begin
case(paddr)
'h54321 : prdata <= REG1; //在32'h54321读出prdata = REG1
'h12345 : prdata <= REG2; //在32'h12345读出prdata = REG2
default : prdata <= prdata;
endcase
//注意下面这种写法是错误的(2.1.3中会分析)
//prdata <= (paddr == 'h54321) ? REG1 : prdata;
//prdata <= (paddr == 'h54321) ? REG2 : prdata;
end
else begin
prdata <= prdata;
end
end
end
即写成:
always @(posedge clk or negedge rstn)begin
if(!rstn)begin
prdata <= 'd0;
end
else begin
if(read) begin
//注意多对一中,下面这种写法是错误的
prdata <= (paddr == 'h54321) ? REG1 : prdata;
prdata <= (paddr == 'h54321) ? REG2 : prdata;
end
else begin
prdata <= prdata;
end
end
end
由此我们可以知道三目运算符和case并不等价,如果改写成if-else多层嵌套语句,编译没有出错误。
always @(posedge clk or negedge rstn)begin
if(!rstn)begin
prdata <= 'd0;
end
else begin
if(read) begin
if(paddr == 'h54321)begin
prdata <= REG1;
end
else begin
if(paddr == 'h54321)begin
prdata <= REG2;
end
else begin
prdata <= prdata;
end
end
end
else begin
prdata <= prdata;
end
end
end
下面进一步分析if-else和case语句的区别来分析。
每个if-else就是一个2选1mux器。当信号有明显优先级时,首先要考虑if-else,但是if嵌套过多也会导致速度变慢;if语句结构较慢,但占用面积小。
嵌套的if语句如果使用不当,就会导致设计的更大延时,为了避免较大的路径延迟,最好不要使用特别长的嵌套if结构。如想利用if语句来实现那些对延时要求苛刻的路径时,应将最高优先级给最迟到达的关键信号。
case语句综合为 n选1的mux电路。适用于无明显优先级的逻辑判断,即这些逻辑条件都处于同一个优先级且互斥;case结构电路速度较快,但占用面积较大。
if-else:组合逻辑和时序逻辑中的always语句块中实现是不同的。
组合逻辑中:if缺少else 时,会有latch;
时序逻辑中:尽管缺少else,依旧是D触发器,不存在latch。
case语句:case列举不全并且还没写default语句,则会综合出锁存器。所以一定写default,无论是组合还是时序逻辑。
总结:保证if-else对应齐全;case必写default。
对于这个的讨论,本人认为是以前由于综合工具落后,导致有区别,但是随着综合工具的更新,他们之间的区别越来越小,甚至有人可以用if-else综合出无优先级的多路选择器,用case综合出有优先级的多路选择器。
放出eetop一个经典的讨论:
https://bbs.eetop.cn/thread-392380-2-2.html
“if-else的逻辑判别是有优先级的,而case的逻辑判断条件是并列的。
举个例子,如果你用IF实现译码器,综合出的是有优先级的译码器。如果用CASE,综合出的就是一个无优先级的译码器。也就是说IF是有优先级的,执行的次序有先后。而CASE执行的时候是没有先后顺序的。”
“随着综合工具的进步,已经不需要讨论if-else 和case的区别了,两者可以等同 ”
“Verilog 2001标准(IEEE 1364-2001)第132页:
The case item expressions shall be evaluated and compared in the exact order in which they are given.
指出了case是串行有优先级。又:
Apart from syntax, the case statement differs from the multiway if-else-if construct in two important ways:
a) The conditional expressions in the if-else-if construct are more general than comparing one expression with several others, as in the case statement.
b) The case statement provides a definitive result when there are x and z values in an expression.
a)是废话。b)指出了case是四态对比。除此之外和if-else没有差别。”