verilog study-初级
目录
简介
语言要素和数据类型
语言要素
数据类型
运算符和表达式
优先级:
算术运算符:
关系运算符
相等关系运算符
规约运算符:
移位运算符:
条件运算符:
连接和复制运算符:
模块 module:
端口:
程序设计语句
数据流建模
行为级建模
可综合描述语句:
initial过程语句
always过程语句
语句块
过程赋值语句:
过程连续赋值语句
条件分支语句
循环语句
结构化建模
模块级建模
模块调用方式:
模块端口对应方式:
模块参数值
门级建模
开关级建模
组合电路设计
3个裁判的表决电路
case语句
逻辑代数方式
结构描述方式
抽象描述方式
数字加法器
真值表
代数逻辑表示为
4位超前进位加法器
数据比较器
数据选择器
数字编码器
8线-3线优先编码器
二进制转化十进制8421BCD编码器
8421BCD十进制余3码编码器
数字译码器
2线-4线译码器
奇偶校验器
时序电路设计
状态图描述
化简描述
抽象描述方式
触发器
最简D触发器
带复位端的D触发器
复杂功能的D触发器
T触发器
计数器
二进制计数器
任意进制计数器
移位寄存器
环形移位寄存器
序列信号发生器
由移位寄存器构成
由移位寄存器和组合逻辑电路构成
由计数器构成
有限同步状态机
状态机的编码方式:
状态机的两段式描述方法:
状态机的三段式描述方法:
4位顺序脉冲发生器
自动售报机
“11010”序列检测器
电路仿真和测试程序
语言要素
$display $write
$monitor 和 $strobe
$time 和 $realtime
$readmemh 和$readmemb
$random
VCD
十进制加法器
简介
本文将涉及verilog的设计方法,探索使用verilog hdl描述数字电路,探索verilog的语言特性。
内容总结于诚聘英才 > 在线课堂_西安电子科技大学微电子学院
【电子】Verilog硬件描述语言 西安电子科技大学 蔡觉平等主讲_哔哩哔哩_bilibili
语言要素和数据类型
语言要素
状态
|
含义
|
0
|
低电平、逻辑0或''假”
|
1 |
高电平、逻辑1或“真”
|
x或X
|
不确定或未知的逻辑状态
|
z或Z
|
高阻态
|
整数:+/-<size>'<base_format>number>
数制
|
基数符号
|
数字字符集
|
二进制
|
b或B
|
0、1、X、X、z、Z、?、_
|
八进制
|
o或O
|
0~7、X、X、z、Z、?、_
|
十进制
|
d或D
|
0〜9、_
|
十六进制
|
h或H
|
0~9、a〜f、A〜F、X、X、z、Z^ ?、_
|
注意事项:
- 在较长的数之间可以用下划线来分开
- 当数字没有说明位宽时,默认为32位
- x或z在二进制中代表1位x或z,在八进制中代表3位x或z,在十六进制中代表4位x或z
- 若没有定义一个整数的位宽,其宽度为相应值中定义的位数。
- 若定义的位宽比实际数的位数大,则在左边用0补齐。但如果数最左边一位为x或z,就相应地用x或z在左边补齐。如果定义的位宽比实际数的位宽小,那么最左边的位被截断。
- “?”是高阻态z的另一种表示符号。在数字的表示中,字符"?”和z或Z是等价的,可互相替代。
- 整数可以带正、负号,并且正、负号应写在最左边。负数表示为二进制的补码形式。-4等价于4'b1100
- 如果位宽和进制都缺省,则代表十进制数。
- 数字中不能有空格,但在表示进制的字母两侧可以有空格。
科学计数法:564.2e2的值为56420.0。
数据类型
标记符
|
名称
|
类型
|
强弱程度
|
supply
|
电源级驱动
|
驱动
|
1 |
strong
|
强驱动
|
驱动
|
2 |
pull
|
上拉级驱动
|
驱动
|
3 |
large
|
大容性
|
存储
|
4 |
weak
|
弱驱动
|
驱动
|
5 |
medium
|
中性驱动
|
存储
|
6 |
small
|
小容性
|
存储
|
7 |
highz
|
高容性
|
高阻
|
8 |
连线型:<net_declaration> <drive_strength><rangexdelay>[list_of_variables];
连线型数据类型
|
功能说明
|
wire, tri
|
标准连线型(缺省为该类型)
|
wor, trior
|
多重驱动时,具有线或特性的连线型
|
wand, trand
|
多重驱动时,具有线与特性的连线型
|
trireg
|
具有电荷保持特性的连线型(特例)
|
tri1
|
上拉电阻
|
tri0
|
下拉电阻
|
supply1
|
电源线,用于对电源建模,为高电平1
|
suppIy0
|
电源线,用于对“地”建模,为低电平0
|
wire 和 tri :
wire型变量通常用来表示单个门驱动或连续赋值语句驱动的连线型数据。
tri型变量则用来表示多驱动器驱动的连线型数据,主要用于定义三态的线网。
wire/tri
|
0
|
1
|
x | z |
0
|
0 | x | x | 0 |
1
|
x | 1 | x | 1 |
x | x | x | x | x |
z | 0 | 1 | x | z |
寄存器型:reg型:数据储存单元的抽象类型,能够存储数据,如触发器、锁存器等,
reg型变量:常用于行为级描述中,由过程赋值语句对其进行赋值。
格式:reg<range><list_of_register_variables>;
存储器型:存储器型(memory)本质上还是寄存器型变量阵列,存储器型变量可以描述RAM型、ROM型存储器以及reg文件。
用reg型变量建立寄存器组(数组)来实现存储器的功能
格式:reg<range 1><name_of_regisler><range2>;
抽象数据类型:
整型:integer<list_of_register_variables>;
整型数据常用于对循环控制变量的说明,在算术运算中被视为二进制补码形式的有符
时间型:lime<list_of_register_variables>;
时间型数据与整型数据类似,只是它是64位的无符号数。
实型:real<list_of_variables>;
参数型:parameter 参数名1=表达式1,参数名2 =表达式2, ...,参数名n =表达式n;
- 表达式既可以是常数,也可以是表达式。参数定义完以后,程序中出现的所有的参
- 另外,对于同一个模块来说,参数一旦被定义就不能够通过其它语句对它重新赋值。
运算符和表达式
优先级:
运算符
|
功 能
|
优先级别
|
!、~ |
反逻辑、位反相
|
1 |
*、/、%
|
乘、除、取模
|
2 |
+、-
|
加、减
|
3 |
<<、>>
|
左移、右移
|
4 |
<、<=、>、>=
|
小于、小于等于、大于、大于等于
|
5 |
==、!=、===、!== |
等、不等、全等、非全等
|
6 |
&
|
按位与
|
7 |
^、^~
|
按位逻辑异或和同或
|
8 |
I
|
按位逻辑或
|
9 |
&&
|
逻辑与
|
10 |
II
|
逻辑或
|
11 |
?: |
条件运算符,唯一的三目运算符,等同于if-else
|
12 |
算术运算符:
注意事项:
- 算术运算结果的位宽:算术表达式结果的长度由最长的操作数决定。
- 有符号数和无符号数的使用:
- 无符号数值一般存储在线网、reg(寄存器)型变量及普通(没有符号标记s)的基数格式表示的整型数中。
- 有符号数值一般存储在整型变量、十进制形式的整数、有符号的reg(寄存器)型变量及
有符号的线网中。
关系运算符
相等关系运算符
== | 0 | 1 | x | z |
0 | 1 | 0 | x | x |
1 | 0 | 1 | x | x |
x | x | x | x | x |
z | x | x | x | x |
===:
=== | 0 | 1 | x | z |
0 | 1 | 0 | 0 | 0 |
1 | 0 | 1 | 0 | 0 |
x | 0 | 0 | 1 | 0 |
z | 0 | 0 | 0 | 1 |
逻辑运算符:
a | b | !a | !b | a&&b | a||b |
1 | 1 | 0 | 0 | 1 | 1 |
1 | 0 | 0 | 1 | 0 | 1 |
0 | 1 | 1 | 0 | 0 | 1 |
0 | 0 | 1 | 1 | 0 | 0 |
按位运算符:
&:
& | 0 | 1 | x |
0 | 0 | 0 | 0 |
1 | 0 | 1 | x |
x | 0 | x | x |
|:
| | 0 | 1 | x |
0 | 0 | 1 | x |
1 | 1 | 1 | 1 |
x | x | 1 | x |
^:
^ | 0 | 1 | x |
0 | 0 | 1 | x |
1 | 1 | 0 | x |
x | x | x | x |
两个不同长度的数据进行位运算时,会自动地将两个操作数按右端对齐,位数少的操作数会在高位用0补齐,然后逐位进行运算,运算结果的位宽与操作数中位宽较大者相同。
规约运算符:
缩位运算符包括&(与)、I (或)、^(异或)以及相应的非操作~&、~|、~^、^~。
归约运算符的操作数只有一个。
移位运算符:
左移位运算符(<<)、右移位运算符(>>)。
条件运算符:
<条件表达式>?<表达式1>:<表达式2>
条件表达式的运算结果有真(1)、假(0)和不定态(x)三种。当条件表达式的结果为真时,
如果条件表达式的运算结果为不定态x,则模拟器将按位对表达式1的值与表达式2的值
?: | 0 | 1 | x | z |
0 | 0 | x | x | x |
1 | x | 1 | x | x |
x | x | x | x | x |
z | x | x | x | x |
连接和复制运算符:
连接运算符 {} :{信号1的某几位,信号2的某几位,信号n的某几位}。
复制运算符 {{}} :将一个表达式放入双重花括号中,复制因子放在第一层括号中。
模块 module:
端口:
声明方式:
输入端口: input[倩号位宽-1:0]端口名1;
输出端口: output[信号位宽-1:0]端口名1:
输入瀚出端口: inout[信号位宽-1:0]端口名1;
模块引用时端口的对应方式:
模块名(连接端口 1信号名,连接端口 2信号名…);
程序设计语句
数据流建模
- 赋值目标只能是线网类型(wire)。
- 在连续赋值中,只要赋值语句右边表达式任何一个变量有变化,表达式立即被计算, 计算的结果立即赋给左边信号(若没有定义延时量)。
- 连续赋值语句不能出现在过程块中。
- 多个连续赋值语句之间是并行关系,因此与位置顺序无关。
- 连续赋值语句中的延时具有硬件电路中惯性延时的特性,任何小于其延时量的信号变化脉冲都将被滤除掉,不会出现在输出端口。
行为级建模
可综合描述语句:
过程语句 always
语句块 串行语句块begin-end
赋值语句 过程赋值语句=、<=
条件语句 if-else case, casez, casex
循环语句 for
编译向导语句 'define 'include 'ifdef, 'else, 'endif
不可综合描述语句:
过程语句 initial
语句块 并行语句块fork-join
赋值语句 过程连续赋值语句assign
循环语句 forever repeat while
编译向导语句 'define 'include 'ifdef, 'else, 'endif
initial过程语句
initial过程语句通常用于仿真模块中对激励向量的描述,或用于给寄存器变量赋初值。
initial过程块在进行仿真时从模拟0时刻开始执行,它在仿真过程中只执行一次,在执
initialbegin语句I;语句2; 语句n;end
module initial_tb1:reg A, B, C;initialbeginA = 0;B= 1;C = O;#100 A= 1; B = 0;#100 A = 0;C= I;#100 B = 1;#100 B = 0; C = 0;end
endmodule
always过程语句
always@(<敏感事件列表>)语句块;@(a) //当信号a的值发生改变时
@(a or b) //当信号a或信号b的值发生改变时
@(posedge clock) //当clock的上升沿到来时
@(negedge clock) //当clock的下降沿到来时
@(posedge elk or negedge reset) //当clk的上升沿到来或reset信号的下降沿(低电平有效)到来时
注意事项:
- 在信号的形式定义方面,无论是对时序逻辑电路还是对组合逻辑电路进行描述,Verilog HDL要求在过程语句(initial和always)中,被赋值信号必须定义为“reg”类型。
- 敏感事件列表:
- 采用过程语句对组合电路进行描述时,需要把全部的输入信号列入敏感事件列表。
- 采用过程语句对时序电路进行描述时,需要把时间信号和部分输入信号列入敏感事件列表
四选一数据选择器
/*四选一数据选择器*/
module mux4_l(out, in0, in1, in2, in3, sel):output out;input in0, ini, in2, in3;inpul[1 :0] sel;reg out; 〃被赋值信号定义为“reg”类型always @(in0 or ini or in2 or in3 or sel) 〃敏感事件列表case(sel)2'b00: out = inO;2'b01: out = ini;2'b10: out = in2;Z'b11: out = in3;default: out = 2'bx;endcase
endmodule
同步置数、同步清零计数器:
module counter 1 (out, data, load, rst, elk);output[7:0] out;input[7:0] data;input load, elk, rst;reg[7:0] out;always @(posedge elk) //clk上升沿触发beginif(!rst) out = 8'h00; //同步清零,低电平有效else if(load) out = data; //同步置数else out = out+ 1;end
endmodule
异步清零计数器:
module counter2(rst, elk, out);output[7:0] out;input elk, rst;reg[7:0] out;always @(posedge clk or negedge rst) // clk 上升沿和 rst 低电平清零有效beginif(!rst) //异步清零out = 0;else out = out+1;end
endmodule
语句块
串行语句块:其中的语句按串行方式顺序执行,可以用于可综合电路程序和仿真测试程序
块名即该块的名字,当块内有变量时必须有块名,否则在编译时将出现语法错误。块内声明语句是可选的,可以是参数说明语句‘integer型变量声明语句、reg型变量声明语句、time型变量声明语句和事件(event)说明语句。
begin:块名块内声明语句;语句1; 语句2;...语句n;
end
并行语句块:语句按并行方式执行,只能用于仿真测试程序,不能用于可综合电路程序。
fork:块名块内声明语句: 语句1;语句2; ...语句n;
join
两者比较:
语句块
|
串行语句块(begin-cnd)
|
并行语句块(fork-join)
|
执行顺序
|
按照语句顺序执行
|
所有语句均在同一时刻执行
|
语句前面延迟
时间的意义
|
相对于前一条语句执行结束的相对时间
|
相对于并行语句块启动的时间
|
起始时间
|
首句开始执行的时间
|
转入并行语句块的时间
|
结束时间
|
最后一条语句执行结束的时间
|
执行时间最长的那条语句执行 结束的时间
|
行为描述的 意义
|
电路中的数据在时钟及控制信号的作用下, 沿数据通道中各级寄存器之间传送的过程
|
电路上电后,各电路模块同时开始工作的过程
|
过程赋值语句:
阻塞赋值语句:变量=表达式;
当一个语句块中有多条阻塞赋值语句时,如果前面的赋值语句没有完成,则后面的语句就不能被执行,仿佛被阻塞了一样,因此称为阻塞赋值方式。
特点:
在串行语句块中,各条阻塞赋值语句将按照排列顺序依次执行;在并行语句块中的各条阻塞赋值语句则同时执行,没有先后之分。
执行阻塞赋值语句的顺序是,先计算等号右端表达式的值,然后立刻将计算的值赋给左边的变量,与仿真时间无关。
非阻塞赋值语句 :变量 <=表达式;
特点:
在串行语句块中,各条非阻塞赋值语句的执行没有先后之分,排在前面的语句不会影响到后面语句的执行,各条语句并行执行。
执行非阻塞赋值语句的顺序是,先计算右端表达式的值,然后等待延迟时间的结束,再将计算的值赋给左边的变量。
过程连续赋值语句
赋值语句和重新赋值语句:assign deassign:使用assign给寄存器型变量赋值之后,该值将一直保 持在这个寄存器上,直至遇到deassign。
assign <寄存器型变量>=<赋值表达式>;
deassign<寄存器型变量>;
强制语句和释放语句:force release:主要用于Verilog HDL仿真测试程序中,便于对某种信号进行临时性的赋值和测试。
force <寄存器或连线型变量>=<赋值表达式>;
release<寄存器或连线型变量>;
条件分支语句
if语句:
if(条件表达式)语句块; //form 1if(条件表达式) //form 2语句块1;
else语句块2;if(条件表达式1) //form 3语句块1;
else if(条件表达式2)语句块2;...
else if(条件表达式i)语句块i;
else语句块n;
case语句:
case(控制表达式) 值1:语句块1 值2:语句块2 ...值n:语句块ndefault:语句块 n+l
endcase
case语句的真值表:
case | 0 | 1 | x | z |
0 | 1 | 0 | 0 | 0 |
1 | 0 | 1 | 0 | 0 |
x | 0 | 0 | 1 | 0 |
z | 0 | 0 | 0 | 1 |
BCD数码管译码:
module BCD_decoder(out, in);output[6:0]out;input[3:0]in;reg[6:0]out;always@(in)begincase(in)4'b0000:out = 7'b1111110;4'b0001:out = 7'b0110000;4'b0010:out = 7'b1101101;4'b0011:out = 7'b1111001;4'b0100:out = 7'b0110011;4'b0101:out = 7'b1011011;4'b0110:out = 7'b1011111;4'b0111:out = 7'b1110000;4'bl000:out = 7'blllllll;4'bl001:out = 7'bllll011;default:out = 7'bx;endcaseend
endmodule
casez:比较双方有一位为z,即认为这一位永远为真
casez | 0 | 1 | x | z |
0 | 1 | 0 | 0 | 1 |
1 | 0 | 1 | 0 | 1 |
x | 0 | 0 | 1 | 1 |
z | 1 | 1 | 1 | 1 |
casex:比较双方有一位为x或z,即认为这一位永远为真
casex | 0 | 1 | x | z |
0 | 1 | 0 | 1 | 1 |
1 | 0 | 1 | 1 | 1 |
x | 1 | 1 | 1 | 1 |
z | 1 | 1 | 1 | 1 |
循环语句
forever 语句
forever 语句或语句块;
module forever_tb;reg clock;initialbeginclock = 0;forever #50clock = ~clock;end
endmodule
repeat 语句
repeat(循环次数表达式) 语句或语句块(循环体)
module repeat_tb; //使用repeat语句产生固定周期数的时钟信号。reg clock;inilialbeginclock = 0;repeat(8) clock = -clock; //循环体所预先制定的循环次数为8次,相应产生4个时钟周期信号end
endmodule
while 语句
while(条件表达式)语句或语句块;
module while_tb;reg clock;initialbeginclock = 0;while(l)#50 clock = ~clock;end
endmodule
for语句
for(循环变量赋初值:循环结束条件:循环变量增值)语句块;
module for_clk;reg cik;integer i;initialbeginelk = 0;for(i = 0; i >= 0: i = i+1)#50 elk = ~clk;end
endmodule
8位移位寄存器
//采用赋值语句实现
module shift_registl(Q, D, rst, elk);output [7:0] Q;input D, rst, elk:reg [7:0] Q;always @(posedge elk)if(!rst) Q <= 8'b000000;else Q <= {Q[6:0], D};
endmodule//采用for语句实现
module shift_regist2(Q, D, rst, elk);output [7:0] Q;input D, rst, elk;reg [7:0] Q;integer i;always @(posedge elk)if(!rst)Q<= 8'b000000;elsebeginfor (i = 7; i > 0; i = i-1) Q[i] <= Q[i-1];Q[0] <= D;end
endmodule
结构化建模
模块级建模
模块调用方式:
模块名〈参数值列表〉实例名(端口名列表);
模块端口对应方式:
端口位置对应方式
模块名〈参数值列表〉实例名(<信号名1>. <信号名2>, …,<信号名n>);
端口名对应方式
模块名〈参数值列表〉实例名(.端口名1<信号名1>, .端口名2<信号名2>, …,.端口名n<信号名 n>):
dff U4(.q(), ,d(out[2]), .clk(clock), .clr(clear)); //端口列表中第一项内的信号名是缺省的(空括号),表明端口 “q”悬空。
模块参数值
使用带有参数的模块实例语句修改参数值
模块名〈参数值列表〉调用名(端口名列表);
para l #(4, 3) U1(C1,D1); //利用位置对应方式将4传给a、3传给b,这和模块paral中定义参数的先后顺序有关;
paral #(.b(6), ,a(5)) U2(C2,D2); //利用名称对应方式将6传给b、5传给a,此时和模块paral中定义参数的顺序无关。
使用参数重定义语句defparam修改参数值
defparam 参数名1 =参数值1,参数名2 =参数值2,...参数名n =参数值n;
module halfadder(a, b, s, c); 〃半加器模块 halfadderinput a, b:output c, s;parameter xor_delay = 2, and_delay = 3:assign #xor_delay s = aAb;assign #and_delay c = a&b;
endmodule
module fulladder(p, q, ci, co, sum); 〃全加器模块 fulladderinput p, q, ci;output co, sum;parameter or_delay = 1;wire wl, w2, w3;halfadder Ul(p, q, wl, w2);halfadder U2(ci, w 1, sum, w3);or #or_delay U3(co, w2, w3);
endmodulemodule topi(topla, top lb, topis, topic); 〃修改半加器模块参数的模块 topiinput top la, top lb;output topis, topic;defparam U1 .xor_delay = 4,U1 .and_delay = 5;//名为U1的半加器实例中对参数xor_delay和参数and_delay值的修改halfadder Ul(topla, top lb, topis, topic);
endmodule
module top2(top2p, top2q, lop2ci, top2co, top2sum); 〃修改全加器模块参数的模块 top2input top2p, top2q, top2ci;output top2co, top2sum;defparam U2.U1.xor_delay = 6,U2.U2.and_deIay = 7;//名为U2的全加器实例中引用的名为U3的半加器实例中对参数xor_delay和//参数and.delay值的修改U2.or_delay = 5;//名为U2的全加器实例中对参数or_delay值的修改fulladder U2(lop2p, top2q, top2ci, top2co, lop2sum);
endmodule
门级建模
类型 |
元 件
|
|
基本门
|
多输入门
|
and, nand, or, nor, xor, xnor
|
多输出门
|
buf, not
|
|
三态门
|
允许定义驱动强度
|
bufif0, bufif1, notif0, notif1
|
MOS开关
|
无驱动强度
|
nmos, pmos, emos
rnmos, rpmos, rcmos
|
双向开关
|
无驱动强度
|
tran, tranif0, tranif1
rtran, rtranifO0, rtranif1
|
上拉、下拉电阻
|
允许定义驱动强度
|
pullup, pulldown
|
门级模块调用
多输入门元件
元件名<实例名>(<输出端口>,<输入端口 1>,<输入端口 2>, <输入端口 n>);
and Al (outl, ini, in2);
or O2 (a, b, c, d);
xor X1 (x_out, pl, p2);
多输出门元件
元件名<实例名>(<输出端口 1>,<输出端口 2>,…,〈输出端口 n>,〈输入端口>);
not NOT_1 (outl, out2, in);
buf BUF_1 (bufoutl, bufout2, bufout3, bufin);
三态门元件
元件名<实例名>(<数据输出端口>,<数据输入端口>,<控制输入端口>);
bufifl BF1 (data_bus, mem_data, enable);
bufifO BFO (a, b, c);
notifl NT1 (out, in, Ctrl);
notifD NTO (addr, a_bus, select);
module decoder2_4(in0, ini, en, outO, outl, out2, out3);output outO, outl, out2, out3;input inO, ini, en;wire wirel, wire2;not Ul(wirel» inO),U2(wire2, ini);nand U3(outO, en, wirel, wire2),U4(outl, en, wire 1, ini),U5(out2, en, inO, wire2),U6(out3, en, inO, ini);
endmodule
开关级建模
nmos
module aNMOS(din, ctr, out);input din, ctr;output out;nmos Ul(oul, din, ctr);
endmodule
2输入与非门的cmos电路
module nnand2(a, b, y);input a, b;output y;supplyO Gnd;supply1 Vdd: //supplyO 和 supply!为内部参 //量,分别表示低电平和高电平wire iml;pmos gl(y, Vdd, a);pmos g2(y, Vdd, b);nmos g3(y, iml, a);nmos g4(iml, Gnd, b);
endmodule
组合电路设计
3个裁判的表决电路
case语句
module design1(OUT, A, B, C);output OUT;input A, B, C;reg OUT;always @(A or B or C)case ((A, B, C})3'b000:OUT<=0;3'b001:OUT<=0;3'b010:OUT<=0;3'b100:OUT<=0;3'b011:OUT<=1;3'bl01:OUT<=1;3'b110:OUT<=1;3'b111:OUT<=1;endcase
逻辑代数方式
module design2(OUT, A, B, C);output OUT;input A, B, C;assign OUT = (A&B)|(B&C)|(A&C);
endmodule
结构描述方式
module design3(OUT, A, B, C);output OUT;input A, B. C;and U1 (wl, A, B);and U2 (w2, B, C);and U3 (w3, A、C);or U4 (OUT, w 1, w2, w3);
endmodule
抽象描述方式
module design4(OUT, A, B, C);output OUT;input A, B, C;wire [1:0] sum:reg OUT;assign sum = A+B+C;always @(sum)if(sum>l) OUT = 1:else OUT = 0;
endmodule
数字加法器
真值表
A | B | C_IN | SUM | C_OUT |
0 | 0 | 0 | 0 | 0 |
0 | 0 | 1 | 1 | 0 |
0 | 1 | 0 | 1 | 0 |
0 | 1 | 1 | 0 | 1 |
1 | 0 | 0 | 1 | 0 |
1 | 0 | 1 | 0 | 1 |
1 | 1 | 0 | 0 | 1 |
1 | 1 | 1 | 1 | 1 |
代数逻辑表示为
/*连续赋值*/
module one_bit_fuiladder(SUM, C_OUT, A, B, C_IN);input A, B, C_IN;output SUM, C_OUT;assign SUM = (A^B)^C_IN;assign C_OUT = (A&B)|((A^B)&C_IN);
endmodule/*行为级*/
module one_bit_fulladder(SUM, C_OUT, A, B, C_IN);output SUM, C_OUT;input A, B, C_IN;assign {C_OUT, SUM} = A+B+C_IN;
endmodule
4位超前进位加法器
module four_bits_fast_addder (sum_out, c_out, a, b, c_in);input [3:0] a, b; //加数,被加数input c_in; //来自前级的进位output [3:0] sum_out; 〃和output c_out; //进位输出wire [4:0] g, p, c; //产生函数、传输函数和内部进位assign c[0] = c_in;assign p = a | b;assign g = a & b;assign c[l] = g[0]|(p[0]&c[0]);assign c[2] = g[1]|(p[1]&(g[0] | (p[0]&c[0])));assign c[3] = g[2]|(p[2]&(g[1] | (p[1]&(g[0] | (p[0]&c[0])))));assign c[4] = g[3]|(p[3]&(g[2] | (p[2]&(g[1] | (p[1]&(g[0]|(p[0]&c[0])))))));assign sum_out = p^c[3:0];assign c_out = c[4];
endmodule
数据比较器
module four_bits_comp 1 (F, A, B, C);parameter comp_width = 4;output [2:0] F;input [2:0] C;input [comp_width-1:0] A;input [comp_width-l:0] B;reg [2:0] F;always @(A or B or C)if(A>B) F= 3'b100;else if(A<B) F = 3'b001;else F = C;
endmoduie
数据选择器
module mux8tol_2(d_out, d_in, sei);output d_out;input[7:0] d_in;input[2:0] sel;wire[3:0] wl;wire[1:0] w2;assign w1 = sel[0]? {d_in[7], d_in[5], d_in[3], d_in[1]} :{d_in[6], d_in[4], d_in[2], d_in[0|};assign w2 = sel[1]? {w1[3], w1[l]}:{w1[2], w1[0]};assign d_out = sel[2]?w2[1]:w2[0];
endmodulemodule mux8tol(out, sel, data_in);output out;input [7:0] data_in;input [3:0] sel;reg out;always @ (data_in or sel)case (sel)3'b000 : out <= data_in[0];3'b001 : out <= data_in[1];3'b010 : out <= daia_in[2];3'b011 : out <= data_in[3];3'b100 : out <= data_in[4];3'b101 : out <= data_in[5];3'b110 : out <= data_in[6];3'b111 : out <= data_in[7];endcase
endmodule
数字编码器
module code_8to3(F, I);output [2:0] F;input [7:0] I;reg [2:0] F;always @ (I)case (1)8'b00000000:F = 3'b000;8'b00000010:F = 3'b001;8'b00000100:F = 3'b010;8,b00001000:F = 3'b011;8'b00010000:F = 3'b100;8'b00100000:F = 3'b101;8'b01000000:F = 3'b110;8'bl0000000:F = 3'b111;default: F = 3'bx;endcase
endmodule
8线-3线优先编码器
module mux8to3_p(data_out, Ys, Yex, sel, data_in);output [2:0] data_out;output Ys, Yex;input [7:0] clata_in;input sel;reg [2:0] data_out;reg Ys, Yex;always @ (data_in or sel)if (sel) (data_out, Ys, Yex} = {3'b111, 1'b1, 1'b1};elsebegincasex (data_in)8'b0???????: {data.out, Ys, Yex} = {3'b000, 1'b1, 1'b0};8'bl0??????: {data-out, Ys, Yex} = {3'b001, 1'b1, 1'b0};8'b110?????: {daia.out, Ys, Yex} = {3'b010, 1'b1, 1'b0};8'b1110????: {data_oul, Ys, Yex} = {3'b011, 1'bl, 1'b0};8'b11110???: {data_out, Ys, Yex} = {3'b100, 1'bl, 1'b0);8'b111110??: {data_out, Ys, Yex} = {3'b101, 1'bl, 1'b0);8'b1111110?: {data_out, Ys, Yex} = {3'b110, 1'bl, 1'b0};8'b11111110: {data_out. Ys, Yex} = {3'b111. 1'bl, 1'b0};8'b11111111: {data.out, Ys, Yex} = {3'b111, 1'b0, 1'b1);
endcase
end
endmodule
二进制转化十进制8421BCD编码器
逻辑表达式:
module BCD8421(data_out, data_in);output [3:0] data_out;input [8:0] data_in;reg [3:0] data_out;always @ (data_in)case (data_in)9'b000000000 : data_out = 4'b0000;9'b00000000l : data_out = 4'b0001;9'b000000010 : data_out = 4'b0010;9'b000000010 : data_out = 4'b0011;9'b000001000 : data_out = 4'bO100;9'b000010000 : data.out = 4'b0101;9'b000100000 : data_out = 4'b0110;9'b001000000 : data_out = 4'b0111;9'b010000000 : data.out = 4'b1000;9'b100000000 : data_out = 4'b1001;default : data_out = 4'b0000;endcase
endmodule
8421BCD十进制余3码编码器
module code_change(B_out, B_in);output [3:0] B_out;input [3:0] B_in;assign B_out = B_in+2'b11;
endmodule
数字译码器
2线-4线译码器
module decode_2to4(Y, E, A);output [3:0] Y:input [1:0] A;input E;assign Y[0] = ~(~E&~A[1]&~A[0]);assign Y[1] = ~(~E&~A[1]&A[0]);assign Y[2] = ~(~E&A[1]&~A[0]);assign Y[3] = ~(~E&A[1]&A[0]);
endmodulemodule decode_2tc4(Y, E, A);output [3:0] Y;input [1:0] A;input E;reg [3:0] Y;always @(E or A)case ((E, A))3'b1??: Y = 4'b0000;3'b000: Y = 4'b0001;3'b001: Y = 4'b0010:3'b010: Y = 4'b0100;3'b011: Y = 4'b1000;default: Y = 4'b0000;endcase
endmodule
奇偶校验器
module checker (Fod, Fev, b);output Fod, Fev;input [7:0] b;wire wl, w2, w3, w4, w5, w6;xor Ul (w1, b[0], b[1]);xor U2 (w2, b[2], b[3]);xor U3 (w3, b[4], b[5]);xor U4 (w4, b[6], b[7]);xor U5 (w5, wl, w2);xor U6 (w6, w3, w4);xor U7 (Fod, w5, w6);not U8 (Fev, Fod);
endmodulemodule checker (Fod, Fev, b);output Fod, Fev;input [7:0] b;assign Fod = ^b;assign Fev = ~Fod;
endmodule
时序电路设计
状态图描述
module checker(Z, X, elk);parameter s0 = 2'b00, s1 = 2'b01, s2 = 2'b11, s3 = 2'bl0;output Z;input X, clk;reg [1:0] state, next_state;reg Z;always @(X, state)case (state)s0:if(X)beginnext_state <= s1; Z = 0;endelsebeginnext_state <= s0; Z = 0;ends1:if(X)beginnext_state <= s2; Z = 0;endelsebeginnext_state <= s0; Z = 0;ends2:if(X)beginnext_state <= s3; Z = 1;endelsebeginnext_state <= s0; Z = 0;ends3:if(X)beginnext_state <= s3; Z = 1;endelsebeginnext_state <= s0; Z = 0;endendcasealways @(posedge clk)state <= next_state;
endmodule
化简描述
//序列检测器模块
module checker (Z, X, clk);output Z;inpul X, elk;wire w1, w2;DFF U1 (.clk(clk), .D(X), .Q(w1));DFF U2 (.clk(clk), .D(wl), .Q(w2));assign Z = X & w1 & w2;
endmodule//D触发器模块
module DFF (Q, D, clk);output Q;input D, clk;reg Q:always @(posedge clk) Q <= D;
endmodule
抽象描述方式
module checker (Z, X, clk);output Z;input X. clk;reg [2:0] q;reg Z;always @(posedge clk) q<= {q[1:0], X};always @(posedge clk) if(q=3'blll) Z=1;else Z = 0;
endmodule
触发器
最简D触发器
module DFF(q, clk, data_in);output q;input clk, data_in;reg q;always @(posedge clk) q <= data_in;
endmodule
带复位端的D触发器
module DFF_rst (q, clk, reset, data_in);output q;input elk, reset, data_in;reg q;always @(posedge clk)if (!reset) q <= 0;else q <= data_in;
endmodule
复杂功能的D触发器
module DFF_l(q, clk, resetl, reset2, data_in);output q;input clk, reset1, reset2, data_in;reg q;always @(posedge clk)if (!reset1) q <= 0;else q <= data_in;always @(posedge clk or negedge reset2)if (!reset2) q <= 0;else q <= data_in;
endmodule
T触发器
module TFF(data_ouL, T, clk, reset);output data_out;input T, clk, reset;reg data_out;always @(posedge clk or negedge reset)if (!reset) data_out <= 1'b0;else if (T) data_out <= ~data_out;
endmodule
计数器
二进制计数器
module comp2bit (Q, clk, reset);output Q;input clk, reset;reg Q;always @ (posedge clk or negedge reset)if (!reset)Q<= 1'b0;elseQ <= ~Q;
endmodulc
任意进制计数器
module comp_11 (count, clk, reset);output [3:0] count;input clk, reset;reg [3:0] count;always @ (posedge clk)if(reset) count <= 4'b0000;elseif (count == 4'b1010)count <= 4'b0000;elsecount <= count+1;
endmodule
移位寄存器
环形移位寄存器
module shiftregistl (D, clk, reset);parameter shiftregist_width = 4;output [shiftregist_widlh-1:0] D;input clk, reset;reg [shiftregist_width-1:0] D;always @(posedge clk)if (!reset)D <= 4'b0000;elseD <= (D[shiftregist_width-2:0], D[shiftregist_width-1]);
endmodule
序列信号发生器
由移位寄存器构成
module signal_maker(out, clk, load, D);parameter M = 6;output out;input clk, load;input [M-1:0] D;reg [M-1:0] Q;initial Q = 6'b100111;always @(posedge clk)if (load) Q <= D;else Q <= {Q[M-2:0], Q[M-1]};assign out = Q[M-1];
endmodule
由移位寄存器和组合逻辑电路构成
首先确定所需移位寄存器的个数n。因M = 6,故 n>=3。其次确定移位寄存器的6个独立状态。按照移位规律每三位一组,划分6个状态为 100、001、011、111, 111、110。其中状态111重复出现,故取n = 4,并重新划分状态, 得到1001、0011、0111、1111、1110、1100。因此确定n = 4。第三,列态序表和反馈激励函数表,求反馈函数F的表达式。
F= ~Q3 + ~Q1 • ~Q0 +Q3+~Q2
module signal_maker(out, clk, load, D);parameter M = 4;output out;input clk, load;input [M-1 :0] D;reg [M-1:0] Q;wire w1;always @(posedge clk) //时序电路部分,移位寄存器if (load) Q<=D;else Q <= {Q[M-2:0], w1};assign w1 =(~Q[3])|(~Q[1]&(~Q[0]))|(Q[3]&(~Q[2])); //组合逻辑电路,反馈网络assign out =Q[M-1];
endmodule
由计数器构成
module signal_maker(out, clk, reset);parameter M = 3;output out;input clk, reset;reg [M-l:0] counter;always @(posedge clk)if (!reset) counter <= 3'b000;else counter <= counter+1;assign out = counter[2]|((~counter[1])&(~counter[0]))l(counter[1]&counter[0]);
endmodule
有限同步状态机
状态机的编码方式:
- 二进制编码:其状态寄存器是由触发器组成的。
- 格雷编码:格雷编码状态跳转时只有一个bit(位)发生变化,减少了产生毛刺和一些暂态的可能。
- 一位独热编码:这是对于n个状态采用n个bit(位)来编码,每个状态编码中只有一个bit(位)为1,如0001、0010、0100、1000。
状态机的两段式描述方法:
//第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器
always @(posedge clk or negedge rst_n) //异步复位if(!rst_n) current_state <= IDLE;else current_state <= next_state; //注意,使用的是非阻塞赋值
//第二个进程,组合逻辑 always模块,描述状态转移条件判断always @(current_state or 输入信号) //电平触发beginnext_state = x; //要初始化,使得系统复位后能进入正确的状态case(current_state)Sl:if(...)next_state = S2; //阻塞赋值outl <= 1'bl; //注意是非阻塞逻辑...endcaseend
状态机的三段式描述方法:
//第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器
always @(posedge clk or negedge rst_n) //异步复位if(!rst_n) current_state <= IDLE;else current_state <= next_state; //注意,使用的是非阻塞赋值
//第二个进程,组合逻辑always模块,描述状态转移条件判断
always @(current_state or 输入信号) //电平触发beginnext_state = x; //要初始化,使得系统复位后能进入正确的状态case(current_state)S1: if(...)next_state = S2; //阻塞赋值... endcaseend
//第三个进程,同步时序always模块,格式化描述次态寄存器输出
always @ (posedge clk or negedge rst_n)begin...//初始化case(next_state or 输入信号)S1:outl <= 1'bl; //注意是非阻塞逻辑S2:outl <= 1'b0;default:... //default的作用是免除综合工具综合出锁存器endcaseend
4位顺序脉冲发生器
module state4(OUT, clk, rst_n);output [3:0] OUT:input clk;input rst_n;reg [3:0] OUT;reg [1:0] STATE, next_STATE;always @(STATE)case (STATE)2'b00:beginOUT <= 4'b11000;next_STATE <= 2'b01;2'b01:beginOUT <= 4'b0100;next_STATE <= 2'b10;end2'b10:beginOUT<= 4'b0010;next_STATE <= 2'b11;end2'bll:beginOUT <= 4'b0001;next_STATE <= 2'b00;endendcasealways @(posedge clk or negedge rst_n)if(!rst_n) STATE <= 2'b00:else STATE <= next_STATE;
endmodule
自动售报机
module auto_sellor(current_state, data_out,data_out_return1, data_out_return2, clk,rst_n, data_in);parameter state_width = 3, data_in_width = 3;output [state_width-1:0] current_state;output data_out, data_out_return1,data_out_return2;input [dala_in_width-1:O] data_in;input clk, rst_n;reg [state_width-l:OJ current_state, next_state;reg data_out, data_out_returnl, data_out_return2;always @(current_state or data_in)case (current_state)3'b000: case (data_in)3'b000: beginnext_state <= 3'b000;data_out <= 1'b0;data_out_return1 <= 1'b0;data_out_return2 <= 1'b0;end3'b001: beginnext_state <= 3'b001;data_out <= 1'bO;data_out_return 1 <= 1'bO;data_out_retum2 <= 1'bO;end3'b010: beginnext_state <= 3'b010;data_out <= 1'b0;data_out_return1 <= 1'b0;data_out_return2 <= 1'b0;end3'b011: beginnext_state <= 3'bl01;data_out <= 1'bO;data_out_return 1 <= 1'bO;data_out_retum2 <= 1'bO;end3'bl00: beginnext_state <= 3'bOOO;data_out <= 1'bl;data_out_retum1 <= 1'bO;data_out_retum2 <= 1'bl;endendcase3'b001: case (data_in)3'b000: beginnext_state <= 3'b001;data_out <= 1'b0;data_out_retum1 <= 1'b0;data_out_retum2 <= 1'b0;end3'b001: beginnext_state <= 3'b010;data_out <= 1'b0;data_out_return1 <= 1'b0:data_out_return2 <= 1'b0;end3'b010: beginnexl_state <= 3'b011;data_out <= 1'b0;data_oul_return1 <= 1'b0;data_out_return2 <= 1'b0:end3'b011: beginnext_state <= 3'b110;data_out <= 1'b0;data_out_return1 <= 1'b0;data_out_return2 <= 1'b0:endendcase3'b010: case (daia_in)3'b000: beginnext_state <= 3'b010;data_out <= 1'b0;data_out_returnl <= 1'b0;data_out_return2 <= 1'b0;end3'bOO1: beginnext_state <= 3'b011;data_out <= 1'b0;data_out_return1 <= 1'b0;data_oul_return2 <= 1'b0;end3'b010: beginnext_state <= 3'b100;data_out <= 1'b0;data_out_return1 <= 1'b0;data_out_return2 <= 1'b0;end3'b011: beginnext_state <= 3'b111;data_out <= 1'b0;data_out_return1 <= 1'b0;data_out_return2 <= 1'b0;endendcase3'bO11: case (data_in)3'b000: beginnext_state <= 3'b011;data_out <= 1'b0;data_out_retuml <= 1'b0;data_out_return2 <= 1'b0;end3'b001: beginnext_state <= 3'b100;data_out <= 1'b0;data_out_return1 <= 1'b0;data_out_return2 <= 1'b0;end3'b010: beginnext_state <= 3'b101;data_out <= 1'b0;data_out_return1 <= 1'b0;data_out_return2 <= 1'b0;end3'b011: beginnext_state <= 3'b000;data_out <= 1'b1;data_out_returnl <= 1'b0;data_out_return2 <= 1'b0;endendcase3'blOO: case (data_in)3'bOOO: beginnext_state <= 3'b000;data_out <= 1'b0;data_out_return1 <= 1'b0;data_out_return2 <= 1'b0;end31)001: beginnext_state <= 3'b101;data_out <= 1'b0;data_out_return1 <= 1'b0;data_out_return2 <= 1'b0;end3'b010: beginnext_state <= 3'b110;data_out <= 1'b0;data_oul_return1 <= 1'b0;data_out_retumrn2 <= 1'b0;end3'b011: beginnext_state <= 3'b000;data_out <= 1'b1;data_out_return1 <= 1'b1;data_out_return2 <= 1'b0;endendcase3'b101: case (data_in)3'bOOO: beginnext_state <= 3'b101;data_out <= 1'b0;data_out_retuml <= 1'b0;data_out_retum2 <= 1'b0;end3'bOO1: beginnext_state <= 3'b110;data_out <= 1'b0;data_out_return1 <= 1'b0;data_out_return2 <= 1'b0;end3'b010: beginnext_state v= 3'bl 11;data_out <= 1'bO;data_out_retum1 <= 1'bO;data_out_retum2 <= 1'bO;end3'bO11: beginnext_state <= 3'b000;data_out <= 1'b1;data_out_return1 <= 1'b0;data_out_return2 <= 1'b1;endendcase3'b110: case (data_in)3'b000: beginnext_state <= 3'b110:data_out <= 1'b0;data_out_return1 <= 1'b0;data_out_relurn2 <= 1'b0:end3'b001: beginnext_state <= 3'b111;data_out <= 1'b0;data_out_relurnl <= 1'bO:data_out_return2 <= 1'bO;end3'b010: beginnext_state <= 3'bOOO;data_out <= 1'b1;data_out_return1 <= 1'bO;data_out_return2 <= 1'bO;endendcase3'b111: case (data_in)3'bOOO: beginnext_state <= 3'b111;data_out <= 1'b0;data_oul_return 1 <= 1'b0;data_out_retum2 <= 1'b0;end3'bOO1: beginnext_state <= 3'b000;data_out <= 1'b1;data_out_retum 1 <= 1'b0;data_out_return2 <= 1'b0;endendcaseendcasealways @(posedge clk or rst_n)if(!rst_n)current_state <= 3'bOOO;elsecurrent_state <= next_state;
endmodule
“11010”序列检测器
module seqdet (D_out, D_in, rst_n, clk);parameter IDLE = 3'd0, A = 3'd1,B = 3'd2, C = 3'd3, D = 3'd4, E = 3'd5;output D_out;input D_in, rst_n, clk;reg [2:0] state, next_state;wire D_out;assign D_out = (state == E)? 1:0;always @(state or D_in)case (state)IDLE : if(D_in) next_state = A;else next_state = IDLE;A : if(D_in) next_state = B;else next_state = IDLE;B : if(D_in) next_state = B;else next_state = C;C : if (D_in) next_state = D;else next_state = IDLE;D : if (D_in) next_state = B;else next_state = E;E : if (D_in) next_state = IDLE;else next_state = A;default: next_state = IDLE;endcasealways @(posedge clk)state <= next_state;
endmodule
电路仿真和测试程序
语言要素
$display $write
$display("<format_specifiers>“, <signal1, signa!2, …,signaln>);
$write("<format_specifiers>", <signal 1, signal2,…,signaln>);
$monitor 和 $strobe
$time 和 $realtime
$readmemh 和$readmemb
$random
VCD
十进制加法器
module cntl0(clk, rst, ena, q, cout);input clk, rst, ena;output[3:0] q;output cout;reg[3:0] q;always @ (posedge clk or posedge rst)beginif(rst)q = 4'b0000;else if(ena)beginif(q<9)q = q+1;else q = 0;endendassign cout = q[3]&q[0];
endmodulemodule cnt10_tb;reg clk, rst, ena;wire [3:0] q;wire cout;cnt_10 U1(clk, rst, ena, q, cout); //模块实例化always #50 elk = ~clk; //时钟信号产生initialbeginclk = 0; rst = 0; ena = 1; //控制信号产生#1200 rst= 1;#120 rst = 0;#2000 ena = 0;#200 ena = 1;#20000 $finish;end
endmodule
verilog study-初级相关推荐
- 二十一世纪大学英语读写教程学习笔记(原文)——6 - Nerds and Geeks(书呆子和极客)
Unit 6 - Nerds and Geeks(书呆子和极客) Nerds and Geeks Leonid Fridman There is something very wrong with t ...
- Verilog初级教程(23)Verilog仿真中的显示任务
文章目录 前言 正文 Display/Write Tasks Verilog Strobes Verilog Continuous Monitors Verilog Format Specifiers ...
- Verilog初级教程(21)Verilog中的延迟控制语句
文章目录 前言 正文 延迟控制语句 事件控制语句 Named Events Event or operator 往期回顾 参考资料及推荐关注 前言 Verilog中的延迟控制有两种类型–延迟和事件表达 ...
- Verilog初级教程(20)Verilog中的`ifdef 条件编译语句
文章目录 前言 正文 语法 示例 Testbench文件 往期回顾 参考资料及推荐关注 前言 `ifdef条件编译语句在逻辑设计中还是很常见的,但也常见一些滥用的情况,这应该避免. 应该在什么情况下使 ...
- Verilog初级教程(15)Verilog中的阻塞与非阻塞语句
文章目录 前言 正文 阻塞赋值 非阻塞赋值 往期回顾 参考资料以及推荐关注 前言 本文通过仿真的方式,形象的说明阻塞赋值以及非阻塞赋值的区别,希望和其他教程相辅相成,共同辅助理解. 正文 阻塞赋值 阻 ...
- Verilog初级教程(14)Verilog中的赋值语句
文章目录 前言 正文 合理的左值 过程性赋值(Procedural assignment) 连续赋值 过程连续性赋值 往期回顾 前言 何为赋值语句?即将值放到线网或者变量上,这种操作称为赋值,英文:a ...
- Verilog初级教程(12)Verilog中的generate块
文章目录 前言 正文 generate for generate if generate case 参考资料 本系列博文 前言 verilog中的generate块可以称为生成块,所谓生成,可以理解为 ...
- Verilog初级教程(11)Verilog中的initial块
文章目录 前言 正文 语法格式 initial块是用来干什么的? initial块何时开始又何时结束? 一个模块中允许有多少个initial块? 参考资料 写在最后 前言 仿真中通常会依次执行一组Ve ...
- Verilog初级教程(9)Verilog的运算符
博文目录 写在前面 正文 Verilog算术运算符 Verilog关系运算符 Verilog等价运算符 Verilog逻辑运算符 Verilog位元运算符 Verilog移位运算符 参考资料 交个朋友 ...
- Verilog初级教程(7)Verilog模块例化以及悬空端口的处理
博文目录 写在前面 正文 按顺序排列的端口连接 按名称排列的端口连接 未连接/悬空端口处理 关于模块端口的说明 参考资料 交个朋友 写在前面 此系列相关博文: Verilog初级教程(6)Verilo ...
最新文章
- WordPress 多个安全漏洞
- 土豆春季实习试题之惨烈教训
- 基于 Blazui 的 Blazor 后台管理模板 BlazAdmin 正式尝鲜
- 哈夫曼字符串编码c语言实现,基于哈夫曼(haffuman)算法的文件压缩的实现(C语言)(原创)...
- python将数组写入文件_python – 将numpy数组的大小写入二进制文件
- ele-plus包的安装和使用
- 工控软件界面_工控主板能当电脑用吗?会怎么样?
- 以太坊交易的打包规则
- 斯皮尔曼spearman相关系数
- 从哥德巴赫说开去(3)
- SEO学习笔记一:Google搜索引擎背后的运作模式
- 群晖NAS教程(二十三)、利用Docker安装mysql8,并使用ipv6和域名访问
- 根据经纬度查询地理位置API
- 写在2020年的初秋
- 【Flutter从入门到实战】⑪、豆瓣案例-1、星星评分Widget、虚线Widget、TabbarWidget、BottomNavigationBarItem的封装、初始化配置抽取
- 趣谈网络协议---容器网络:来去自由的日子,不买公寓去合租
- linux ssh su - 区别,su 与 su -区别
- 享受代码的快乐--小米抢购前端代码分析
- MAFIA 算法解析
- 深信服上网行为管理开启snmp_深信服上网行为管理部署方式及功能实现配置说明资料...