Verilog代码优化之case语句
题记:那天做完13路脉冲计数并写入dual RAM模块的设计后组长看了我的资源占用,吃惊的说怎么占用资源这么少啊,以为我偷工减料了。呵呵,其实这个也是一直困扰初学者的一个课题,可综合的verilog是一个,最优化的代码也是一个,所以就想说说这方面的问题,算是自己攒的一点经验分享吧,可能会有所欠缺或者说的不太对,还望EDN的各路高手指点。那就先从case语句和if…else语句开始吧。
module test_3(clk,rst_n,data,add);
input clk;
input rst_n;
input[3:0] data;
output[2:0] add;
reg[2:0] add;
always @ (posedge clk) begin
if(!rst_n) begin
add <= 0;
else begin
case(data)
0,1,2,3: add <= 1;
4,5,6,7: add <= 2;
8,9,10,11: add <= 3;
12,13,14,15: add <= 4;
default: ;
endcase
endmodule
资源占用情况:
Design Statistics
# IOs : 9
Macro Statistics :
# RAM : 1
# 16x3-bit single-port block RAM: 1
Cell Usage :
# BELS : 3
# GND : 1
# INV : 1
# VCC : 1
# RAMS : 1
# RAMB16_S36 : 1
# Clock Buffers : 1
# BUFGP : 1
# IO Buffers : 8
# IBUF : 5
# OBUF : 3
Selected Device : 3s50pq208-5
Number of bonded IOBs: 9 out of 124 7%
Number of BRAMs: 1 out of 4 25%
Number of GCLKs: 1 out of 8 12%
module test_3(clk,rst_n,data,add);
input clk;
input rst_n;
input[3:0] data;
output[2:0] add;
reg[2:0] add;
always @ (posedge clk) begin
if(!rst_n) begin
add <= 0;
else begin
casex(data)
4'b00xx: add <= 1;
4'b01xx: add <= 2;
4'b10xx: add <= 3;
4'b11xx: add <= 4;
default: ;
endcase
endmodule
资源占用情况:
Design Statistics
# IOs : 9
Macro Statistics :
# Registers : 1
# 3-bit register : 1
Cell Usage :
# BELS : 4
# INV : 2
# LUT2 : 2
# FlipFlops/Latches : 3
# FDR : 3
# Clock Buffers : 1
# BUFGP : 1
# IO Buffers : 6
# IBUF : 3
# OBUF : 3
Selected Device : 3s50pq208-5
Number of Slices: 2 out of 768 0%
Number of Slice Flip Flops: 3 out of 1536 0%
Number of 4 input LUTs: 2 out of 1536 0%
Number of bonded IOBs: 9 out of 124 7%
Number of GCLKs: 1 out of 8 12%
module test_3(clk,rst_n,data,add);
input clk;
input rst_n;
input[3:0] data;
output[2:0] add;
reg[2:0] add;
always @ (posedge clk) begin
if(!rst_n) begin
add <= 0;
else begin
if(data<4) add <= 1;
else if(data<8) add <= 2;
else if(data<12) add <= 3;
else add <= 4;
endmodule
资源占用情况:
Design Statistics
# IOs : 9
Macro Statistics :
# Registers : 3
# 1-bit register : 3
# Multiplexers : 1
# 3-bit 4-to-1 multiplexer : 1
# Comparators : 3
# 4-bit comparator less : 3
Cell Usage :
# BELS : 6
# INV : 1
# LUT2 : 4
# LUT3 : 1
# FlipFlops/Latches : 3
# FDR : 2
# FDRS : 1
# Clock Buffers : 1
# BUFGP : 1
# IO Buffers : 6
# IBUF : 3
# OBUF : 3
Number of Slices: 3 out of 768 0%
Number of Slice Flip Flops: 3 out of 1536 0%
Number of 4 input LUTs: 5 out of 1536 0%
Number of bonded IOBs: 9 out of 124 7%
Number of GCLKs: 1 out of 8 12%
结语:硬件设计和软件编程不同,在C语言里if…else和for循环满天飞,可以说用这两个语句打天下都是不成问题的,但是HDL设计中这是万万不可的。我们先分析上面的结果,从以上的代码综合后的占用资源情况对比,case语句和casex语句是差不多的,一般在设计中如果可以使用casex语句那就优先考虑,其次case语句也是很常用的,至于if…else语句,明眼人一看就知道,比case(x)语句多出的寄存器比较器如果是一个更高级的if…else嵌套那么无非对硬件资源是一个巨大的浪费,至于for语句,这里没有进行对比,虽然在很多的综合工具里这个语句是可综合的,但是因为它在设计中往往不是可以和case或者if…else语句互相代替使用,所以放在后面再讨论。
Verilog代码优化之case语句 题记:那天做完13路脉冲计数并写入dual RAM模块的设计后组长看了我的资源占用,吃惊的说怎么占用资源这么少啊,以为我偷工减料了。呵呵,其实这个也是一直困扰初学者的一个课题,可综合的verilog是一个,最优化的代码也是一个,所以就想说说这方面的问题,算是自己攒的一点经验分享吧,可能会有所欠缺或者说的不太对,还望EDN的各路高手指点。那就先从
背景描述:将一个独热码转换成二进制。
分析:由于当前使用的zynq是6输入的lut,设计一个较简单的12bit独热码转换为4bit的二进制。根据如下代码可以知道每一个bit都可以用一个lut解决问题。
第一版的代码:
assign binary_data = binary;
always @(posedge clk) begin
case
(...
这几天在做一个无人机定位的项目,时间比较紧,自己也不太懂,所以就边忙别愁就没有了精力写博客了。可是想想这样也不好,还是抽出点时间写博客,即使写的比较简单也行,至少能解答自己的疑惑就够了。
Verilog
HDL中的
case
语句
有两种变种,
case
x和
case
z,既然存在这两种形式,肯定是合理的,为了应对特殊的情况。我们只需要掌握其具体用法,需用用到的地方就用上,倒也不必考虑太多。(我见有些人还分...
1、资源共享
资源共享主要是指在互斥(Mutually-Exclusive) 条件下(即不能同时运行)共享算术逻辑单元(Arithmetic Logic Unit)。
module test(a, b, c, sel, result); //相同运算符没有资源共享
input [7:0) a, b, c;
input sel;
output [8:0] result;
reg [8:0] result;
always @ (a or b or sel)begin
if (sel)
result = a
转自:https://blog.csdn.net/CLL_caicai/article/details/104395480
实际问题中常常需要用到多分支选择,使用if
语句
导致内容繁琐;更明智的做法是使用
case
语句
,
case
语句
是一种多分支选择
语句
,可以方便的处理多分支选择。本文通过实际例子,讲解
case
语句
的使用,以及
case
语句
的变体
case
z和
case
x的使用:
一、
case
的用法
二、
case
z与
case
x的用法
三、参考文献
end
case
其中,expression是一个表达式,可以是任何
Verilog
数据类型,value1、value2等是
case
分支的值,statement1、statement2等是与分支对应的
语句
。default是可选的,表示当expression的值不匹配任何分支时执行的
语句
。
下面是一个例子,演示了如何使用
case
语句
实现一个4位二进制加法器:
module adder(input [3:0] a, b, output [3:0] sum);
reg [3:0] carry;
always @ (a, b) begin
case
({carry, a} + {carry, b})
2'b00: begin
sum = {carry[3:1], a[0]};
carry = {1'b0, carry[2:0]};
2'b01: begin
sum = {carry[3:1], ~a[0]};
carry = {1'b1, carry[2:0]};
2'b10: begin
sum = {carry[3:1], ~b[0]};
carry = {1'b1, carry[2:0]};
2'b11: begin
sum = {carry[3:1], a[0]};
carry = {1'b1, carry[2:0]};
default: begin
sum = 4'bxxxx;
carry = 4'bxxxx;
end
case
endmodule
在这个例子中,我们使用了
case
语句
来根据输入的a和b的值计算出输出的sum和进位carry的值。注意,我们使用了{carry, a}和{carry, b}来将进位和输入值组合成一个4位二进制数,以便于进行加法运算。同时,我们使用了~运算符来实现减法运算。如果输入的值不符合预期,我们将输出sum和carry设为xxxx,表示无效的值。