Verilog几个这样的写法

 

 

转载:https://zhuanlan.zhihu.com/p/114823546

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

组合逻辑+时序逻辑

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

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

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

casez

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

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

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

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

generate+for

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

 generate
     genvar i;
     for(i=0;i<16;i=i+1)
         begin: neg_data
             assign neg_data_out[i*DATA_WIDTH +:DATA_WIDTH] = 
                 -data_in[i*DATA_WIDTH +:DATA_WIDTH]
         end
 endgenerate

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

 generate 
     genvar i;
     for(i=0;i<16;i=i+1)
         begin: mult_12x12
             DW02_mult #(
                 .A_WIDTH(12),
                 .B_WIDTH(12)
             ) u_DW02_mult0(
                 .A(mult_a[i*12 +:12]),
                 .B(mult_b[i*12 +:12]),
                 .TC(1'b0),
                 .PRODUCT(product[i*24 +:24])
             );
         end
 endgenerate

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

generate if/case

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

 generate if(MUX_NUM == 0)begin : mux4_1
     always@(*)begin
         case(sel[1:0])
             2'b00:data_out = data_in0;
             2'b01:data_out = data_in1;
             2'b10:data_out = data_in2;
             default:data_out = data_in3;
         endcase
     end
 end else if(MUX_NUM = 1) begin : mux3_1
     always@(*)begin
         case(sel[1:0])
             2'b00:data_out = data_in0;
             2'b01:data_out = data_in1;
             default:data_out = data_in2;
         endcase
     end
 end else begin : mux2_1
     always@(*)begin
         case(sel[1:0])
             2'b00:data_out = data_in0;
             default:data_out = data_in1;
         endcase
     end
 end endgenerate

generate case可以写更多的分支

 generate
     case(MUX_NUM)
         0:begin:mux_2
         end
         1:begin: mux_3
         end
         2:begin: mux_4
         end
         default:begin
         end
     endcase
 end endgenerate

调用的时候只需要

 mux #(
     .MUX_NUM(0)
 )
 u_mux(
     ...
 );

 

参数化定义

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

 always @(*)begin
     case(sel)
         CASE0:data_out = data_in0;
         CASE1:data_out = data_in1;
         CASE2。。。
         default:;
     endcase    
 end

实例化

 mux #(
     .CASE0(8'd11),
     .CASE1(8'd44)
     ...
 )
 u_mux(
     ...
 );

移位操作

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

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

写成

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

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

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

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

$clog2系统函数

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

 parameter   DATA_WIDTH = 4,
 parameter   CNT_WIDTH  = log2(DATA_WIDTH)
 parameter   CNT_WIDTH  = clog2(DATA_WIDTH-1)
 parameter   CNT_WIDTH  = $clog2(DATA_WIDTH)
 ​
 reg   [DATA_WIDTH-1:0]   data_r0;
 ​
 reg     [CNT_WIDTH-1:0]   cnt;
 ​
 //-------------------------------------------------------
 //以下两个函数任用一个
 //求2的对数函数
 function integer log2;
   input integer value;
   begin
     value = value-1;
     for (log2=0; value>0; log2=log2+1)
       value = value>>1;
   end
 endfunction
 ​
 //求2的对数函数
 function integer clogb2 (input integer bit_depth);
 begin
     for(clogb2=0; bit_depth>0; clogb2=clogb2+1)
         bit_depth = bit_depth>>1;
 end
 endfunction

 给大家推荐一下这个宝藏博主,制作了很多干货

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值