verilog编程艺术(提升代码灵活性)

        verilog中有许多语法,可以用来提升代码灵活性,特别是重复的代码逻辑,或者for循环展开等等,这里总结了这些语法,你不来看看吗?

一、verilog参数例化

1、parameter

        parameter参数是一种用于定义常量的语言元素。可以在模块实例化时使用,用于设置模块的参数值。parameter参数可以用于定义数字类型的常量,也可以在模块内部使用。使用parameter参数可以让代码更加灵活和可重用。

        parameter使用示例如下:

//模块定义module raw#( parameter DWIDTH=128,parameter AWIDTH=32)(input clk,input wr_en,input [AWIDTH-1] wr_addr,input [DWIDTH-1:0] wr_data,input rd_en,input [AWIDTH-1] rd_addr,output [DWIDTH-1:0] dout);..................
endmodule 
//模块例化ram#( .DWIDTH(128), .AWIDTH(10))ram_u(.clk(wclk),.wr_en(wr_en),.wr_addr(wr_addr),.wr_data(wr_data),.rd_en(rd_en),.ren(read_en),.rd_addr(rd_addr),.dout(dout));

2、localparam

        localparam用于模块内部定义常量,特别是模块名已定义了parameter属性时,模块内部使用常量,需要用localparam来定义。

localparam DATA_WIDTH = 10;localparam SHIFT_WIDTH = 10;

二、generate语句

        Verilog中的generate语句可以生成重复结构的代码块,例如模块实例、寄存器或电路组件等等,在设计大型系统时非常有用,可提高写代码效率。

        Generate语句还可以与if、case等条件语句结合使用,以生成更加复杂的结构。

1、generate for语句

格式:​​​​​​​

localparam WIDTH = 10;localparam NUM = 6;genvar i;wire [WIDTH-1:0] data [0:NUM]
generate    for(i=0; i<NUM; i=i+1) begin:循环体名称      //循环内容   end endgenerate

示例:​​​​​​​

module genrate_test(    input clk,    input reset,    input [5:0] data_i,    output [6:0] data_o);
//参数定义localparam NUM = 6;reg [6:0] tmp_r [0:NUM-1];
assign tmp_r[0] = data_i;
generate    for(i=1; i<NUM; i=i+1) begin:test_cal//循环体名称      //循环内容     assign data[i] = data[i-1] + NUM;   end endgenerate

2、generate if语句

格式:​​​​​​​

 generate      if (<condition>) begin: <label_1>         <code>;//语句或者模块      end else if (<condition>) begin: <label_2>         <code>;//语句或者模块      end else begin: <label_3>         <code>;//语句或者模块      end   endgenerate

示例:​​​​​​​

module genrate_test#(    parameter MODE = 0)(    input clk,    input reset,    input [5:0] data0_i,    input [5:0] data1_i,    output [6:0] data_o);
//参数定义localparam NUM = 6;
generate    if(MODE) begin:MODE0       asssign data_o = data0_i + data1_i;   end else begin:MODE1       asssign data_o = data0_i - data1_i;   end              endgenerate
endmodule

三、function

        Verilog中的function语句是用来定义函数的,通常用于执行一些重复的操作,例如计算逻辑等等。

        function语句有如下特征:

  • 只能返回一个值,不能更改模块中的其他变量。

  • 包含组合逻辑,不能包含时序逻辑(即不能使用always)。

下面是一个简单的例子,展示了如何使用function语句:​​​​​​​

module my_module (  input [7:0] a,  input [7:0] b,  output [7:0] result);
function [7:0] adder;  input [7:0] x, y;  begin    adder = x + y;  endendfunction
assign result = adder(a, b);
endmodule


        注意:在function语句内部使用的变量只在该语句内部有效,不能在模块的其他部分访问。

四、比特位选择

        比特位选择,可以让代码更简洁,适用于重复性逻辑代码。

        注意比特位选择中的位号、位范围必须是常量表达式,不允许使用变量。

DATA_WIDTH,常数,表示位宽index,常数,序号data[index*DATA_WIDTH+:16];  等价于 data[(index + 1)*DATA_WIDTH-1:index*DATA_WIDTH]; 

说明:index = 0时,data[15:0];index = 1时,data[31:16]。

代码示例:​​​​​​​

genvar i; generate for(i=0;i<16;i=i+1) begin:data_save
always@(posedge clk or posedge rst) begin      if(rst)         data_save[(i*16)+:15]<= ’b0;      else         data_save[(i*16)+:16]<= data_in ;endend endgenerate

五、宏定义

1、宏定义`define

        用于定义常量,需用在module外面或者verilog header文件,可用于多个模块调用,用法如下所示。​​​​​​​

`define FILE_PATH  "../../file_path"`define NULL 0

2、条件编译语句`ifdef `ifndef

        可用于选择不同代码块的有效状态,有助于提高模块的复用性。​​​​​​​

`ifdef  FOR_FPGA  //如果定义了FOR_FPGA宏,则会执行如下    //语句/或者没有语句`else            //如果没有定义FOR_FPGA宏,执行如下语句    //语句/或者没有语句 `endif         //结束
`ifndef  FOR_FPGA  //如果没有定义了FOR_FPGA宏,则会执行如下    //语句/或者没有语句`else             //如果定义了FOR_FPGA宏,执行如下语句    //语句/或者没有语句 `endif       //结束

六、case、casex、casez

1、case语句

        case语句中的敏感表达式中与各项值之间的比较是一种全等比较,每一位都相同才认为匹配。

        case 语句格式如下:​​​​​​​

case(case_expr)    condition1     :             true_statement1 ;    condition2     :             true_statement2 ;    ……    default        :             default_statement ;endcase

小tips:

  • default 语句是可选的,且在一个 case 语句中只能有一个 default 语句。

  • case 语句支持嵌套使用。

代码示例:​​​​​​​

module mux4to1(input clk,input [1:0] sel ,input [1:0] p0 ,input [1:0] p1 ,input [1:0] p2 ,input [1:0] p3 ,output reg [1:0] sout);     always @(posedge clk) begin        case(sel)            2'b00:   sout <= p0 ;            2'b01:   sout <= p1 ;            2'b10:   sout <= p2 ;            default: sout <= p3 ;        endcase    endendmodule

2、casez语句

        casez语句中,如果分支表达式某些位的值为高阻z,那么就忽略这些位的比较,而只关注其他位的比较结果。

        casez语句中需要忽略的bit位给“z”即可,该语句可综合.

        代码示例:​​​​​​​

wire sel [5:0] ;always@(posedge clk) begin  casez(sel)  6’bzzzzz1: data_out <= data_in0 ;  6’bzzzz1z: data_out <= data_in1 ;  6’bzzz1zz: data_out <= data_in2 ;  default : data_out <= 4’b0 ;  endcaseend

        也可以换case语句来实现​​​​​​​

wire sel [5:0] ;always@(posedge clk) begin  casez(1'b1)  sel[0]: data_out <= data_in0 ;  sel[1]: data_out <  sel[2]: data_out <= data_in2 ;  default : data_out <= 4’b0 ;  endcaseend

3、casex语句

        这种处理方式进一步扩展到对x的处理,即如果比较双方有一方的某些位的值是z或x,那么这些位可忽略。

        注意:casex语句不可综合,一般用于仿真测试激励中。​​​​​​​

casex(sel)  2’b00:  data_out = data_in0 ;  2’b01:  data_out = data_in1 ;  2’bx0:  data_out = data_in2 ;  2’bz0:  data_out = data_in3 ;  2’b1?:  data_out = data_in4 ;  default: data_out = data_in5 ;endcase  
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值