ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Verilog几个这样的写法-转自 宁河川

2021-08-17 23:34:56  阅读:289  来源: 互联网

标签:case begin end data 转自 Verilog shift 写法 out


数字电路设计主要就是,选择器、全加器、比较器,几个常用逻辑门,再加个D触发器,电路基本都能实现了。

组合逻辑+时序逻辑

组合逻辑用assign或always@(*)实现,

时序逻辑用always@(posedge clk or negedge rst_n)

有人说掌握Verilog 20%的语法就可以描述 90%以上的电路,说的对。

casez

 1 always @(*)begin
 2     casez(code)
 3         8'b1???_???? : data[2:0] = 3'd7;
 4         8'b01??_???? : data[2:0] = 3'd6;
 5         8'b001?_???? : data[2:0] = 3'd5;
 6         8'b0001_???? : data[2:0] = 3'd4;
 7         8'b0000_1??? : data[2:0] = 3'd3;
 8         8'b0000_01?? : data[2:0] = 3'd2;
 9         8'b0000_001? : data[2:0] = 3'd1;
10         8'b0000_0001 : data[2:0] = 3'd0;
11         default : data[2:0] = 3'd0;
12     endcase
13 end

这样的case有优先级选择,虽然可综合,但是不推荐使用,有优先用if-else,没有直接用case。

synopsys的EDA工具有关于full case与parallel case可以查看下面博客链接。

https://blog.csdn.net/li_hu/article/details/10336511

 

generate+for

合理使用generate+for循环可以提高编码效率,同样的赋值语句需要赋值多次。

1 generate
2     genvar i;
3     for(i=0;i<16;i=i+1)
4         begin: neg_data
5             assign neg_data_out[i*DATA_WIDTH +:DATA_WIDTH] = 
6                 -data_in[i*DATA_WIDTH +:DATA_WIDTH]
7         end
8 endgenerate

同一个模块需要实例化多次

 1 generate 
 2     genvar i;
 3     for(i=0;i<16;i=i+1)
 4         begin: mult_12x12
 5             DW02_mult #(
 6                 .A_WIDTH(12),
 7                 .B_WIDTH(12)
 8             ) u_DW02_mult0(
 9                 .A(mult_a[i*12 +:12]),
10                 .B(mult_b[i*12 +:12]),
11                 .TC(1'b0),
12                 .PRODUCT(product[i*24 +:24])
13             );
14         end
15 endgenerate

当然这样写debug会有一些困扰,Verdi会显示每一个generate块,选中对应的块,加进去的波形就会是对应的bit信号。

generate if/case

做一些通用IP的方法,比如要做一个选择器通用IP,支持二选一,三选一,四选一。

 1 generate if(MUX_NUM == 0)begin : mux4_1
 2     always@(*)begin
 3         case(sel[1:0])
 4                2'b00:data_out = data_in0;
 5             2'b01:data_out = data_in1;
 6             2'b10:data_out = data_in2;
 7             default:data_out = data_in3;
 8         endcase
 9     end
10 end else if(MUX_NUM = 1) begin : mux3_1
11     always@(*)begin
12         case(sel[1:0])
13                2'b00:data_out = data_in0;
14             2'b01:data_out = data_in1;
15             default:data_out = data_in2;
16         endcase
17     end
18 end else begin : mux2_1
19     always@(*)begin
20         case(sel[1:0])
21                2'b00:data_out = data_in0;
22             default:data_out = data_in1;
23         endcase
24     end
25 end endgenerate

generate case可以写更多的分支

 1 generate
 2     case(MUX_NUM)
 3         0:begin:mux_2
 4         end
 5         1:begin: mux_3
 6         end
 7         2:begin: mux_4
 8         end
 9         default:begin
10         end
11     endcase
12 end endgenerate

调用的时候只需要

1 mux #(
2     .MUX_NUM(0)
3 )
4 u_mux(
5     ...
6 );

参数化定义

模块化设计,功能模块的划分尽可能细, 差别不大的代码通过参数化达到重复使用的目的。

1 always @(*)begin
2     case(sel)
3         CASE0:data_out = data_in0;
4         CASE1:data_out = data_in1;
5         CASE2。。。
6         default:;
7     endcase    
8 end

实例化

1 mux #(
2     .CASE0(8'd11),
3     .CASE1(8'd44)
4     ...
5 )
6 u_mux(
7     ...
8 );

移位操作

对于移位操作直接用位拼接,

1 assign data_shift[6:0] = data[4:0] << 2;
2 assign data_shift[7:0] = data[4:0] << shift[1:0];

写成

1 assign data_shift[6:0] = {data[4:0], 2'b0};
2 always @(*)begin
3     case(shift[1:0])
4         2'b00: data_shift[7:0] = {3'b0, data[4:0]};
5         2'b01: data_shift[7:0] = {2'b0, data[4:0], 1'b0};
6         2'b10: data_shift[7:0] = {1'b0, data[4:0], 2'b0};
7         default:data_shift[7:0] = {data[4:0], 3'b0};
8     endcase
9 end

如果是有符号数,高位要补符号位。也就是算术移位。

1 always @(*)begin
2     case(shift[1:0])
3         2'b00: data_shift[7:0] = {{3{data[4]}}, data[4:0]};
4         2'b01: data_shift[7:0] = {{2{data[4]}}, data[4:0], 1'b0};
5         2'b10: data_shift[7:0] = {data[4], data[4:0], 2'b0};
6         default:data_shift[7:0] = {data[4:0], 3'b0};
7     endcase
8 end

shift也可能是有符号数,正数左移,负数右移。右移方法同理。

$clog2系统函数

Verilog-2005引入了$clog2系统函数,为了方便计算数据位宽,避免位浪费。这个其实是来凑数的。

 1 parameter   DATA_WIDTH = 4,
 2 parameter   CNT_WIDTH  = log2(DATA_WIDTH)
 3 parameter   CNT_WIDTH  = clog2(DATA_WIDTH-1)
 4 parameter   CNT_WIDTH  = $clog2(DATA_WIDTH)
 5 
 6 reg   [DATA_WIDTH-1:0]   data_r0;
 7 
 8 reg     [CNT_WIDTH-1:0]   cnt;
 9 
10 //-------------------------------------------------------
11 //以下两个函数任用一个
12 //求2的对数函数
13 function integer log2;
14   input integer value;
15   begin
16     value = value-1;
17     for (log2=0; value>0; log2=log2+1)
18       value = value>>1;
19   end
20 endfunction
21 
22 //求2的对数函数
23 function integer clogb2 (input integer bit_depth);
24 begin
25     for(clogb2=0; bit_depth>0; clogb2=clogb2+1)
26         bit_depth = bit_depth>>1;
27 end
28 endfunction

最后

欢迎指点,有哪些Verilog的奇技淫巧,留言告诉我吧。

 

转自:https://ninghechuan.com/2020/03/14/2020-3-14-Verilog%E5%87%A0%E4%B8%AA%E8%BF%99%E6%A0%B7%E7%9A%84%E5%86%99%E6%B3%95/

标签:case,begin,end,data,转自,Verilog,shift,写法,out
来源: https://www.cnblogs.com/lcq-manji/p/15154757.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有