打印
[Verilog HDL]

Verilog几个这样的写法

[复制链接]
9479|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gaochy1126|  楼主 | 2023-8-31 22:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
数字电路设计主要就是,选择器、全加器、比较器,几个常用逻辑门,再加个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



使用特权

评论回复

相关帖子

沙发
地瓜patch| | 2023-8-31 23:01 | 只看该作者
阻塞非阻塞

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:这个社会混好的两种人:一是有权有势,二是没脸没皮的。

1050

主题

11299

帖子

26

粉丝