学习记录
1.fpga中什么是输入信号与时钟同步,什么是异步输入信号
1.1. 与时钟同步的输入信号
- 定义
- 在FPGA(现场可编程门阵列)中,与时钟同步的输入信号是指其变化与系统时钟信号的边沿(上升沿或下降沿)有确定的时序关系的输入信号。
- 工作原理
- 同步电路设计基于时钟信号来控制数据的传输和处理。当一个输入信号是与时钟同步时,它的采样时刻是由时钟沿决定的。例如,在一个正沿触发的同步系统中,输入信号的值只会在时钟的上升沿被寄存器采样并进行后续处理。
- 假设我们有一个简单的计数器电路,输入信号
count_enable
用于控制计数器是否计数。如果count_enable
是与时钟同步的信号,那么只有当count_enable
在时钟上升沿为高电平时,计数器才会增加计数。
- 优点
- 可预测性:同步电路的行为更容易预测,因为数据的变化是按照时钟节拍进行的。这有助于进行时序分析和确保电路的正确性。
- 避免亚稳态:由于输入信号与时钟有确定的时序关系,在合理的设计约束下,可以减少亚稳态的发生概率。亚稳态是指电路在某个时刻处于不稳定状态,可能导致错误的输出。
1.2. 异步输入信号
- 定义
- 异步输入信号是指其变化与系统时钟信号没有固定时序关系的输入信号。它可以在任何时刻发生变化,不受时钟信号的控制。
- 工作原理
- 异步输入信号可能来自外部设备,如按键、传感器等,这些设备的操作不受FPGA内部时钟的约束。当FPGA接收到异步输入信号时,需要特殊的处理机制。例如,一个按键输入信号,用户可以在任何时间按下或松开按键,这个按键信号相对于FPGA的时钟就是异步的。
- 问题与处理
- 亚稳态问题:由于异步信号与时钟没有同步关系,当使用异步信号直接驱动同步电路中的寄存器时,很容易导致亚稳态。为了避免这种情况,通常需要采用异步信号同步化技术,如使用双稳态触发器(如D触发器)来对异步信号进行同步处理。例如,对于一个异步的复位信号
async_reset
,可以通过两个串联的D触发器将其同步到系统时钟域,第一个D触发器的输出作为第二个D触发器的输入,经过这样的处理后,得到的同步复位信号就可以安全地用于同步电路中。 - 时序分析复杂性:异步输入信号会增加电路时序分析的复杂性,因为其变化不受时钟控制,难以用传统的基于时钟周期的时序分析方法来准确评估电路的性能和正确性。
- 亚稳态问题:由于异步信号与时钟没有同步关系,当使用异步信号直接驱动同步电路中的寄存器时,很容易导致亚稳态。为了避免这种情况,通常需要采用异步信号同步化技术,如使用双稳态触发器(如D触发器)来对异步信号进行同步处理。例如,对于一个异步的复位信号
2.fpga中always @ (*)什么时候执行
2.1. 敏感列表为*
的含义
- 在FPGA编程中,
always @(*)
是一种过程块的敏感列表表示方式。*
表示这个always
块对其内部使用到的所有输入信号敏感。
2.2. 执行时机
- 当
always @(*)
块内部使用的任何一个输入信号发生变化时,这个always
块就会执行。例如,如果在这个always
块内部使用了信号a
、b
和c
,那么只要a
、b
或者c
中的任意一个信号发生了电平的改变(从0到1或者从1到0),always
块中的代码就会被执行。 - 假设在一个简单的组合逻辑电路描述中,有如下代码:
module example (
input wire a,
input wire b,
output wire y
);
wire temp;
always @(*) begin
temp = a & b;
y = ~temp;
end
endmodule
- 在这个例子中,
always @(*)
块内部使用了输入信号a
和b
。当a
或者b
发生变化时,always
块就会执行。首先计算temp
的值(a
和b
的与操作),然后计算y
的值(temp
的取反操作)。这样就实现了一个简单的组合逻辑电路,y
的输出会根据a
和b
的输入变化而实时更新。
3.fpga中wire [7:0] s_str[0:7];
在FPGA(现场可编程门阵列)编程中,wire [7:0] s_str[0:7];
是一种声明语句。
3.1. 数据类型与位宽
wire
是一种数据类型,表示线网类型。在数字电路中,线网类型用于连接不同的模块或者逻辑元件,它表示信号在电路中的连接关系。[7:0]
表示每个元素的位宽为8位。这意味着每个s_str
中的元素可以存储一个8位的值,范围从00000000
到11111111
(二进制表示)或者0到255(十进制表示)。
3.2. 数组声明
s_str[0:7]
声明了一个名为s_str
的数组。这个数组包含8个元素(索引从0到7),每个元素都是一个8位的线网类型。这种数组结构在FPGA编程中非常有用,例如:- 在处理多个相似的信号或者数据时,可以使用数组来简化代码结构。假设
s_str
是用来存储8个不同端口输入的8位数据,那么可以方便地通过索引来访问每个端口的数据。例如,s_str[0]
表示数组中的第一个8位数据,s_str[3]
表示第四个8位数据等。 - 在一些数据处理模块中,如数据缓存或者并行数据处理模块,这种数组结构可以提高代码的可读性和可维护性。例如,在一个图像数据处理的FPGA应用中,如果要处理8个相邻像素的数据,就可以将这8个像素的数据存储在
s_str
数组中,每个元素对应一个像素的8位数据(可能是灰度值等),然后对这些数据进行并行处理,如滤波、边缘检测等操作。
4.fpga中if(~rstn) {en_s2, ialpha_s2, i_beta1_s2, i_beta2_s2, i_beta3_s2} <= 0;
在FPGA(现场可编程门阵列)的代码中,这是一个典型的复位逻辑部分。
4.1. 条件判断
if(~rstn)
语句表示当rstn
信号为低电平时(因为~
是取反操作符),执行花括号内的操作。在很多FPGA设计中,复位信号rstn
是低电平有效,这是一种常见的设计约定。
4.2. 复位操作
-
{en_s2, ialpha_s2, i_beta1_s2, i_beta2_s2, i_beta3_s2} <= 0;
这一语句是一个并行赋值语句。当复位条件满足(rstn
为低电平)时,将多个信号(en_s2
、ialpha_s2
、i_beta1_s2
、i_beta2_s2
和i_beta3_s2
)同时赋值为0。这种操作通常用于在系统复位时将某些内部状态或者使能信号初始化为已知的状态,以确保系统从一个确定的初始状态开始运行。 -
例如,假设
en_s2
是一个模块的使能信号,在复位时将其设置为0可以确保该模块在复位期间处于关闭或者非使能状态。而ialpha_s2
、i_beta1_s2
、i_beta2_s2
和i_beta3_s2
可能是与某些计算或者状态相关的信号,将它们初始化为0可以清除之前可能存在的任何不确定状态。 -
在实际的FPGA设计中,这种复位逻辑可能是一个更大的状态机或者逻辑模块的一部分。例如,在一个数字信号处理模块中,可能有多个子模块,每个子模块都有自己的复位逻辑,当整个系统复位时,这些子模块的相关信号都会被初始化为合适的状态,以保证系统的正确运行。
5.fpga硬核和软核交换数据方案
以下是一些FPGA硬核和软核交换数据的方案:
5.1.共享存储器方案
- 原理
- 在FPGA内部构建一块共享的存储器(如双端口RAM或者FIFO)。硬核和软核都可以对这个共享存储器进行读写操作,从而实现数据交换。
- 例如,硬核(如硬核处理器)可以将采集到的数据写入共享存储器的特定地址空间,软核(如用户自定义的软核处理器或者逻辑模块)可以从该地址空间读取数据进行后续处理。反之,软核也可以将处理结果写入共享存储器,供硬核使用。
- 实现要点
- 地址分配:需要明确划分硬核和软核对共享存储器的访问地址范围,以避免数据冲突。例如,将共享存储器的低地址空间分配给硬核写入,高地址空间分配给软核写入,中间部分作为共享的读取区域。
- 读写控制信号:合理设计读写控制信号,确保在同一时间只有一个核对共享存储器进行写操作(读操作可以同时进行)。可以使用互斥信号(如信号量)来实现。
5.2.总线连接方案
- 原理
- 利用FPGA内部的总线结构(如AXI总线等)将硬核和软核连接起来。硬核和软核作为总线上的主设备或者从设备,通过总线进行数据传输。
- 例如,硬核作为主设备发起数据传输请求,将数据发送到总线上指定的地址,软核作为从设备监听总线地址,如果地址匹配则接收数据。同样,软核也可以作为主设备向硬核发送数据。
- 实现要点
- 总线协议配置:根据所选的总线类型(如AXI4、AXI4 - Lite等),正确配置硬核和软核的总线接口。对于AXI4总线,需要配置地址宽度、数据宽度、突发长度等参数。
- 仲裁机制:如果有多个主设备(例如多个软核或者硬核与软核同时作为主设备),需要设计仲裁机制来决定哪个主设备可以优先使用总线。可以采用轮询仲裁、优先级仲裁等方式。
5.3.直接端口连接方案
- 原理
- 当硬核和软核的接口信号兼容时,可以直接将硬核的输出端口连接到软核的输入端口,反之亦然。这种方式适用于简单的数据传输,数据流向比较固定的情况。
- 例如,硬核的一个数据输出引脚直接连接到软核的一个数据输入引脚,硬核将处理后的一位数据发送给软核进行后续逻辑判断。
- 实现要点
- 信号匹配:要确保硬核和软核的端口信号在电平标准(如LVTTL、LVCMOS等)、数据宽度、时钟域等方面匹配。如果时钟域不同,可能需要进行时钟域跨越处理(如使用异步FIFO等)。
- 数据同步:由于直接连接可能存在不同的时钟域或者信号延迟问题,需要考虑数据的同步。例如,在软核中使用寄存器对输入数据进行采样,以确保数据的稳定性。
6.fpag中result1<={data_den1[15],data_den1[12:0],1’b0,1’b0};,什么意思
在Verilog硬件描述语言中,fpag
中的这行代码是在进行位拼接操作。具体来说,它将多个位拼接在一起形成一个新的向量。让我们逐步解析这行代码:
result1 <= {data_den1[15], data_den1[12:0], 1'b0, 1'b0};
-
data_den1[15]
: 这是从data_den1
向量中提取的第16位(因为Verilog中的位索引是从0开始的)。 -
data_den1[12:0]
: 这是从data_den1
向量中提取的第13位到第1位,形成一个13位的子向量。 -
1'b0
: 这是一个1位的二进制数,值为0。 -
1'b0
: 这是另一个1位的二进制数,值为0。 -
{ }
: 大括号{}
用于位拼接操作,将上述各个部分拼接成一个新的向量。
因此,这行代码的意思是将data_den1
的第16位、第13位到第1位,以及两个0位拼接在一起,形成一个新的向量,并将其赋值给result1
。
假设data_den1
是一个16位的向量,那么result1
将是一个17位的向量,其组成如下:
- 第17位:
data_den1[15]
- 第16位到第4位:
data_den1[12:0]
- 第3位:
1'b0
- 第2位:
1'b0
总结:这行代码将data_den1
的部分位和两个0位拼接成一个新的17位向量result1
。
7.fpga中result<={{9{data_den[41]}},data_den[41:9]};
在Verilog硬件描述语言中,result<={{9{data_den[41]}},data_den[41:9]};
这行代码执行的是位拼接操作。具体来说,它将 data_den
的某些位拼接成一个新的向量,并将其赋值给 result
。
让我们逐步解析这行代码:
-
data_den[41]
:这是从data_den
向量中提取的第42位(因为Verilog中的位索引是从0开始的)。 -
{9{data_den[41]}}
:这是一个重复操作,表示将data_den[41]
的值重复9次。如果data_den[41]
是1,那么结果就是111111111
(9个1);如果data_den[41]
是0,那么结果就是000000000
(9个0)。 -
data_den[41:9]
:这是从data_den
向量中提取的第42位到第10位,形成一个33位的子向量。 -
{{9{data_den[41]}}, data_den[41:9]}
:这是位拼接操作,将重复的9位和33位的子向量拼接在一起,形成一个新的42位向量。
因此,这行代码的意思是将 data_den
的第42位重复9次,然后拼接上 data_den
的第42位到第10位,形成一个新的42位向量,并将其赋值给 result
。
总结:
result
是一个42位的向量。- 前9位是
data_den[41]
的值重复9次。 - 接下来的33位是
data_den
的第42位到第10位。
这种操作在某些特定的硬件设计中非常有用,尤其是在需要对数据进行特定格式化或处理时。