一、语法
1、模块
module test(A,B,C,D,F1,F2); // test为模块名
input A,B,C,D; // 输入端口,默认为wire类型信号,一般都是wire
output F1,F2; // 输出端口,默认wire
wire F1; // 连线
reg [2:0] F2; // 3bit寄存器
endmodule
module top_module(
input a,
input b,
output out
);
// 模块实例化语法: 模块名 实例名(定义连接port的信号);
mod_a instance2 (.in1(a), .in2(b), .out(out)); // 即普通函数
endmodule
module top_module(input [7:0] in, output [7:0] out);
genvar i; // genvar i; 也可以定义在generate内部
generate
for(i = 0; i < 8; i++) begin: bit
assign out[i]=^in[8-1:i];
end
endgenerate
endmodule
2、赋值语句
对应wire,持续赋值语句
assign F = (A & B) | (A & C); // F = AB + AC
对应assign,可用if、case、for
always@(A or B) // A或B发生变化就执行后面语句
begin
if(A == B) // 只能在always块内
C <= 1;
else
C <= 0;
case(A) // 只能在always块内
2'b00 : B <= 1; // 2'b表示2位二进制
2'b01 : B <= 0;
2'b10 : B <= 1;
2'b11 : B <= 1;
default :B <= 0; // 当A为01时,输出B为0;A为00,10,11时为1
endcase
end
always@(posedge A) // 在A的上升沿时执行后面语句
begin
b <= 1'b1; // 1'b表示一位二进制,再例如4’b 1111表示四位二进制数1111
a <= b; // 非阻塞赋值(< =),b先赋值给a,b再变为1
end
always@(negedge B) // 在B的下降沿时执行后面语句
begin
b = 1'b1; // 阻塞赋值(=),a、b均为1
a = b;
end
3、逻辑运算
(1)逻辑运算符:&& (与)、==(相等)、||(或)、!=(不等)
m&&n :判断m和n是否全为真(非0即为真),真则输出1'b1,否则输出1'b0
最后输出结果只有1bit
(2)按位运算符:& 、| 、~ 、^ 、~& 、~^ 、~|
m&n : 是把m的每一位与n的每一位按位做与运算(4’b1010 & 4’b0101 = 4’b0000)
输出结果与m/n的bit数相同
(3)归约运算符:& 、| 、~ 、^ 、& 、~^ 、~|
只有一个参量参与运算时(&为一元运算符),表示规约与,即向量内部进行与运算
&a [3:0] // AND:a[3]&a[2]&a[1]&a[0] 相当于 (a[3:0] == 4'hf)
|b [3:0] // OR:b[3]|b[2]|b[1]|b[0] 相当于 (b[3:0] != 4'h0)
^c [2:0] // XOR:c[2]^c[1]^c[0]
即(&4’b0101 = 0&1&0&1 = 1'b0)
最后输出结果只有1bit
(4)其他:
条件运算符 “ ?:”
assign a = (b==3) ? 4 : 5; // 如果b=3,那就将4赋值给a,如果不等于就将5赋值给a;
拼接运算符 “ { , } ”
c = { a , b }; // 假设a=3’b011,b=3’b101,c的结果就为011101
// 但前提是c这个变量的位宽必须要大于6,如果他只有4bit位宽,那结果就变为1101。
二、常量
1、十进制整数 表示 整型常量
1)正数: 直接写 10 表示位宽为32bit的十进制整数(系统默认)
2)负数: -10需要用二进制补码表示,多了一位符号位(1 1010)
3)用科学计数法表示:12.345e3 表示 12345
2、基数法 表示 整数型常量
1) 二进制(b): 8'b1000_1100
当表示二进制时,最好每4位写一个下划线以增强可读性
当位宽大于二进制位数时左边自动补0,位宽小于二进制数时从左边截断
2)十六进制(h): 8'h8c
3)八进制(o): 8'o214
基数表示法中遇到x时:十六进制表示4个x,八进制中表示3个x
4)十进制(d): 8'140
3、字符串
每个字符由1个8位的ASCII码值表示,即需要1byte存储空间
eg. “Hello world” 字符串由11个ASCII符号构成,需要11byte存储空间
三、参数
参数的名称一般为大写,以区分其他变量
1、parameter(常量)
通常出现在module内部,常被用于定义状态、数据位宽等
只作用于声明的那个文件,且可以被灵活改变
parameter STATE = 1'b0;
2、localparam(局部参数)
只在本模块中使用
localparam STATE= 1'b1’;
四、向量(vector)
是一组信号的集合,可视为位宽超过1bit 的 wire 信号
1、定义方式
//输入输出型
input [7:0] a, b; // [upper:lower] 定义位宽,如 [7:0] 表示位宽为8 bit
output reg [7:0] out;
// 模块中间向量
wire [7:0] c, e;
reg [7:0] d;
2、向量片选
eg. 多路选择器:实现一个 256 选 1 选择器,sel 信号作为选择信号
当 sel = 0 时选择 in[3:0],sel = 1 时选择 in[7:4],以此类推
module top_module (
input [1023:0] in,
input [7:0] sel,
output [3:0] out
);
assign out = {in[sel*4+3], in[sel*4+2], in[sel*4+1], in[sel*4+0]}; // 直接一个个选
// or
assign out = in[sel*4 +: 4]; // 索引从 sel*4 开始的高4bit信号
// or
assign out = in[sel*4+3 -: 4]; // 索引从 sel*4+3 开始的低4bit信号
endmodule