从本文起,开始记录自己的学习历程,以便后续学习与分享。(希望大家一起学习,如有错误请指出)
2022年3月10日,于上海
目录
1.一个代码的大概组成
module top_module //top_module 是函数名 ( input a, inout,a1 output b );//声明输入和输出,输入输出变量 也就是I/O //内部信号说明 reg [n-1:0] c; wire [n-1:0] d; //功能定义 initial begin .... .... end always @(*)begin ...if()begin end else begin end ... end assign ... endmodule //和最开始的module 都是端口
下面是一个模拟时钟的例子
module top_module(
input clk,
input reset,
input ena,
output pm,
output [7:0] hh,
output [7:0] mm,
output [7:0] ss);
initial
begin
hh[7:4]=4'd1;
hh[3:0]=4'd2;
mm=0;
ss=0;
//pm=0;
end
always @(posedge clk)
begin
if(reset==0)
begin
if(ena==1)
begin
if(ss[3:0]<4'd9)
begin
ss[3:0]<=ss[3:0]+4'd1;
ss[7:4]<=ss[7:4];
mm<=mm;
hh<=hh;
end
else if(ss[3:0]==4'd9&&ss[7:4]!=4'd5)
begin
ss[3:0]<=0;
ss[7:4]<=ss[7:4]+4'd1;
mm<=mm;
hh<=hh;
end
else if(ss[3:0]==4'd9&&ss[7:4]==4'd5&&mm[3:0]!=4'd9)
begin
ss<=0;
mm[3:0]<=mm+4'd1;
mm[7:4]<=mm[7:4];
hh<=hh;
end
else if(ss[3:0]==4'd9&&ss[7:4]==4'd5&&mm[3:0]==4'd9&&mm[7:4]!=4'd5)
begin
ss<=0;
mm[3:0]<=0;
mm[7:4]<=mm[7:4]+4'd1;
hh<=hh;
end
else if(ss[3:0]==4'd9&&ss[7:4]==4'd5&&mm[3:0]==4'd9&&mm[7:4]==4'd5&&hh[3:0]<4'd9&&hh[7:4]!=1)
begin
ss<=0;
mm<=0;
hh[3:0]<=hh[3:0]+4'd1;
hh[7:4]<=hh[7:4];
end
else if(ss[3:0]==4'd9&&ss[7:4]==4'd5&&mm[3:0]==4'd9&&mm[7:4]==4'd5&&hh[3:0]==4'd9&&hh[7:4]!=4'd1)
begin
ss<=0;
mm<=0;
hh[3:0]<=0;
hh[7:4]<=hh[7:4]+4'd1;
end
else if(ss[3:0]==4'd9&&ss[7:4]==4'd5&&mm[3:0]==4'd9&&mm[7:4]==4'd5&&hh[3:0]<4'd1&&hh[7:4]==4'd1)
begin
ss<=0;
mm<=0;
hh[3:0]<=hh[3:0]+4'd1;
hh[7:4]<=4'd1;
end
else if(ss[3:0]==4'd9&&ss[7:4]==4'd5&&mm[3:0]==4'd9&&mm[7:4]==4'd5&&hh[3:0]==4'd1&&hh[7:4]==4'd1)
begin
ss<=0;
mm<=0;
hh[3:0]<=4'd2;
hh[7:4]<=4'd1;
pm<=~pm;
end
else
begin
ss<=0;
mm<=0;
hh<=8'd1;
end
end
else
begin
hh<=hh;
mm<=mm;
ss<=ss;
pm<=pm;
end
end
else
begin
hh[3:0]<=4'd2;
hh[7:4]<=4'd1;
mm<=0;
ss<=0;
pm<=0;
end
end
endmodule
2.变量
变量分为常量和变量
2.1首先是常量
数字/值
基本格式:<位宽>'<进制><数字>
进制有h/H,d/D,o/O,b/B
一些例子:
8'b10101001
4'd4(注意,尽管是十进制,但是最大范围的数字也是二进制4位宽的15)
-8'd5(负数要放在表达式的最前面)
16'b1010_1101_0011_0001(下划线之用于提高可读性)
与其他语言不同的Verilog有x和z值
x代表不定值,z是高阻值。一个x可以定义16进制数的4位状态,8进制的3位,2进制的1位,z还可以写成?的形式。在case表达中多用
一些例子:
4'b101z(位宽为4的2进制数,从低位起的第1位为高阻值)
12'dz(位宽为12的10进制数,其值为高阻值)
8'h4x(位宽为8的16进制数,其低4位为不定值)
参数parameter
基本格式:parameter 参数名1=表达式1,参数名2=表达式2,....;
参数名一般都是英文+下划线/数字这种表达形式,方便自己弄懂;
表达式必须是一个常数表达式,或之前已经定义过的表达式;
例子:
parameter me=2;(指的是10进制的7)
parameter byte_one=6,byte_onehalf=byte_one/2;
参数常用于定义延迟时间或变量宽度,在模块或者实例化引用中,可以通过参数来改变我们需要的变化的内容。
2.2接下来是变量
网络数据类型
wire [n-1 :0] a,d,e,f; (单个门驱动或连续赋值语句驱动)
tri [n-1:0] b,g,h,j; (多驱动器驱动)
寄存器
reg [n-1:0] a,b,c,d;
经常用在always中,同时always中被赋值的都要定义为reg型。
reg型一开始的默认值是不定的(可为负,可为正),但是在进行运算时,reg型的数据被当做正值来计算。
存储器(memory型)
reg [n-1:0] 存储器名 [m-1:0];
例子:
reg [7:0] memo [63:0] (定义了一个名为memo的存储器,该存储器有64个8位寄存器),存储器的地址范围是0到63.
给寄存器赋值可以是reg=1;但是个存储器赋值不可以是memo=1,必须是memo[1]=1,memo[2]=3;
3.运算符
运算符名称 | 运算符 | 优先级 |
---|---|---|
! ~ | 逻辑非 取反 | 高 |
* / % | 乘 除 取余 | |
+ - | 加 减 | |
<< >> | 左移位 右移位 | |
< <= > >= | 小于 小于等于 大于 大于等于 | |
== != === !== | 相等 不等 | |
& | 按位与 | |
^ ^~ | 按位异或 按位同或 | |
| | 按位或 | |
&& | 逻辑与 | |
|| | 逻辑或 | |
?: | 条件选择 | 低 |
一些比较特殊的运算符
位拼接运算符:{ 表达式或数字, 表达式或数字, ...,... ,... ,...... }
关于== 和=== 的区别是,==可以不考虑z和x,但是===必须完全相等才相等。
C=&B,C=|B...可以成为缩减运算符,即自己与自己或,自己与自己与,最后只剩下一位了。