异步FIFO设计

1 FIFO简介

FIFO的本质是RAM,具有先进先出的特性。

FIFO的基本使用原则:空时不能读,满时不能写

FIFO的两个重要参数:宽度和深度

FIFO的两种类型:

  • 同步FIFO:读写时钟相同,通常用来做数据缓存
  • 异步FIFO:读写时钟不同,通常用来做跨时钟域处理

2 异步FIFO设计要点

2.1 空满信号产生的原理

读空信号:

  • 复位的时候(读指针和写指针相等),读空信号有效
  • 读指针赶上写指针的时候,读空信号有效

写满信号:

  • 写指针赶上读指针的时候

2.2 空满指针跨时钟域处理,为什么要使用Gray信号进行同步

空满信号是通过读写指针的比较来产生,但是读指针属于读时钟域,写指针属于写时钟域,读写指针的比较有一个跨时钟域的问题,因此需要对读写指针进行信号的同步:

  • 将写指针同步到读时钟域,然后读指针再和同步后的写指针比较,产生读空信号
  • 将读指针同步到写时钟域,然后写指针再和同步后的读指针比较,产生写满信号

使用格雷码Gray表示的读写指针用两级寄存器同步:
同步过程的亚稳态问题是无法解决的,需要保证即使出现亚稳态也不影响设计的功能

  1. 如果使用二进制编码表示的读写指针进行同步,当出现亚稳态的时候,将会影响设计的功能。
    例如现在将写指针同步到读时钟域,去判断读空信号。写指针0111–>1000,同时有4bit数据发生跳变,在亚稳态的影响下,同步后的写指针的数值可能是0000-1111之间的任何一个数值。本来应该判空的,但是现在没有判空,将会读取错误的数据,使得设计出现问题。
  2. 如果使用格雷码表示的读写指针进行同步,即使出现亚稳态,也不会影响设计的功能。
    格雷码的特点是,相邻的编码之间每次只有1bit数据发生变化。那么这1bit数据如果发生亚稳态会影响设计的功能吗?答案是不会。例如现在还是将写指针同步到读时钟域,去判断读空信号。假设格雷码写指针从0000->0001,写指针同步出错,出错的结果只能是0000->0000,即写指针不变。这种结果最多就是让空信号标志在FIFO不是真正空的时候产生,而不会产生空读的情形。只会影响FIFO的效率,而不会影响到FIFO的功能。
    所以Gray码保证的是同步后的读写指针即使在出错的情形下依然能够保证FIFO功能的正确性

2.3 设计的时候,读写指针的同步至少需要消耗两个时钟周期,肯定会使得空满信号的判断有延迟,会不会导致设计出错??

假设现在将写指针同步到读时钟域再和读指针比较进行FIFO空状态判断,因为在同步写指针时需要时间,而在这个同步的时间内有可能还会写入新的数据,因此同步后的写指针一定是小于或者等于当前实际的写指针,所以此时判断FIFO为空不一定是真空,这样更加保守,一共不会出现空读的情况,虽然会影响FIFO的性能,但是并不会出错。

同理将读指针同步到写时钟域再和写指针比较进行FIFO满状态判断,同步后的读指针一定是小于或者等于当前的读指针,所以此时判断FIFO为满不一定是真满,这样更保守,肯定不会出错。

总结来说异步逻辑转到同步逻辑不可避免需要额外的时钟开销,这会导致满空趋于保守,会稍微有性能损失,但是不会出错

2.4 读写时钟不同频,在同步的过程中,可能会有指针遗漏,是否会影响功能?

异步FIFO两端的时钟不是同频的,或者读快写慢,或者读慢写快,慢的时钟域同步到快的时钟域不会出现漏掉指针的情况,但是将指针从快的时钟域同步到慢的时钟域时可能会有指针遗漏。

举例:假设读慢写快

进行满标志判断的时候,需要将读指针同步到写时钟域,因为写时钟快,不会发生读指针同步遗漏的情况,但是由于同步需要消耗至少两个时钟周期,导致读指针同步延迟,读时钟域rd_ptr=3,但是写时钟域的sync_rd_ptr=2,这样可能会导致满标志信号提前产生,满并非真满,但是不影响FIFO功能。

进行空标志判断的时候,需要将写指针同步到读时钟域,因为读时钟慢,会发生写指针同步遗漏的情况,不用关心漏掉哪几个,而是担心漏掉的指针是否会对设计产生影响,比如写指针从0写到10,期间读时钟域只同步捕捉到了3、5、8这三个写指针而漏掉了其他指针。当同步到8这个写指针时,真实的写指针可能已经写到10 ,相当于在读时钟域还没来得及觉察的情况下,写时钟域可能偷偷写了数据到FIFO去,这样在判断它是不是空的时候会出现不是真正空的情况,漏掉的指针不会对FIFO的逻辑操作产生影响(即不会影响,FIFO在满的时候写数据,空的时候读数据,造成的功能错误),只会影响FIFO的工作效率。

总而言之,实际的读/写指针大于同步之后的读/写指针的数值,这种情况不会影响FIFO的功能,只会影响FIFO的效率。(2.3和2.4)均是这种情况

2.5 二进制转Gray码

原理
在这里插入图片描述
代码
在这里插入图片描述

代码编写思路
大概就是格雷码最高位与二进制码一致,其余各位为二进制码对应位与其相邻的高位异或,如格雷码的第二位为二进制的第二位与二进制码的第三位异或。因此实现代码则为二进制码本身与逻辑右移一位后的二进制码异或即可得。
在这里插入图片描述

2.6 Gray码转二进制

原理
在这里插入图片描述
在这里插入图片描述

代码
在这里插入图片描述

代码编写思路
二进制码的最高位与格雷码最高位保持一致,其余通过自生移位与异或得到,如b[2]为格雷码逻辑右移两位(逻辑右移,最高位补0)再自身四位异或,0与任何数异或均为其本身。
在这里插入图片描述

2.7 读空的条件是写指针等于读指针,写满的条件也是写指针等于读指针,到底如何区分呢?

二进制码判断空满:指针的位宽多定义一位
假设要设计深度为 8 的异步FIFO,此时定义读写指针只需要 3 位(2^3=8)就够用了,
但是我们在设计时将指针的位宽设计成 4 位,最高位的作用就是区分是读空还是写满。
具体判断规则如下:

  • 当最高位相同,其余位相同认为是读空
  • 当最高位不同,其余位相同认为是写满

格雷码判断空满:指针的位宽多定义一位
在设计中判断是读指针是否等于写指针的时候,用的是读写指针的格雷码形式
具体判断规则如下:

  • 当最高位和次高位相同,其余位相同认为是读空

  • 当最高位和次高位不同,其余位相同认为是写满

    因为格雷码是一种镜像码, 例如读指针指向 8,写指针指向 7 ,我们可以知道此时此刻并不是读空状态也不是写满状态;
    (7对应的格雷码0100;8对应得格雷码1100) 但是如果按照二进制码得判断规则,最高位不同,其余位相同,就会误判出现写满信号;因此格雷码判断空满的条件和二进制判断空满的规则不相同。

3 RTL

一个典型的FIFO模块结构如下所示:
在这里插入图片描述
下面是参考上图进行的实现(略有不同):

module async_fifo#(parameter   DEPTH   =   16,parameter   WIDTH   =   8
)(input                   wr_clk  ,input                   wr_rstn ,input                   wr_en   ,input       [WIDTH-1:0] wr_data ,input                   rd_clk  ,input                   rd_rstn ,input                   rd_en   ,output  reg [WIDTH-1:0] rd_data ,output                  rempty   ,output                  wfull    
);//------------------------------------------------------------------------------------
//                              internal vars         
//------------------------------------------------------------------------------------reg     [WIDTH-1:0] fifo_ram    [DEPTH-1:0];reg     [$clog2(DEPTH):0] wr_ptr;
reg     [$clog2(DEPTH):0] rd_ptr;wire    [$clog2(DEPTH):0] wr_ptr_g;
wire    [$clog2(DEPTH):0] rd_ptr_g;
reg     [$clog2(DEPTH):0] wr_ptr_g_d1;
reg     [$clog2(DEPTH):0] rd_ptr_g_d1;
reg     [$clog2(DEPTH):0] wr_ptr_g_d2;
reg     [$clog2(DEPTH):0] rd_ptr_g_d2;wire    [$clog2(DEPTH)-1:0] wr_addr;
wire    [$clog2(DEPTH)-1:0] rd_addr;//------------------------------------------------------------------------------------
//                             wr_ptr && rd_ptr       
//------------------------------------------------------------------------------------always@(posedge wr_clk or negedge wr_rstn)beginif(!wr_rstn)wr_ptr <= 0;else if(wr_en && !wfull)wr_ptr <= wr_ptr + 1'b1;
endalways@(posedge rd_clk or negedge rd_rstn)beginif(!rd_rstn)rd_ptr <= 0;else if(rd_en && !rempty)rd_ptr <= rd_ptr + 1'b1;
end//------------------------------------------------------------------------------------
//                             wfull && rempty       
//------------------------------------------------------------------------------------
assign wr_ptr_g = (wr_ptr >> 1) ^ wr_ptr;
assign rd_ptr_g = (rd_ptr >> 1) ^ rd_ptr;always@(posedge rd_clk or negedge rd_rstn )begin//write_ptr_g sync to read domainif(!rd_rstn){wr_ptr_g_d2,wr_ptr_g_d1} <= 0;else {wr_ptr_g_d2,wr_ptr_g_d1} <= {wr_ptr_g_d1,wr_ptr_g};
endalways@(posedge wr_clk or negedge wr_rstn)begin//read_ptr_g sync to write domainif(!wr_rstn){rd_ptr_g_d2,rd_ptr_g_d1} <= 0;else {rd_ptr_g_d2,rd_ptr_g_d1} <= {rd_ptr_g_d1,rd_ptr_g};
endassign rempty = (rd_ptr_g == wr_ptr_g_d2);
assign wfull = wr_ptr_g == {~rd_ptr_g_d2[$clog2(DEPTH):$clog2(DEPTH)-1],rd_ptr_g_d2[$clog2(DEPTH)-2:0]};//------------------------------------------------------------------------------------
//                             write && read       
//------------------------------------------------------------------------------------assign wr_addr = wr_ptr[$clog2(DEPTH)-1:0];
assign rd_addr = rd_ptr[$clog2(DEPTH)-1:0];always@(posedge wr_clk)if(wr_en && !wfull)fifo_ram[wr_addr] <= wr_data;always@(posedge rd_clk)if(rd_en && !rempty)rd_data <= fifo_ram[rd_addr];endmodule

4 Testbench

pattern只写不读、pattern只读不写、pattern写比读快

`timescale 1ns / 1psmodule tb_async_fifo();//---------------------------------------------------parameter WIDTH = 3;
parameter DEPTH = 32;reg                   wr_clk  ;
reg                   wr_rstn ;
reg                   wr_en   ;
reg       [WIDTH-1:0] wr_data ;
reg                   rd_clk  ;
reg                   rd_rstn ;
reg                   rd_en   ;
wire   [WIDTH-1:0]    rd_data ;
wire                  empty   ;
wire                  full    ;//---------------------------------------------------initial beginwr_clk = 0;forever #10 wr_clk = ~wr_clk;//50MHz
end
initial beginrd_clk = 0;forever #12.5 rd_clk = ~rd_clk;//40MHz
endinitial beginrd_rstn = 0;wr_rstn = 0;#103 ;rd_rstn = 1;wr_rstn = 1;
end//pattern1
initial beginwr_en   = 0;wr_data = 0;#203;wr_en = 1;repeat(32) @(posedge wr_clk)begin#1;wr_data = wr_data + 1;end#1;wr_en = 0;
end//pattern2
initial beginrd_en = 0;#3000;rd_en = 1;repeat(32) @(posedge rd_clk)beginend#1;rd_en = 0;
end//pattern3
initial beginrd_en = 0;wr_en = 0;#6000;wr_en = 1;rd_en = 1;repeat(300) @(posedge wr_clk)begin#1;wr_data = wr_data + 1;end#1;wr_en = 0;repeat(32) @(posedge rd_clk)beginend#1;rd_en = 0;
end
//---------------------------------------------------async_fifo#(.DEPTH(DEPTH),.WIDTH(WIDTH)
) u_async_fifo(.wr_clk  (wr_clk  ),.wr_rstn (wr_rstn ),.wr_en   (wr_en   ),.wr_data (wr_data ),.rd_clk  (rd_clk  ),.rd_rstn (rd_rstn ),.rd_en   (rd_en   ),.rd_data (rd_data ),.empty   (empty   ),.full    (full    )
);endmodule

pattern读比写快

`timescale 1ns / 1psmodule tb_async_fifo_w_slow();//---------------------------------------------------parameter WIDTH = 3;
parameter DEPTH = 32;reg                   wr_clk  ;
reg                   wr_rstn ;
reg                   wr_en   ;
reg       [WIDTH-1:0] wr_data ;
reg                   rd_clk  ;
reg                   rd_rstn ;
reg                   rd_en   ;
wire   [WIDTH-1:0]    rd_data ;
wire                  empty   ;
wire                  full    ;//---------------------------------------------------initial beginwr_clk = 0;forever #10 wr_clk = ~wr_clk;//50MHz
endinitial beginrd_clk = 0;forever #8 rd_clk = ~rd_clk;//62.5MHz
endinitial beginrd_rstn = 0;wr_rstn = 0;#103 ;rd_rstn = 1;wr_rstn = 1;
end//pattern1
initial beginwr_en   = 0;wr_data = 0;#203;wr_en = 1;repeat(32) @(posedge wr_clk)begin#1;wr_data = wr_data + 1;end#1;wr_en = 0;
end//pattern2
initial beginrd_en = 0;#3000;rd_en = 1;repeat(32) @(posedge rd_clk)beginend#1;rd_en = 0;
end//pattern3
initial beginrd_en = 0;wr_en = 0;#6000;wr_en = 1;rd_en = 1;repeat(300) @(posedge wr_clk)begin#1;wr_data = wr_data + 1;end#1;wr_en = 0;repeat(32) @(posedge rd_clk)beginend#1;rd_en = 0;
end
//---------------------------------------------------async_fifo#(.DEPTH(DEPTH),.WIDTH(WIDTH)
) u_async_fifo(.wr_clk  (wr_clk  ),.wr_rstn (wr_rstn ),.wr_en   (wr_en   ),.wr_data (wr_data ),.rd_clk  (rd_clk  ),.rd_rstn (rd_rstn ),.rd_en   (rd_en   ),.rd_data (rd_data ),.empty   (empty   ),.full    (full    )
);endmodule

pattern读写一样快

`timescale 1ns / 1psmodule tb_async_fifo_w_equal();//---------------------------------------------------parameter WIDTH = 3;
parameter DEPTH = 32;reg                   wr_clk  ;
reg                   wr_rstn ;
reg                   wr_en   ;
reg       [WIDTH-1:0] wr_data ;
reg                   rd_clk  ;
reg                   rd_rstn ;
reg                   rd_en   ;
wire   [WIDTH-1:0]    rd_data ;
wire                  empty   ;
wire                  full    ;//---------------------------------------------------initial beginwr_clk = 0;forever #10 wr_clk = ~wr_clk;//50MHz
endinitial beginrd_clk = 0;#8;forever #10 rd_clk = ~rd_clk;//50MHz
endinitial beginrd_rstn = 0;wr_rstn = 0;#103 ;rd_rstn = 1;wr_rstn = 1;
end//pattern1
initial beginwr_en   = 0;wr_data = 0;#203;wr_en = 1;repeat(32) @(posedge wr_clk)begin#1;wr_data = wr_data + 1;end#1;wr_en = 0;
end//pattern2
initial beginrd_en = 0;#3000;rd_en = 1;repeat(32) @(posedge rd_clk)beginend#1;rd_en = 0;
end//pattern3
initial beginrd_en = 0;wr_en = 0;#6000;wr_en = 1;rd_en = 1;repeat(300) @(posedge wr_clk)begin#1;wr_data = wr_data + 1;end#1;wr_en = 0;repeat(32) @(posedge rd_clk)beginend#1;rd_en = 0;
end
//---------------------------------------------------async_fifo#(.DEPTH(DEPTH),.WIDTH(WIDTH)
) u_async_fifo(.wr_clk  (wr_clk  ),.wr_rstn (wr_rstn ),.wr_en   (wr_en   ),.wr_data (wr_data ),.rd_clk  (rd_clk  ),.rd_rstn (rd_rstn ),.rd_en   (rd_en   ),.rd_data (rd_data ),.empty   (empty   ),.full    (full    )
);endmodule

参考博客:
https://zhuanlan.zhihu.com/p/551351794
https://blog.csdn.net/ZZ2588/article/details/122347438
https://blog.csdn.net/spx1164376416/article/details/121086907
https://zhuanlan.zhihu.com/p/344170711
https://wuzhikai.blog.csdn.net/article/details/121152844
https://blog.csdn.net/JustinLee2015/article/details/106527301/
https://blog.csdn.net/wuzhikaidetb/article/details/123570799
https://blog.csdn.net/weixin_44348260/article/details/119612998

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/132931.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

本地录像视频文件如何推送到视频监控平台EasyCVR进行AI视频智能分析?

安防监控平台EasyCVR支持多协议、多类型设备接入&#xff0c;可以实现多现场的前端摄像头等设备统一集中接入与视频汇聚管理&#xff0c;并能进行视频高清监控、录像、云存储与磁盘阵列存储、检索与回放、级联共享等视频功能。视频汇聚平台既具备传统安防监控、视频监控的视频能…

【算法】前缀和与差分

大家好&#xff01;今天我们来学习前缀和与差分算法。 目录 1. 一维前缀和 1.1 定义 1.2 计算方法 1.3 作用 1.4 适用场景 1.5 模板题 1.6 总结 2. 二维前缀和 2.1 定义 2.2 计算方法 2.3 模板题 2.4 总结 3. 一维差分 3.1 定义 3.2 差分数组 3.3 差分标记 3…

什么是JavaScript中的严格模式(strict mode)?应用场景是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 严格模式&#xff08;Strict Mode&#xff09;&#xff1a;⭐ 使用场景⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&…

SpringMVC多文件上传

文章目录 一、文件上传1.1 导入pom依赖1.2 配置文件上传解析器1.3 设置文件上传表单1.4 实现文件上传 二、文件下载三、多文件上传四、JRebel的使用 一、文件上传 1.1 导入pom依赖 <commons-fileupload.version>1.3.3</commons-fileupload.version><dependency…

高德地图实现-微信小程序地图导航

效果图&#xff1a; 一、准备阶段 1、在高德开放平台注册成为开发者2、申请开发者密钥&#xff08;key&#xff09;。3、下载并解压高德地图微信小程序SDK 高德开放平台&#xff1a; 注册账号(https://lbs.amap.com/)) 申请小程序应用的 key 应用管理(https://console.ama…

苹果“FindMy”APP

“FindMy”是一项 Apple 服务&#xff0c;可以定位设备。在 iOS 13 之前&#xff0c;Apple将该服务拆分为单独的应用程序&#xff1a;“查找我的 iPhone”&#xff08;或 iPad 或 Mac&#xff09;和“查找我的朋友”。该服务适用于iPhone、iPad、Mac、Apple Watch、AirPods、Ai…

MyBatisPlus(二)基础Mapperr接口:增删改查

MyBatisPlus&#xff1a;基础Mapper接口&#xff1a;增删改查 插入一条数据 代码 Testpublic void insert() {User user new User();user.setId(6L);user.setName("张三");user.setAge(25);user.setEmail("zhangsanexample.com");userMapper.insert(use…

什么是接口自动化?为什么要做?和怎么做接口自动化?

服务端接口测试介绍 什么是服务端&#xff1f; 一般所说的服务端是指为用户在 APP 或 PC 使用的互联网功能提供数据服务的背后的一切。以天猫精灵智能音箱系列的产品链路为例&#xff0c;服务端便是网关&#xff08;包括网关在内&#xff09;之后的链路。 什么是接口&#xf…

张雪峰说网络空间安全专业

网络空间安全专业是一个涵盖了计算机科学、信息安全、法律等多个领域的学科&#xff0c;旨在研究保护网络空间的信息系统和数据不被非法侵入、破坏、篡改、泄露的技术和管理手段。 网络安全专业的重要性 随着网络技术的发展&#xff0c;网络安全问题也日益凸显&#xff0c;黑客…

避免使用违规词,企业新媒体营销应注重品牌形象维护

随着越来越多的主体入局新媒体平台&#xff0c;为了维护平台健康的内容生态和创造良好的社区氛围&#xff0c;社交平台在内容上的监管越发严格。 不可避免的&#xff0c;很多做新媒体营销的企业开始陷入与平台审核的“拉扯”之中。 为了让品牌账号在各平台上顺利运营&#xff0…

Linux C++ 海康摄像头 Alarm Demo

项目结构 CMakeLists.txt cmake_minimum_required(VERSION 3.7)SET(CMAKE_BUILD_TYPE "Debug") SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb") SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")project(CapPicture…

vue2以ElementUI为例构建notify便捷精美提示

我们先引入一个 第三方UI库 这里 我们以elementUI为例 先引入依赖 npm install element-ui --save然后 在 main.js 入口文件中 引入一下 import ElementUI from element-ui import element-ui/lib/theme-chalk/index.cssVue.use(ElementUI)然后 在组件中使用 this.$notify({…

代码随想录算法训练营第49天|121. 买卖股票的最佳时机,买卖股票的最佳时机II

链接: 121. 买卖股票的最佳时机 链接: 122.买卖股票的最佳时机II 121. 买卖股票的最佳时机 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出…

RTE 领域近期词云统计发布;谷歌开始新一轮「瘦身」计划;使用ChatGPT之后智力提高 50%丨RTE开发者日报 Vol.50

开发者朋友们大家好&#xff1a; 这里是**「RTE 开发者日报」**&#xff0c;每天和大家一起看新闻、聊八卦。不知不觉&#xff0c;我们的日报已经发布了 50 期&#xff0c;作为 RTE 领域最垂直的日报栏目&#xff0c;我们的社区编辑团队会整理分享 RTE &#xff08;Real Time …

云计算——ACA学习 云计算分类

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 公众号&#xff1a;网络豆 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a; 网络豆的主页​​​​​ 目录 写在前面 前期回顾 本期介绍 一.云计算分类 1.公有云…

模拟实现C语言--strcat函数

模拟实现C语言–strcat函数 文章目录 模拟实现C语言--strcat函数一、strcat函数是什么&#xff1f;二、使用示例二、模拟实现 一、strcat函数是什么&#xff1f; 作用是把源数据追加到目标空间 char * strcat ( char * destination, const char * source );源字符串必须以 ‘…

誉天在线项目-UML状态图+泳道图

什么是UML UML&#xff08;Unified Modeling Language&#xff09;是一种用于软件系统建模的标准化语言。它提供了一组图形符号和规范&#xff0c;用于描述和设计软件系统的结构、行为和交互。 UML图形符号包括类图、用例图、时序图、活动图、组件图、部署图等&#xff0c;每…

基础术语和模式的学习记录

1 范围 本文件界定了政府和社会资本合作(PPP) 的基础术语&#xff0c;给出了政府和社会资本合作(PPP) 的 模 式 分类和代码。 本文件适用于政府和社会资本合作(PPP) 的所有活动。 2 规范性引用文件 本文件没有规范性引用文件。 3 基础术语 3.1 PPP 主体 3.1.1 政府和社…

Apache HTTPD 漏洞复现

文章目录 Apache HTTPD 漏洞复现1. Apache HTTPD 多后缀解析漏洞1.1 漏洞描述1.2 漏洞复现1.3 漏洞利用1.4 获取GetShell1.5 漏洞防御 2. Apache HTTPD 换行解析漏洞-CVE-2017-157152.1 漏洞描述2.2 漏洞复现2.3 漏洞利用2.4 修复建议 3. Apache HTTP Server_2.4.49 路径遍历和…

十七、Webpack搭建本地服务器

一、为什么要搭建本地服务器&#xff1f; 目前我们开发的代码&#xff0c;为了运行需要有两个操作&#xff1a; 操作一&#xff1a;npm run build&#xff0c;编译相关的代码&#xff1b;操作二&#xff1a;通过live server或者直接通过浏览器&#xff0c;打开index.html代码…