[读书笔记] 用 Verilog 设计 FPGA 样机实例解析 -4.8.2019

2024-02-09 15:50

本文主要是介绍[读书笔记] 用 Verilog 设计 FPGA 样机实例解析 -4.8.2019,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

FPGA Prototyping by Verilog Examples [美]Ping D.Chu [译]李艳志 孟伟 刘军 机械工业出版社

中文版 ISBN: 9787111536444

分类:可编程逻辑器件-系统设计

配套网站:https://academic.csuohio.edu/chu_p/rtl/fpga_vlog.html


一、门级组合电路

1.标识符,由字母、数字、下划线 (_) 和符号 ($) 组合而成

2.四值系统,0、1、Z、X(X仅用于建模与仿真)

3.数据类型,线网类(表示硬件元件间的物理连线,wire、wand、supply0)、变量类(表示行为模型中的抽象存储,reg、integer、real、time、realtime,后三种仅用于建模仿真)

4.数字表示

[符号][位宽]' [基数][数值]  其中位宽可选,若数值位数少于位宽,则填充 0 或z、x(当数值最高位为z、x时),若未指定,则取决于主机,且至少为32位。此外基数省略时,默认为十进制

b/B 二进制  o/O 八进制  h/H 十六进制  d/D 十进制

5.运算符,~、&、|、^

6.程序结构,I/O端口声明、信号声明、模块体

module eq1
([mode] [data-type][port-names],...[mode] [data-type][port-names]
)

程序体的描述方法,连续赋值、Always块、模块示例

assign [signal_name] = [expression];

信号声明指定了模块使用的内部信号和参数,如没有声明,则默认为线网类型

[数据类型] [端口名词]

结构描述

[模块名称] [例化名称]
(.[端口名称] ([信号名称]),....[端口名称] ([信号名称])
)

也可以通过规则列表,即按照原模块的顺序直接列出所有信号名称

用户数据报协议 UDPS,用表的形式描述电路

测试程序 testbench,uut 测试底层电路实例

附:eq1.v —> 1bit 比较器,eq2.v —> 2bit 比较器


二、FPGA 及 EDA 软件概述 (以 Spartan-3 为例)

1.FPGA 中最小单元是逻辑单元 LC,其包含 LUT 查找表和一个 D 触发器,8个逻辑单元通过内部布线结构组合起来,2个 LC 组合为一个 Slice,4个Slice组合成一个可配置逻辑块 CLB

宏单元,包含4种:组合乘法器、块 RAM、数字时钟管理器 DCM、I/O块 IOB

2.开发流程

附:eq1.v,eq2.v,.ucf 配置文件


三、寄存器传输级组合逻辑电路

1.运算符,共24个

算术运算符 + - * / %取模 **求幂;移位运算符 >> <<逻辑右/左移 >>> <<<算术右/左移;

关系运算符 > < >= <=;相等运算符 == !=逻辑相等/不等 === !==全等/全不等;

按位运算符 ~ & | ^;规约运算符 & | ^规约与/或/异或;逻辑运算符 ! && ||逻辑非/与/或;

连接运算符 {}连接 {{}}复制;条件运算符 ?:条件

注意:>>>移入的是最高符号位,其他移入的均为0

& | ^ 操作可以只有一个运算符,即缩减运算符,即对运算符各位按位操作

拼接运算符实现多个信号的拼接,复制运算符 {4{2'b01}} —> 8'b01010101

条件运算符

[signal] = [boolean-exp]? [true-exp] : [false-exp]

运算符优先级:! ~ + - ; ** * / + - ; >> << >>> <<< ; <<=>>= ; ==! ==== !== ; & ^ | ; && || ; ?:

2.组合逻辑电路 always 块

阻塞顺序赋值、if 语句、case 语句

always、initial

always @ ([sensitivity-list])begin [optional name][optional local variable declaration][procedural statement]...
end

顺序赋值语句:阻塞、非阻塞,阻塞赋值立即赋值,非阻塞赋值在 always 块最后赋值

一般对组合逻辑使用阻塞,对时序逻辑使用非阻塞

[variable-name] = [expression]; //阻塞
[variable-name] <= [expression]; //非阻塞

变量,reg、integer、real、time、realtime。integer数据的宽度固定(32位)

3.if 语句

if [bool-expr]
begin[procedural statement];[procedural statement];
end
else
begin[procedural statement];[procedural statement];
end

也可以使用 else if 构成"级联",并构成优先级布线

4.case 语句

case [case-expr][item]:begin[procedural statement];[procedural statement];...end[item]:begin[procedural statement];[procedural statement];...end...default:begin[procedural statement];[procedural statement];...end
endcase

case 语句即为多路选择语句,分支项过多会导致很大的传播延迟

casez、casex 语句,casez 语句中 z 值被 ? 替代,casex 语句中 x z 值被 ? 替代

full case、parallel case。每一种输入组合都被覆盖,即为 full,每种分支的值都互斥,即为 parallel

5.条件控制语句的布线结构:优先路由网络 if-else、多路选择网络 parallel case

也可看为是多个 2 选 1 多路选择器,还是一个 n 选 1 多路选择器

6.通用编码准则

在组合逻辑中,同一变量被多个 always 块赋值,可仿真,不可被综合;always 块中未被赋值的变量将增加一个锁存器,应使得 if case 语句包含所有分支,在每一个分支为每一个输出信号赋值

7.参数和常量

常量可用 localparam 关键字声明

参数可用 parameter 声明,用于将信息传递到一个模块

module [module-name]
#(parmeter [parameter-name] = [default_value],...[parameter_name] = [default_value];
)
(...// I/O port declaration
);

verilog-1995 中,参数只能在开头后声明,且只能用顺序清单方式或 defparam 语句重新定义,另常数也规定定义为参数

8.实例

LED数码管译码器、"符号-幅值"加法器、桶式移位器、简化的浮点加法器

整数 — "符号-幅值" 格式,最高位为符号,剩余位显示数值

桶式移位器,即逐级对移位数值按位识别,进行任意位数的移位

简化的浮点加法器,共 13 位:1 位符号位 s、4 位指数阈 e、8 位尾数字段 f,即(-1)^{s}*.f*2^e

最大和最小的非零幅值为0.11111111*2^1111和0.10000000*2*0000

浮点数加法器计算步骤:排序、对齐、加减法、规范化,运算过程中的信号名称分别使用后缀 b、s、a、r、n 以分别表示大数、小数、对齐的数、加减法结果、规范化的数

附:eq1_always.v —> 1bit 比较器,prio_encoder.v —> 优先解码器,decoder_2_4.v —> 2:4解码器,

adder_carry.v —> 加法器,hex_to_sseg.v —> LED 数码管译码器,sign_mag_add.v —> "符号-数值" 数加法器,

barrel_shifter.v —> 桶式移位器,fp_adder.v —> 浮点加法器


四、常规时序电路

1.时序电路,输出与输入和内部状态有关

D 触发器和寄存器

D 触发器 DFF,主要参数:Tcq (clk 到 q 端的延迟)、Tsetup (建立时间)、Thold (保持时间)

同步系统包括:状态寄存器、次态逻辑、输出逻辑

最高运行频率、最小时钟周期,可设置期望的运行频率作为综合约束。时序电路时钟的最大频率必须超过所用晶振的频率

时序电路:常规时序电路、FSM、FSMD。使用非阻塞赋值 <=

2.触发器和寄存器的 HDL 代码

D触发器,有三种:不带异步复位、带异步复位 reset、带同步使能 en

寄存器,为由同一时钟和复位信号控制的 D 触发器的集合

寄存器文件,即带有一个输入端口和一个或多个输入端口的寄存器集合,用于快速、临时的存储

3.简单实例

移位寄存器:Free_running 寄存器,在每一时钟周期内右/左移一位;通用移位寄存器

二进制计数器:Free_running 二进制计数器,不断重复二进制序列实现;通用二进制计数器;模 m 计数器,实现从 0 到 m-1 不断循环计数

tick 信号,常用作与其他时序电路的接口的使能信号

4.时序电路的测试平台

时钟生成

always
beginclk = 1'b1;#(T/2);clk = 1'b0;#(T/2);
end

复位信号

initial
beginreset = 1'b1;#(T/2);reset = 1'b0;
end

@(negedge clk);    wait (q == 2);

5.案例

LED 分时复用电路,需保证 1kHz 左右的频率,其可用于十六进制数字的显示,即在输出 sseg 处添加一个译码器

码表,包含有 BCD 码计数器,并以 BCD 码计数,两种方案:case、if

FIFO,有两个控制信号 wr 写、rd 读,FIFO 头部始终可访问,任何时候都可对 FIFO 读。基于循环队列的实现,寄存器被排列为循环队列,并用两个指针访问,写指针指向队列头,读指针指向队列尾。两个状态信号 full empty,都在读写指针相同时发生置位。一种分别的机制为,使用两个触发器跟踪 empty 和 full 状态,初始化时其分别为 1、0,在每个时钟周期根据 wr rd 信号值修改此两个触发器。即刚读完即 empty,刚写完即 full。

附:d_ff.v —> D 触发器,reg.v —> 触发器,shift_reg.v —> 移位寄存器,bit_counter.v —> 二进制计数器,

mod_m_counter.v —> 模 m 计数器,disp_mux.v —> LED 分时复用电路,disp_hex_mux.v —> 十六进制数字 LED 分时复用,

stop_watch.v —> 码表,fifo.v —> FIFO缓冲器


五、有限状态机

1.有限状态机 FSM,用来对具有有限个内部转换状态的系统进行建模,这些内部状态的转换依赖于当前状态和外部输入

Mealy 输出、Moore 输出。如果一个 FSM 的输出只与其当前状态有关,则为 Moore 状态机;如一 FSM 输出和当前状态和外部输入都有关,则为 Mealy 状态机

状态机一般由一个抽象的状态图或 ASM 图说明,两者可随意转换

2.状态机编码设计:首先分类状态寄存器,然后使用组合逻辑对次态逻辑和输出逻辑进行编码。完整的状态机编码:状态寄存器、次态逻辑、Moore 输出逻辑、Mealy 输出逻辑

case,有两种设计方法,即次态逻辑与输出逻辑是否分开

ISE StateCAD,用户可图形化设计状态机

3.实例

上升沿检测器:基于 Moore、基于Mealy。基于 Mealy 设计需更少状态、更快运行速度,但易受毛刺信号影响

  

去抖电路,有多种去抖方案,这里是基于 FSM 的去抖方案。

注意:次态逻辑中要记得加 default 状态

附:fsm_eg.v —> FSM 举例,edge_detect_moore.v —> Moore 上升沿检测器,

edge_detect_mealy.v —> Mealy 上升沿检测器,edge_detect_gate.v —> 直接用门级实现上升沿检测器,

db_fsm.v —> FSM 实现去抖电路


六、带数据路径的有限状态机

1.带数据路径的有限状态机 FSMD,由一个 FSM 和常规时序电路组合而成。常用来检测外部命令和状态并生成控制信号,以指定常规时序电路的相应操作。FSMD 使用 RT (寄存器传输) 方法学的描述来实现系统

单个 RT 操作,即对于单个目标寄存器的数据处理和传输

        r_{dsp}\leftarrow f(r_{src1},r_{src2},...,r_{srcn})

ASMD 图,即将 RT 操作纳入到 ASM。图中的 RT 操作由模块内嵌的时钟信号控制,且目标寄存器的值得更像发生在 FSMD 退出当前 ASMD 块时,而非在 ASMD 块内

带寄存器的判决盒,FSMD 模块框图从形式上可分为数据路径和控制路径,数据路径的执行需进行 RT 操作,其包含数据寄存器、功能单元和布局网络

数据路径根据控制信号执行期望的 RT 操作并生成相应的内部状态信号,控制路径即一个有限状态机

2.FSMD 的代码开发

基于 RT 方法学的去抖电路

追溯 HDL 编码方式的方法:数据流组成的白盒描述、数据流组成的黑盒描述

首先分离状态机控制流和关键数据流,再使用独立的代码段分别描述

带有数据路径元件的编码,即数据路径独立出来编写

带有隐含数据路径元件的编码,即在状态机控制路径中嵌入 RT 操作,隐含描述的方法更加遵循 ASMD 图,且更简单。但显示描述可以通过适当修改减少逻辑元件

3.实例

斐波那契数电路

除法电路,通过逐步移位来计算二进制除法。此外由于是二进制,可以直接比大小看是否可以除,可除即相减

二进制向 BCD 码转换电路

周期计数器,测量周期性的输入波形的周期,系统时钟为f,在两上升沿间测得 N 个周期,则其周期为 N*{​{1}/f}

低频率计数器,测量一个周期性的输入波形的频率,先求周期,再取倒数以获得较好的精确度

附:debounce_explicit.v —> 带明确数据路径元件的去抖电路,debounce.v —> 带隐含数据路径元件的去抖电路,

fib.v —> 斐波那契数电路,div.v —> 除法电路,bin2bcd —> 二进制向 BCD 码转换电路,

period_counter.v —> 周期计数器,low_freq_counter.v —> 低频率计数器


七、Verilog 相关的话题

1.阻塞和非阻塞

[variable-name] = [expression]; //阻塞
[variable-name] <= [expression]; //非阻塞

阻塞赋值立即发生,非阻塞赋值发生在所在 always 块结束时

组合逻辑电路中阻塞赋值语句的顺序很重要,一般情况下,阻塞赋值语句都可用非阻塞赋值语句替代

存储元件中须使用非阻塞赋值,以避免"竞争"

时序电路中使用阻塞和非阻塞赋值,其具体实现方式:触发器和组合逻辑是否在一个 always 块

2.另一种时序电路代码分格

先前代码都将 寄存器和次态逻辑 分开编写,另一种代码分格即将其组合起来

可以使用阻塞赋值获取次态逻辑的中间结果,并使用非阻塞赋值语句将中间结果赋值给寄存器,有时次态逻辑中的状态逻辑可以和次态逻辑结合起来

二进制计数器

FSM,在状态机也可以类似地,将状态寄存器和次态逻辑组合起来

FSMD,切要注意非寄存器输出要从 always 块中分离出来,单独成块

3.使用有符号数据类型

无符号整数和有符号整数,有符号整数通常由二进制补码格式表示

4 bit 二进制码盘,码盘中无符号整数和有符号整数的位置

在位宽扩展时,无符号数即在高位扩展 0,有符号数即扩展其符号位

Verilog-1995 中的有符号数:仅 integer 可以,reg 和 wire 默认为无符号数。同时 integer 位宽固定,使用很不便。可以按照符号数的扩展方式和计算方式手动编码,以实现任意位数的有符号数

Verilog-2001 中的有符号数:reg 和 wire 在声明时可通过 signed 关键字扩展为有符号类型。Verilog 默认仅在当表达式一边全部为有符号数,才会进行有符号数的扩展,否则进行 0 扩展

Verilog 中有两个系统函数:$signed()、$unsigned(),以将括号内的变量强制转换

4.在综合中使用函数

函数的基本语法:

module
...
//函数定义于 module 内
function [result_type] [func_id] ([input_arg]);begin[statements];end
endfunction
...
endmodule

5.仅用于测试仿真的额外结构

always 和 initial 块

//时钟单元
always
beginclk = 1'b1;#20;clk = 1'b0;#20;
end
//设置初值
initial
begin[procedural statements]
end

程序语句:阻塞赋值、非阻塞赋值、if 语句、case 语句、循环语句。支持的循环语句:for、while、repeat、forever

//for
for ([initial-assignment];[end-condition];[step-assignment])
begin[procedural-statements;]
end
//while
while ([end-condition])
begin[procedural-statements;]
end
//repeat
repeat ([number])
begin[procedural-statements;]
end
//forever
forever
begin[procedural-statements;]
end

forever 语句也可用于描述时钟单元

initial beginclk = 1'b0;
forever#10 clk = ~ clk;
end

时序控制

# [delay-time] //延时控制
@ ([eventl,[eventl,...); //事件控制
wait ([boolean_expression]) //等待控制
'timescale 

事件控制语句中,@ 紧跟敏感列表,posedge、negedge

wait 语句,挂起后面的语句,直到满足条件

timescale 指令,用于控制 Verilog 代码的编译和处理

'timescale [time-unit]/[time-precision] //指定事件和延时单元,指定仿真的分辨率

其时间单位可为:s、ms、us、ns、ps、fs

系统函数和任务

$unsigned  $signed  //数据类型转换函数
$time  $stime  $realtime  //仿真时间函数
$finish  $stop  //仿真控制任务:结束并退出、挂起
$display  $write  $strobe  $monitor  //显示任务
$display ([format_strinf],[argument],[argument],...);
常用换码:%d 十、%b 二、%o 八、%h 十六、%c 字符、%s 字符串、%g 实数
$write 类似 $display,但不会再字符的末尾添加换行符
$strobe 类似 $display,但在当前时间片的末尾执行,而非立即执行
$monitor 在每次参数变化时显示,而另外三个仅显示一次
$fopen  $fclose  文件访问函数
[mcd-name] = $fopen("[file-name]");  //返回一个与文件相关的 32 位多通道描述符,最低位为输出保留位,其他各位各代表一个文件是否打开
文件打开后,即可写入数据: $fdisplay  $fwrite  $fstrobe  $fmonitor
$fclose ([mcd-name],[format_string],...);
获取外部文件数据:$readmenb  readmenh
$readmemb/h ("[file_name]",[,em_variable]);

自定义函数和任务,任务可以后输入、输出、双向参数、还可以包含时序控制结构。而函数中不能包含有时序结构

task [task_id] ([arg]);  //其中 arg 默认数据类型是 reg,且 wire 不能被使用begin[statements];end
endtask

复杂测试平台示例:二进制计数器的测试模块,bin_gen 模块生成测试向量、monitor 模块监视输入激励和输出响应

附:and.v —> 与门,eq1.v —> 1bit 比较器,ab_ff.v —> 与门和 D 触发器的实现,bin_counter.v —> 二进制计数器,

fsm_eg.v —> FSM 实例,div.v —> FSMD 除法实例,mod_m_counter_fc.v —> 使用函数的模 m 计数器,

eq2_file_tb.v —> 测试,eq2_task.v —> 任务实现 2bit 比较器,eq2_function.v —> 函数实现 2bit 比较器,

bin_gen.v —> 测试向量生成器,bin_monitor.v —> 监视器,bin_counter_tb3.v —> 顶层模块


八、UART

1.UART,即通用异步收发传输器,是一种用串行通信方式来传输并行数据的电路。其常与 RS-232 标准同时使用,RS-232 标准规定的电平和 FPGA 的 I/O 电压不相同,因此需要在串口和 I/O 口间使用电平转换芯片

UART 包括一个发送器和一个接收器。数据为:1 位起始位(为0)、6-8 位数据位、可选的奇偶校验位、1-2 位停止位(为1)

在串口线上没有时钟信息,在传输前,需将波特率、数据位、停止位的数量和奇偶校验位等参数提前设置好

2.UART 接收子系统:波特率发生器、UART 接收器、接口电路

过采样步骤,过采样可以确保没有时钟的 UART 传输数据的可靠性,但也限制串行传输的波特率只能是系统时钟的一个很小的分频,以至于其不能用于高数据传输速率

波特率产生器,用来产生一个采样信号,其频率是 UART 波特率的 16 倍,对 UART 接收端来说,采样信号仅作为一个使能信号来使用,而非作为一个时钟来使用,即仅通过其计算每经过几个系统时钟周期产生一个采样点

UART 接收端

接口电路,通常有三种方案:单指示触发器、单指示触发器与单字缓冲器、一个 FIFO 缓冲器

单指示触发器的方案,容易导致数据被覆盖的问题。由此增添一个单字缓冲器,即不会覆盖前一个数据。另一种方案即直接使用FIFO 缓冲器缓存所有未读数据

3.UART 发送子系统:UART 发送器、波特率发生器、接口电路。UART 发送器本质上是一个按照特定速率把数据位一位一位输出的移位寄存器。发送端和接受端公用一个波特率发生器

4.UART 总系统简述

 

附:uart_rx.v —> UART 接收端,flag_buf.v —> 指示触发器和缓冲器的接口,uart_tx —> UART 发送器,

uart.v —> UART 顶层描述,uart_test.v —> UART 验证电路


九、PS2 键盘 & 十、PS2 鼠标

跳过


十一、外部 SRAM

 

 

 

 

 

 


十二、Xilinx Spartan-3 特殊存储器

 

 

 

 

 


十三、VGA 控制器 I :图形 & 十四、VGA 控制器 II:示例


 

这篇关于[读书笔记] 用 Verilog 设计 FPGA 样机实例解析 -4.8.2019的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/694639

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

怎么让1台电脑共享给7人同时流畅设计

在当今的创意设计与数字内容生产领域,图形工作站以其强大的计算能力、专业的图形处理能力和稳定的系统性能,成为了众多设计师、动画师、视频编辑师等创意工作者的必备工具。 设计团队面临资源有限,比如只有一台高性能电脑时,如何高效地让七人同时流畅地进行设计工作,便成为了一个亟待解决的问题。 一、硬件升级与配置 1.高性能处理器(CPU):选择多核、高线程的处理器,例如Intel的至强系列或AMD的Ry

BUUCTF靶场[web][极客大挑战 2019]Http、[HCTF 2018]admin

目录   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 [web][HCTF 2018]admin 考点:弱密码字典爆破 四种方法:   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 访问环境 老规矩,我们先查看源代码

基于51单片机的自动转向修复系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机

C++操作符重载实例(独立函数)

C++操作符重载实例,我们把坐标值CVector的加法进行重载,计算c3=c1+c2时,也就是计算x3=x1+x2,y3=y1+y2,今天我们以独立函数的方式重载操作符+(加号),以下是C++代码: c1802.cpp源代码: D:\YcjWork\CppTour>vim c1802.cpp #include <iostream>using namespace std;/*** 以独立函数

OWASP十大安全漏洞解析

OWASP(开放式Web应用程序安全项目)发布的“十大安全漏洞”列表是Web应用程序安全领域的权威指南,它总结了Web应用程序中最常见、最危险的安全隐患。以下是对OWASP十大安全漏洞的详细解析: 1. 注入漏洞(Injection) 描述:攻击者通过在应用程序的输入数据中插入恶意代码,从而控制应用程序的行为。常见的注入类型包括SQL注入、OS命令注入、LDAP注入等。 影响:可能导致数据泄

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动