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;
end
endfunction
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 ;
end
end
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
end
endmodule
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 ;
endcase
end
也可以换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 ;
endcase
end
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