如上图所示,systemverilog/verilog的语法有很多(verilog是sv的一个子集),但是对于FPGA开发者来说,是不需要完全掌握的,就语法而言仅需要掌握:
1、数据类型:wire/reg/parameter
2、运算符:算数、逻辑、关系、条件、移位、拼接等
3、语句:if..else case generate
4、结构 begin ... end
至于其他的一些语法对于FPGA开发是不需要的,比如:
数据类型:integer/logic
语句:for while
结构:fork..join等
函数、任务
// ============================================================
// File Name: FPGA干货分享
// VERSION : V1.0
// DATA : 2022/7/20
// Author : sun
// ============================================================
// 功能:verilog语法学习模板
// ============================================================
module verilog_template #(
parameter C_DATA_WITH = 16, ///数据位宽
parameter C_DATA_LENG = 16) ///数据长度
(
input wire i_clk_in , // clk
input wire i_rst_n , // 复位 低有效
input wire [C_DATA_WITH-1:0] i_data_a , // 输入
input wire [C_DATA_WITH-1:0] i_data_b , // 输入
input wire [2:0] i_data_sel , // 输入
input reg [C_DATA_WITH-1:0] o_data_out // 输出
);
// ============================================================
// 本地参数
// ============================================================
localparam C_DATA_WITH_LOCAL = C_DATA_WITH +1;
// ============================================================
// wire reg 信号声明
// ============================================================
wire [C_DATA_WITH_LOCAL-1:0] s_data_a ;
wire [C_DATA_WITH_LOCAL-1:0] s_data_b ;
reg [C_DATA_WITH_LOCAL-1:0] s_data_add ;
wire [C_DATA_WITH_LOCAL-1:0] s_data_add_move ;
reg [C_DATA_WITH-1:0] s_data_sub ;
wire [C_DATA_WITH-1:0] s_data_sub_wire ;
wire [C_DATA_WITH-1:0] s_data_and ;
wire [C_DATA_WITH-1:0] s_data_or ;
wire [C_DATA_WITH-1:0] s_data_not ;
wire s_bit_and ;
wire s_bit_or ;
wire s_bit_not ;
wire s_bit_cut_and ;
wire s_bit_cut_or ;
wire [C_DATA_WITH-1:0] s_data_or_gen ;
// ============================================================
// 赋值、拼接
// ============================================================
assign s_data_a = {i_data_a[C_DATA_WITH],C_DATA_WITH};
assign s_data_b = {i_data_b[C_DATA_WITH],C_DATA_WITH};
// ============================================================
// always 块 if...else
// ============================================================
always @(posedge i_clk_in)
if(!i_rst_n)
begin
s_data_add <= {C_DATA_WITH_LOCAL{1'b0}};
end
else
begin
s_data_add <= s_data_a + s_data_b;
end
// ============================================================
// 移位操作
// ============================================================
assign s_data_add_move = (s_data_add>>1);
// ============================================================
// always 块 if...else (if ... else..)
// ============================================================
always @(posedge i_clk_in)
if(!i_rst_n)
begin
s_data_sub <= {C_DATA_WITH{1'b0}};
end
else
begin
if(i_data_a >= i_data_b)
begin
s_data_sub <= i_data_a - i_data_b;
end
else
begin
s_data_sub <= i_data_b - i_data_a;
end
end
// ============================================================
// 条件运算符
// ============================================================
assign s_data_sub_wire = (i_data_a >= i_data_b) ? (i_data_a - i_data_b) : (i_data_b - i_data_a) ;
// ============================================================
// 位运算符:~,|,·,&
// ============================================================
assign s_data_and = i_data_a & i_data_b;
assign s_data_or = i_data_a | i_data_b;
assign s_data_not = ~i_data_a ;
// ============================================================
// 逻辑运算符:&&,||,!
// ============================================================
assign s_bit_and = i_data_a && i_data_b;
assign s_bit_or = i_data_a || i_data_b;
assign s_bit_not = !i_data_a ;
// ============================================================
// 缩减运算符:&,|
// ============================================================
assign s_bit_cut_and = &i_data_a ;
assign s_bit_cut_or = |i_data_b ;
// ============================================================
// 缩减运算符:生成语句
// ============================================================
genvar i;
generate (for i=0;i<C_DATA_WITH;i=i+1)
begin : LOOP
s_data_or_gen[i] = i_data_a[i] || i_data_b[i];
end
endgenerate
// ============================================================
// always 块 if...else
// ============================================================
always @(posedge i_clk_in)
if(!i_rst_n)
begin
o_data_out <= {C_DATA_WITH{1'b0}};
end
else
begin
o_data_out <= s_data_add_move[0+:C_DATA_WITH];
end
// ============================================================
// always 块 if...else
// ============================================================
always @(posedge i_clk_in)
case (i_data_a[2:0])
3'd0 : o_data_out <= s_data_and ;
3'd1 : o_data_out <= s_data_or ;
3'd2 : o_data_out <= s_data_not ;
default : o_data_out <= o_data_out ;
endmodule