[TOC]
和verilog相比system verilog提供了很多数据改进的数据结构,一些数据对于创建者和测试者都有用。
># 内建数据类型
## 逻辑(logic)类型
system verilog对经典的reg数据类型进行了改进,使他除了作为变量以外,还能被**连续赋值、门单元、和驱动模块所驱动**,这种改进的数据类型被称为**logic**。</br>
它既可被过程赋值也能被连续赋值,编译器可自动推断**logic**是**reg**还是**wire**。唯一的限制是**logic**只允许一个输入,不能被多重驱动,所以**inout**类型端口不能定义为**logic**。不过这个限制也带来了一个好处,由于大部分电路结构本就是单驱动,如果误接了多个驱动,使用**logic**在编译时会报错,帮助发现bug。*所以单驱动时用**logic**,多驱动时用**wire***。</br>
在[Jason的博客](https://link.zhihu.com/?target=http%3A//www.verilogpro.com/verilog-reg-verilog-wire-systemverilog-logic)评论中,Evan还提到一点**logic**和**wire**的区别。**wire**定义时赋值是连续赋值,而**logic**定义时赋值只是赋初值,并且赋初值是不能被综合的。
```verilog
wire mysignal0 = A & B; // continuous assignment, AND gate
logic mysignal1 = A & B; // not synthesizable, initializes mysignal1 to the value of A & B at time 0 and then makes no further changes to it.
logic mysignal2;
assign mysignal2 = A & B; // Continuous assignment, AND gate
```
```
module tb ;
logic [7:0]i; //声明logic结构数据
initial begin
i = 0;
repeat(10) begin //循环10次
$display("i=%d",i);
i = i + 1;
end
$display("test running!");
end
endmodule
```
仿真结果
```
Start run at Nov 2 19:42 2020
i= 0
i= 1
i= 2
i= 3
i= 4
i= 5
i= 6
i= 7
i= 8
i= 9
```
logic不仅能够作为变量,而且可以被连续赋值,门单元和模块所驱动。但是logic不能够被多个结构体驱动。下面这段代码展示了logic的使用方法。
```
module logic_test(input logic rst_h
);
parameter CYCLE = 20;
logic q,q_1,d,clk,rst_1;
initial
begin
clk = 0;
forever #(CYCLE/2) clk = ~clk; // 过程赋值
end
assign rst_1 = ~ rst_h; //连续赋值
not n1(q_1,q); //q_1被门驱动
my_dff d1(q,d,clk,rst_1); //q被模块驱动
endmodule
```
**SystemVerilog logic的使用方法**
* 单驱动时**logic**可完全替代**reg**和**wire**,除了Evan提到的赋初值问题。
* 多驱动时,如**inout**类型端口,使用**wire**。
## 双状态数据类型
相比于verilog中的4状态数据类型(1,0,x,z),SV引入双状态数据类型有利于提高仿真器的性能并减少内存的使用量。下面逐例解释。
```
bit b; // 双状态 单bit
bit [31:0] b32; // 双状态,32bit,无符号
int unsigned ui; // 双状态,32bit,无符号
int i; // 双状态,32bit,有符号
byte b8; // 双状态,8bit ,有符号
shortint s; // 双状态,16bit,有符号
longint l; // 双状态,64bit,有符号
integer i4; // 四状态,32bit,有符号
time t; // 四状态,64bit,无符号
real r; // 双状态,双精度浮点数。
```
双状态数据类型有利于提高仿真器的性能并减少内存。</br>
**对四态信号的检查:**($isunknown)
这会让任意位置出现X或者Z时返回1,使用实例如下:
```
if( $isunknown(iport) == 1)
$display("@%0t: 4-state velue detected on iport %b",$time,iport)
```
*****
部分仿真结果如下:
```
module tb ;
longint i; //声明logic结构数据
byte b8;
initial begin
i = 0;
b8 = 2;
repeat(3) begin //循环
$display("i=%0d , b8=%0d",i,b8);
i = i - 1;
b8=b8*2;
end
end
endmodule
```
```
Start run at Nov 2 20:01 2020
i=0 , b8=2
i=-1 , b8=4
i=-2 , b8=8
```
># 定宽数组
verilog要求在声明中必须给出数组的上下边界,因为几乎所有的数组都是用0作为索引下界,**所以sv允许只给出数组的宽度**,跟c语言类似。</br>
**例 :数组的声明**
```
int arr[0:15]; //16个整数
int c_style[16]; //c风格,16个整数
```
可以通过**在变量后面指定维度的方式来声明多维数组**;</br>
**例 : 声明8行4列多维数据**
```
int arr2 [0:7][0:3]; //完整声明
int arr2_cstyle[8][4];
```
**特别注意:**如果读取的数据地址越界,那么sv会**返回数组元素的缺省值**
* logic类型:返回 X
* 双状态类型:返回 0
* 线网在没有驱动时输出为 Z
## 数组的遍历
```
module tb ;
int md[2][3] = '{'{1,2,3},'{4,5,6}}; // 声明2行3列数组并赋初值,这里使用常量数组来初始化md数组
initial begin
foreach(md[i,j]) //遍历数组
$display("md[%0d][%0d]=%0d",i,j,md[i][j]);
end
endmodule
```
输出结果
```
VCS Build Date = May 24 2016 20:38:43
Start run at Nov 2 20:26 2020
md[0][0]=1
md[0][1]=2
md[0][2]=3
md[1][0]=4
md[1][1]=5
md[1][2]=6
```
按维度遍历
```
module tb ;
int md[2][3] = '{'{1,2,3},'{4,5,6}}; // 声明2行3列数组并赋初值
initial begin
foreach( md[i] ) begin //遍历第1维
$write("%2d:",i);
foreach( md[,j] ) //遍历第2维
$write("%3d",md[i][j]);
$display;//显示一个维度
end
end
endmodule
```
结果
```
0: 1 2 3
1: 4 5 6
```
## 数组的比较与复制
```
module tb ;
bit [31:0] src[5] = '{0,1,2,3,4},
dst[5] = '{5,4,3,2,1};
initial begin
//比较两个数组
if( src == dst ) $display("src == dst");
else $display("src != dst");
//把src元素拷贝到dst
dst = src;
//只改变一个元素
dst[0] = 5;
//所有元素的值是否相等
$display("src %s dst",(src == dst)? "==" : "!=");
//使用数组片段对第 1-4 个元素进行比较
$display("src[1:4] %s dst[1:4]",(src[1:4] == dst[1:4]) ? "==" : "!=");
end
endmodule
```
输出结果
```
Start run at Nov 2 20:41 2020
src != dst
src != dst
src[1:4] == dst[1:4]
```
## 使用数组位下标和数组下标
**例 : 位下标和数组下标**
```
module tb ;
bit [31:0] src[5] = '{5,1,2,3,4};
initial begin
$display(src[0],, // 5
src[0][0],, // 1
src[0][2:1]); // 2
end
endmodule
```
## 合并数组
对于一些数据你可能既希望作为**整体**访问,也希望**拆分为更小单元**访问,使用sv的合并数组可以实现这个功能。</br>
**例 : 合并数组例子**
```
module tb ;
bit [3:0][7:0] bytes ; //四个字节组装而成的32 bit数据
initial begin
bytes = 32'hCafe_Dada;
$display(bytes,, //显示所有32 bit
bytes[3],, //显示最高字节 "CA"
bytes[3][7]); //显示最高bit位 ”1“
end
endmodule
```
结果
```
3405699802 202 1
```
**扩展说明:**
已知一个多维混合数组的定义为:
```
bit [3:0][7:0][15:0] Array [3:0][7][6];
```
那么当我们写下
```
Array[2][3][2][2] = xxxx;
```
的时候,到底是对哪个位置赋值了??
话不多说,直接看解答好啦~最后的答案其实很简单,因为有一个简单的图示估计很多人知道,就是逆时针索引法:
![](https://img.kancloud.cn/df/ee/dfee598075719706775ec92a8906638d_533x330.png)
**合并数组和非合并数组的选择**
* 合并数组:和标量进行相互转换,等待数组中的变化必须使用合并数组
> # 动态数组
sv提供动态数组,动态数组在声明时使用空下标[ ]。**宽度将不会在编译时给出,而是在程序运行时在指定**。数组开始时为空,因此你必须调用`new [ ] `操作来分配空间。</br>
**例 :动态数组实例**
```
module tb ;
int dyn[],d2[] ; //声明动态数组
initial begin
dyn = new[5] ;//分配5个元素空间
foreach( dyn[i] ) dyn[i] = i; //对5个元素空间的值进行初始化
d2 = dyn ; //复制数组dyn到d2
d2[0] = 5 ; //修改d2[0]的值为5
$display(dyn[0],d2[0]); //显示数值
dyn = new[20](dyn); //分配20个证书值并进行复制
dyn = new[100]; //分配 100 个新的整数值
dyn.delete(); //删除所有元素
end
endmodule
```
**例 : 使用动态数组保存元素数量不定的列表**
```
bit [7:0] mask[] = '{ 8'h00,8'h01,
8'h03,8'h04,
8'h23,8'h36};
```
># 队列
队列与链表类似,可以**在一个队列中的任何地方增加和删除元素**,这类操作在性能上的损失比动态数组小的多!</br>
队列的声明使用`[$]`,队列元素的编号从0到$。sv的队列类似与STL的双端队列。可以通过增加元素来创建队列。**你可以扩大和缩小队列,但是不用向动态数组一样付出很大的代价**。</br>
**例 : 队列操作**
```
module tb ;
//注意,队列常量不需要使用“’”
int q2[$] = {3,4};
int q[$]= {0,2,5};
initial begin
//在2之前插入1
q.insert(1,1); // 0 1 2 5
foreach(q[i])$write("%3d",q[i]); $display; //显示结果
//在5之前插入队列q2
q.insert(3,q2); // 0 1 2 3 4 5
foreach(q[i])$write( "%3d",q[i]); $display; //显示结果
//删除q下标为1的元素
q.delete(1); //0 2 3 4 5
foreach(q[i])$write( "%3d",q[i]); $display; //显示结果
//以下操作速度很快
//在队列最前面插入 8
q.push_front(8); //8 0 2 3 4 5
foreach(q[i])$write( "%3d",q[i]); $display; //打印整个链表
//在队列最前后面插入 6
q.push_back(6); //8 0 2 3 4 5 6
foreach(q[i])$write( "%3d",q[i]); $display; //显示结果
//读出队列最前面的元素并从队列中移除该元素
$display(q.pop_front());
foreach(q[i])$write( "%3d",q[i]); $display; //显示结果 0 2 3 4 5 6
//读出队列最后面的元素并从队列中移除该元素
$display(q.pop_back());
foreach(q[i])$write( "%3d",q[i]); $display; //显示结果 0 2 3 4 5
end
endmodule
```
结果
```
Start run at Nov 2 21:56 2020
0 1 2 5
0 1 2 3 4 5
0 2 3 4 5
8 0 2 3 4 5
8 0 2 3 4 5 6
8
0 2 3 4 5 6
6
0 2 3 4 5
```
>>**说明:** 可以使用字下标串联来代替方法。对于队列`q[$]={0,2,4}`,如果把`$`放在一个范围表达式的左边,那么`$`将代表最小值,例如`[$:2]`就代表`[0:2]`。如果把`$`放在一个范围表达式的右边,那么`$`将代表最大值,例如`[1:$]`就代表`[1:2]`。
使用上述方法的操作如下:</br>
**例 : 队列串联表达式**
```
module tb ;
//注意,队列常量不需要使用“’”
int q2[$] = {3,4};
int q[$]= {0,2,5};
initial begin
//在2之前插入1
q={q[0:1],1,q[2:$]}; // 0 1 2 5
foreach(q[i])$write("%3d",q[i]); $display; //显示结果
//在5之前插入队列q2
q={q[0:2],q2,q[3:$]}; // 0 1 2 3 4 5
foreach(q[i])$write( "%3d",q[i]); $display; //显示结果
//删除q下标为1的元素
q.delete(1); //0 2 3 4 5
foreach(q[i])$write( "%3d",q[i]); $display; //显示结果
//删除整个队列
q={};
end
endmodule
```
># 关联数组
当你只需要偶尔创建一个大容量数组,那么动态数组已经足够好用了,但是如果需要超大容量的呢?sv提供了关联数组用来保存稀疏矩阵的元素。也就是说只为实际写入的数据开辟存储空间。**可以将其理解为哈希表**,虽然哈希表带来了额外开销,但是在这种情况下,这是可以也接受的。</br>
**例 : 关联数组声明,初始化和使用**
```
module tb ;
bit [63:0] assoc[ bit [63:0] ],idx = 1;
initial begin
//对稀疏分布的元素进行赋值
repeat (3) begin
assoc[idx] = idx;
idx = idx << 1;
end
//foreach遍历数组
foreach(assoc[i])$display("assoc[%h]=%h",i,assoc[i]);
$display("+++++++++++++++++++++++");
//使用函数遍历数组
if( assoc.first(idx) ) begin
do
$display("assoc[%h]=%h",idx,assoc[idx]);
while( assoc.next(idx) ); //得到下一个索引
end
//找到并删除第一个元素
assoc.first(idx);
assoc.delete(idx);
$display("The array now has %0d elements",assoc.num);
end
endmodule
```
结果
```
Start run at Nov 2 22:22 2020
assoc[0000000000000001]=0000000000000001
assoc[0000000000000002]=0000000000000002
assoc[0000000000000004]=0000000000000004
+++++++++++++++++++++++
assoc[0000000000000001]=0000000000000001
assoc[0000000000000002]=0000000000000002
assoc[0000000000000004]=0000000000000004
The array now has 2 elements
```
**例 : 使用带字符串索引的关联数组**
```
//关联数组也可以用字符串索引进行寻址,使用字符串索引读取文件,并建立关联数组switch,可以实现字符串到数字的映射。
/*
输入文件内容如下:
42 min_address
1492 max_address
*/
int switch[string],min_address,max_address; //定义变量
initial begin //初始化
int i,r,file;
string s;//string 用来年保存长度可变的字符串常量
file = $fopen(“switch.txt”,r); //在当前目录下以只读的方式打开文件switch.txt,使用指针向量file指向该文件
while(! $feof(file) ) begin //未读取到文件的结尾时
r=$fscanf (file, “%d %s”, i, s); //将文件中的数字以10进制的方式保存到i中,字符串保存到s中
switch[s] = i; //为数组中的字符串指定地址
end
$fclose(fire); //关闭文件
//获取最小地址值,缺省为0
min_address=switch[“min_address”] //将min_address对应的地址(数字)赋值给min_address
//获取最大地址值,缺省为1000
if(switch.exists(“max_address”)) //使用exists函数判断switch数组中是否含有“max_address”
max_address = switch[“max_address”]//含有的话,将内容的地址赋值给 max_address
else
max_address =1000 //不存在指定内容,则默认地址为1000
//打印数组的所有元素
foreach(switch [s])
$display(“switch[ ‘ %s ’ ] = %0d ”, s ,switch[s] );//打印数组的内容和相应的地址
end
```
---
**例 : 字符关联数组操作**
```
module tb ;
bit [63:0] assoc[ string ];
initial begin
//对稀疏分布的元素进行赋值
assoc["a"] = 1;
assoc["b"] = 2;
assoc["c"] = 3;
//foreach遍历数组
foreach(assoc[i])$display("assoc[%s]=%h",i,assoc[i]);
end
endmodule
```
># 链表
sv提供了链表数据结构,类似于STL的列表容器,这个容器被定义为参数化的类,可以根据用户所需存放各种类型的数据。</br>
虽然sv提供了链表,但是应该避免使用它。sv使用队列更高效。
># 数组的方法
sv提供了很多数组的方法,可以用于任何一种非合并数组的类型,**包括定宽数组,动态数组,队列和关联数组**。
## sum方法:数组求和
**例 : 数组求和**
```module tb ;
bit on[5] = '{0,1,0,1,0};//单bit数组
initial begin
foreach( on [i])$write("%3d",on[i]);$display;
//单bit求和
$display("on.sum=%0d",on.sum);
end
endmodule
```
结果
```
Start run at Nov 2 22:49 2020
0 1 0 1 0
on.sum=0
```
>>sum方法的结果位宽和数组定义的位宽是一致的。
## product方法:数组求积
**例 :数组求积**
```
module tb ;
int on[3] = '{1,2,3};//单bit数组
initial begin
foreach( on [i])$write("%3d",on[i]);$display;
//单bit求和
$display("on.product=%0d",on.product);
end
endmodule
```
结果
```
Start run at Nov 2 22:57 2020
1 2 3
on.product=6
```
##and,or,xor方法:数组求与,或,异或
**例 :数组求与,或,异或**
```
module tb ;
int on[3] = '{1,3,3};//单bit数组
initial begin
foreach( on [i])$write("%3d",on[i]);$display;
$display("on.and=%0d",on.and);
$display("on.or=%0d",on.or);
$display("on.xor=%0d",on.xor);
end
endmodule
```
## min,max方法:最大值最小值方法
**注意返回值为一个队列!**
**例 :最大值最小值方法**
```
module tb ;
int on[] = '{1,3,3,9};
int rt[$];
initial begin
foreach( on [i])$write("%3d",on[i]);$display;
rt=on.min();foreach(rt[i])$write("%3d",rt[i]);$display;
rt=on.max();foreach(rt[i])$write("%3d",rt[i]);$display;
end
endmodule
```
结果
```
Start run at Nov 2 23:11 2020
1 3 3 9
1
9
```
## unique方法:排除重复数值
**注意返回值为一个队列!**
**例 :排除重复数值**
```
module tb ;
int on[] = '{1,3,3,9};
int rt[$];
initial begin
foreach( on [i])$write("%3d",on[i]);$display;
rt=on.unique();foreach(rt[i])$write("%3d",rt[i]);$display;
end
endmodule
```
结果
```
Start run at Nov 2 23:15 2020
1 3 3 9
1 3 9
```
## size方法:获取数组大小
**例 :获取数组大小**
```
module tb ;
int on[] = '{1,3,3,9};
int rt[$];
initial begin
foreach( on [i])$write("%3d",on[i]);$display;
//获取动态数组的大小
$display("len=%0d",on.size());
//获取各种数组大小的方法
$display("len=%0d",$size(on));
endmodule
```
结果
```
Start run at Nov 2 23:18 2020
1 3 3 9
len=4
len=4
```
## find方法:数组定位方法
**注意返回值为一个队列!**
**例 :find数组定位方法**
```
module tb ;
int on[] = '{4,1,3,3,9};
int rt[$];
initial begin
foreach( on [i])$write("%3d",on[i]);$display;
//找出所有大于等于3的元素 4 3 3 9
rt=on.find with (item >= 3);
foreach(rt[i])$write("%3d",rt[i]);$display;
//找出值大于等于2的索引 0 2 3 4
rt=on.find_index with (item >= 2);
foreach(rt[i])$write("%3d",rt[i]);$display;
//找出第一个大于4的值 9
rt=on.find_first with (item >4);
foreach(rt[i])$write("%3d",rt[i]);$display;
//找出最后一个小于9的值 3
rt=on.find_last with (item < 9);
foreach(rt[i])$write("%3d",rt[i]);$display;
//找出第一个大于4的数据的索引值 4
rt=on.find_first_index with (item >4);
foreach(rt[i])$write("%3d",rt[i]);$display;
//找出最后一个==3的数据的索引值
rt=on.find_last_index with (item == 3);
foreach(rt[i])$write("%3d",rt[i]);$display;
end
endmodule
```
结果
```
Start run at Nov 2 23:31 2020
4 1 3 3 9
4 3 3 9
0 2 3 4
9
3
4
3
```
**例 : 等同的几种描述**
```
rt=on.find_first with (item >= 3);
rt=on.find_first() with (item >= 3);
rt=on.find_first(item) with (item >= 3);
rt=on.find_first(x) with (x >= 3);
```
## 数组排序方法:reverse,sort,rsort,shuffle
**例:数组排序**
```
module tb ;
int on[] = '{4,1,3,3,9};
int rt[$],msum;
initial begin
foreach( on [i])$write("%3d",on[i]);$display;
//数组反序
on.reverse();
foreach( on [i])$write("%3d",on[i]);$display;
//数组 小->大
on.sort();
foreach( on [i])$write("%3d",on[i]);$display;
//数组 大->小
on.rsort();
foreach( on [i])$write("%3d",on[i]);$display;
//数组洗牌
on.shuffle();
foreach( on [i])$write("%3d",on[i]);$display;
end
endmodule
```
结果
```
Start run at Nov 3 00:12 2020
4 1 3 3 9
9 3 3 1 4
1 3 3 4 9
9 4 3 3 1
3 4 1 9 3
```
## 结构数组的使用和排序
**例 : 结构数组的使用和排序例子**
```
module tb ;
int rt[$],msum;
struct packed {byte red,green,blue;} c[]; //结构数组
initial begin
c=new[5];
foreach(c[i])c[i] = $urandom;//随机赋值
foreach( c[i])$write("%10d",c[i].red);$display;
c.sort with (item.red); //up排序red
foreach( c[i])$write("%10d",c[i].red);$display;
end
endmodule
```
结果
```
Start run at Nov 3 00:17 2020
-30 -34 127 -86 121
-86 -34 -30 121 127
```
> # typedef创建新的数据类型
**例 :创建新数据类型**
```
parameter N = 8;
typedef reg [N - 1 : 0 ] opreg_t;
opreg_t c;
```
> # struct创建新的数据类型
**例 :struct创建新数据类型**
```
module tb ;
int rt[$];
typedef struct packed {byte red,green,blue;} pixel_s;//结构数组
typedef struct packed {int a;bit[2:0] b;} m_s;//结构数组
pixel_s c='{1,2,3};
m_s cc = '{
32'd23,
3'b101
};
initial begin
$display("%5d %5d %5d",c.red,c.green,c.blue);
$display("%5d %5d",cc.a,cc.b);
end
endmodule
```
结果
```
Start run at Nov 3 00:38 2020
1 2 3
23 5
```
># 静态转换
静态转换操作不对转换值进行检查。
**例 : 静态转换例子**
```
module tb ;
int rt[$];
int i ;
real r;
initial begin
i = int '(10.0 - 0.1); //非强制转换
r = real '(42);
$display(i);
$display(r);
end
endmodule
```
> # 流操作
```
module tb ;
int rt[$];
byte h ;
bit [3:0] q[2] = '{4'h04,4'h01} ;
initial begin
$display("%6b %6b",q[0],q[1]);
//将q打包为byte
h = {>>{q}}; //0100_0001
$display("%b",h);
//位倒叙
h = {<<{h}}; //1000_0010
$display("%b",h);
end
endmodule
```
- 序
- 第1章 Linux下开发FPGA
- 1.1 Linux下安装diamond
- 1.2 使用轻量级linux仿真工具iverilog
- 1.3 使用linux shell来读写串口
- 1.4 嵌入式上的linux
- 设备数教程
- linux C 标准库文档
- linux 网络编程
- 开机启动流程
- 1.5 linux上实现与树莓派,FPGA等通信的串口脚本
- 第2章 Intel FPGA的使用
- 2.1 特别注意
- 2.2 高级应用开发流程
- 2.2.1 生成二进制bit流rbf
- 2.2.2 制作Preloader Image
- 2.2.2.1 生成BSP文件
- 2.2.2.2 编译preloader和uboot
- 2.2.2.3 更新SD的preloader和uboot
- 2.3 HPS使用
- 2.3.1 通过JTAG下载代码
- 2.3.2 HPS软件部分开发
- 2.3 quartus中IP核的使用
- 2.3.1 Intel中RS232串口IP的使用
- 2.4 一些问题的解决方法
- 2.4.1 关于引脚的复用的综合出错
- 第3章 关于C/C++的一些语法
- 3.1 C中数组作为形参不传长度
- 3.2 汇编中JUMP和CALL的区别
- 3.3 c++中map的使用
- 3.4 链表的一些应用
- 3.5 vector的使用
- 3.6 使用C实现一个简单的FIFO
- 3.6.1 循环队列
- 3.7 C语言不定长参数
- 3.8 AD采样计算同频信号的相位差
- 3.9 使用C实现栈
- 3.10 增量式PID
- 第4章 Xilinx的FPGA使用
- 4.1 Alinx使用中的一些问题及解决方法
- 4.1.1 在Genarate Bitstream时提示没有name.tcl
- 4.1.2 利用verilog求位宽
- 4.1.3 vivado中AXI写DDR说明
- 4.1.4 zynq中AXI GPIO中断问题
- 4.1.5 关于时序约束
- 4.1.6 zynq的PS端利用串口接收电脑的数据
- 4.1.7 SDK启动出错的解决方法
- 4.1.8 让工具综合是不优化某一模块的方法
- 4.1.9 固化程序(双核)
- 4.1.10 分配引脚时的问题
- 4.1.11 vivado仿真时相对文件路径的问题
- 4.2 GCC使用Attribute分配空间给变量
- 4.3 关于Zynq的DDR写入byte和word的方法
- 4.4 常用模块
- 4.4.1 I2S接收串转并
- 4.5 时钟约束
- 4.5.1 时钟约束
- 4.6 VIVADO使用
- 4.6.1 使用vivado进行仿真
- 4.7 关于PicoBlaze软核的使用
- 4.8 vivado一些IP的使用
- 4.8.1 float-point浮点单元的使用
- 4.10 zynq的双核中断
- 第5章 FPGA的那些好用的工具
- 5.1 iverilog
- 5.2 Arduino串口绘图器工具
- 5.3 LabVIEW
- 5.4 FPGA开发实用小工具
- 5.5 Linux下绘制时序图软件
- 5.6 verilog和VHDL相互转换工具
- 5.7 linux下搭建轻量易用的verilog仿真环境
- 5.8 VCS仿真verilog并查看波形
- 5.9 Verilog开源的综合工具-Yosys
- 5.10 sublim text3编辑器配置verilog编辑环境
- 5.11 在线工具
- 真值表 -> 逻辑表达式
- 5.12 Modelsim使用命令仿真
- 5.13 使用TCL实现的个人仿真脚本
- 5.14 在cygwin下使用命令行下载arduino代码到开发板
- 5.15 STM32开发
- 5.15.1 安装Atollic TrueSTUDIO for STM32
- 5.15.2 LED闪烁吧
- 5.15.3 模拟U盘
- 第6章 底层实现
- 6.1 硬件实现加法的流程
- 6.2 硬件实现乘法器
- 6.3 UART实现
- 6.3.1 通用串口发送模块
- 6.4 二进制数转BCD码
- 6.5 基本开源资源
- 6.5.1 深度资源
- 6.5.2 FreeCore资源集合
- 第7章 常用模块
- 7.1 温湿度传感器DHT11的verilog驱动
- 7.2 DAC7631驱动(verilog)
- 7.3 按键消抖
- 7.4 小脚丫数码管显示
- 7.5 verilog实现任意人数表决器
- 7.6 基本模块head.v
- 7.7 四相八拍步进电机驱动
- 7.8 单片机部分
- 7.8.1 I2C OLED驱动
- 第8章 verilog 扫盲区
- 8.1 时序电路中数据的读写
- 8.2 从RTL角度来看verilog中=和<=的区别
- 8.3 case和casez的区别
- 8.4 关于参数的传递与读取(paramter)
- 8.5 关于符号优先级
- 第9章 verilog中的一些语法使用
- 9.1 可综合的repeat
- 第10章 system verilog
- 10.1 简介
- 10.2 推荐demo学习网址
- 10.3 VCS在linux上环境的搭建
- 10.4 deepin15.11(linux)下搭建system verilog的vcs仿真环境
- 10.5 linux上使用vcs写的脚本仿真管理
- 10.6 system verilog基本语法
- 10.6.1 数据类型
- 10.6.2 枚举与字符串
- 第11章 tcl/tk的使用
- 11.1 使用Tcl/Tk
- 11.2 tcl基本语法教程
- 11.3 Tk的基本语法
- 11.3.1 建立按钮
- 11.3.2 复选框
- 11.3.3 单选框
- 11.3.4 标签
- 11.3.5 建立信息
- 11.3.6 建立输入框
- 11.3.7 旋转框
- 11.3.8 框架
- 11.3.9 标签框架
- 11.3.10 将窗口小部件分配到框架/标签框架
- 11.3.11 建立新的上层窗口
- 11.3.12 建立菜单
- 11.3.13 上层窗口建立菜单
- 11.3.14 建立滚动条
- 11.4 窗口管理器
- 11.5 一些学习的脚本
- 11.6 一些常用的操作语法实现
- 11.6.1 删除同一后缀的文件
- 11.7 在Lattice的Diamond中使用tcl
- 第12章 FPGA的重要知识
- 12.1 面积与速度的平衡与互换
- 12.2 硬件原则
- 12.3 系统原则
- 12.4 同步设计原则
- 12.5 乒乓操作
- 12.6 串并转换设计技巧
- 12.7 流水线操作设计思想
- 12.8 数据接口的同步方法
- 第13章 小项目
- 13.1 数字滤波器
- 13.2 FIFO
- 13.3 一个精简的CPU( mini-mcu )
- 13.3.1 基本功能实现
- 13.3.2 中断添加
- 13.3.3 使用中断实现流水灯(实际硬件验证)
- 13.3.4 综合一点的应用示例
- 13.4.5 使用flex开发汇编编译器
- 13.4.5 linux--Flex and Bison
- 13.4 有符号数转单精度浮点数
- 13.5 串口调试FPGA模板