FPGA -手写异步FIFO

一,FIFO原理

        FIFO(First In First Out)是一种先进先出的数据缓存器,没有外部读写地址线,使用起来非常简单,只能顺序写入数据顺序的读出数据,其数据地址内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。也正是由于这个特性,使得FIFO可以用作跨时钟域数据传输和数据位宽变换

二,双端口RAM

        FIFO中用来存储数据的器件为双口RAM,首先搭建一个Dual Ram(双口RAM)。我们以一个深度为16,数据位宽为8的Dual Ram为例,框图和时序如下。

        

Dual Ram读端和写端采用两个时钟,可以实现读写时钟为异步时钟,也可以实现读写同时进行的功能。代码实现如下:

// -----------------------------------------------------------------------------
// Author : RLG
// File   : Dual_Ram.v
// -----------------------------------------------------------------------------
`timescale 1ns / 1ps
module Dual_Ram#(
	parameter 			ADDR_WIDTH = 4,
	parameter 			DATA_WIDTH = 8
	)(
	input 								wrclk	,
	input 								rdclk	,
				
	input 								wr_en	,
	input 								rd_en	,	

	input 		[ADDR_WIDTH-1:0]		wr_addr ,
	input 		[ADDR_WIDTH-1:0]		rd_addr ,

	input  		[DATA_WIDTH-1:0]		wr_data	,
	output 	reg [DATA_WIDTH-1:0]		rd_data
    );

	/*---------------输入数据打一拍-------------*/
    reg [ADDR_WIDTH-1:0]	wr_addr_d1;
    reg [ADDR_WIDTH-1:0]	rd_addr_d1;
    reg [DATA_WIDTH-1:0]	wr_data_d1;
    reg 					wr_en_d1  ;
    reg 					rd_en_d1  ;
 	/*----------------数据寄存----------------*/  
 	reg [DATA_WIDTH-1:0] rd_data_out; 
	reg [DATA_WIDTH-1:0] Data_reg [2**ADDR_WIDTH-1:0];


	/*---------------输入数据打拍-------------*/
	always @(posedge wrclk ) begin 
		wr_addr_d1 <= wr_addr;
		rd_addr_d1 <= rd_addr;
		wr_data_d1 <= wr_data;
		wr_en_d1   <= wr_en  ;
		rd_en_d1   <= rd_en  ;
	end

	/*-------------------写数据-----------------*/
	always @(posedge wrclk ) begin 
		if(wr_en_d1)
			Data_reg[wr_addr_d1] <= wr_data_d1;
	end

	/*-------------------读数据-----------------*/
	always @(posedge rdclk ) begin 
		if(rd_en_d1)
			rd_data_out <=  Data_reg[rd_addr_d1];
	end

	/*-----------------输出打一拍----------------*/
	always @(posedge rdclk ) begin 
		rd_data <= rd_data_out;
	end

endmodule

二、FIFO地址设计

        我们知道FIFO中是没有地址线的,地址靠自身计数器自加1来控制,那么我们很容易想到把外部输入信号wr_addr和rd_addr换成内部信号并用计数器来控制其自加,计数器加满之后直接清零,从0重新开始写/读,循环往复。由于写端和读端的时钟速率不同,就会有快慢的问题,        

        那么就出现了一个问题,以地址2为例,写入的数据还没有被读出,又被新的数据覆盖了,造成数据丢失;或者写入的数据已经被读出,新的数据还没有写进来,地址2的老数据又被读了一遍,造成数据重复。

        为了解决上述问题,引入 full empty 信号来表示内部RAM中的数据写满或者读空,新的框图如下所示。

        

        如何产生full和empty信号呢,我们可以用 wr_addrrd_addr 来做判断,当 wr_clk 大于 rd_clk 时,会产生写满的情况,如下图中黄色部分代表已经写入数据,还未被读取,白色代表数据已被读取,图1中当 waddr>raddr时,waddr-raddr → 1111 - 0001 = 1110 可以表示两者的差值。

        图2中当 waddr<raddr 时,计算两者的差值为16 – raddr + waddr → 10000 - 1100 +1010 = 1110,此时的 waddr – raddr → 1010-1100 →1010+0011+0001=1110,两者结果相同,所以无论 waddr 大于 raddr 还是小于 raddr,都可以用 waddr-raddr 来表示写比读多几个数据。此时再引入一个full_limit用来设置一个写满的阈值。当waddr – raddr >= full_limit 时,full信号拉高,停止写入。

        同理,读比写快的情况下引入一个empty_limit来作为读空的阈值,当 waddr – raddr <= empty_limit 时。empty信号拉高停止读出。在实际工程中可以根据实际需要和 fifo 的设计区别灵活设置 full_limit 和empty_limit 的数值

三、空满信号判断

        使用读写地址进行判断空满信号。读地址rd_addr是在读时钟域wr_clk内,空信号empty也是在读时钟域内产生的;而写地址wr_addr是在写时钟域内,且满信号full也是在写时钟域内产生的。 那么,要使用读地址rd_addr与写地址wr_addr对比产生空信号empty,可以直接对比吗?        

        答案是不可以。

        因为这两个信号处于不同的时钟域内,要做跨时钟域CDC处理,而多bit信号跨时钟域处理,常用的方法就是使用异步FIFO进行同步可是我们不是在设计异步FIFO吗?

        于是,在这里设计异步FIFO,多bit跨时钟域处理的问题可以转化单bit跨时钟域的处理,把读写地址转换为格雷码后再进行跨时钟域处理,因为无论多少比特的格雷码,每次加1,只改变1位。把读地址rd_addr转换为格雷码,然后同步到写时钟域wr_clk;同样的,把写地址指wr_addr转换为格雷码,然后同步到读时钟域rd_clk

        二进制转格雷码:二进制的最高位作为格雷码的最高位,次高位的格雷码为二进制的高位和次高位相异或得到,其他位与次高位相同。

        代码:

  	assign wr_gray = (wr_addr >> 1) ^ wr_addr;
  	assign rd_gray = (rd_addr >> 1) ^ rd_addr;

        格雷码转二进制:使用格雷码的最高位作为二进制的最高位,二进制次高位产生过程是使用二进制的高位和次高位格雷码相异或得到,其他位的值与次高位产生过程相同。

        代码:

assign wr_bin[ADDR_WIDTH-1] = wr_gray_d2[ADDR_WIDTH-1];
	
  	genvar i;
  	generate
  	  for ( i = 0; i < ADDR_WIDTH-1; i=i+1) begin
  	    assign wr_bin[i] = wr_bin[i+1] ^ wr_gray_d2[i];
  	  end
  	endgenerate
	
  	assign rd_bin[ADDR_WIDTH-1] = rd_gray_d2[ADDR_WIDTH-1];
	
  	genvar j;
  	generate
  	  for ( j = 0; j < ADDR_WIDTH-1; j=j+1) begin
  	    assign rd_bin[j] = rd_bin[j+1] ^ rd_gray_d2[j];
  	  end
  	endgenerate

四、跨时钟域同步

        如何避免漏采和重采,首先考虑一个问题,地址同步要在哪个时钟域进行呢,我们所期望的结果是慢时钟地址同步到快时钟域,以免发生快时钟域信号漏采导致的读空或者写满。至于重采的情况,即慢时钟域信号被多采了一次,只会在判断空满状态时更安全,不会导致读空和写满这种不安全现象的出现。不过这样会产生虚假的full和empty信号,即full信号已经拉高,但ram中仍存有可用的地址,或者empty信号已经拉高,但ram中仍存有可被读出的数据。虽然效率和资源上有一点浪费,但不会发生丢失数据或读错数据的不安全行为

        那怎么实现慢时钟域的信号同步到快时钟域呢?因为若同时读写时出现 empty 则一定是读时钟快于写时钟,所以在判断 empty 状态时,读时钟域为快时钟,把较慢的写时钟同步到读时钟域来判断 empty。同理,若同时读写时出现 full 则一定是写时钟快于读时钟,所以在判断 full 状态时,写时钟域为快时钟,把较慢的读时钟同步到写时钟域来判断 full。以判断empty状态为例,过程如下图所示:

        其中B2G模块(二进制转格雷码)G2B模块(格雷码转二进制)empty判断模块均为组合逻辑,所以加一级D触发器以满足时序。圈中的两级D触发器用作消除跨时钟域同步的亚稳态。empty信号在RCLK快于WCLK时产生,中间虽然加入了四级D触发器,导致写地址同步到读时钟域时是之前的老地址,这和之前采重的问题一样,只会让empty的判断更安全,但会造成少许的资源浪费,属于保守但安全的做法。

        至此,一个简易的异步fifo就被设计出来了,总体框图如下:

代码:

// -----------------------------------------------------------------------------
// Author : RLG
// File   : async_fifo.v
// -----------------------------------------------------------------------------
`timescale 1ns / 1ps
module async_fifo#(
  parameter       ADDR_WIDTH = 4    ,
  parameter       DATA_WIDTH = 8    ,
  parameter       EMPTY_LIMIT= 1'b1  ,
  parameter       FULL_LIMIT = 4'd15

  )(
  input                           wrclk   ,
  input                           rdclk   ,

  input                           wr_rst_n,
  input                           rd_rst_n,   
          
  input                           wr_en   ,
  input                           rd_en   , 

  input       [DATA_WIDTH-1:0]    wr_data ,
  output  reg [DATA_WIDTH-1:0]    rd_data ,
  output  reg             		    empty   ,
  output  reg             		    full
    );

  	/*---------------输入数据打一拍-----------*/
    reg   [DATA_WIDTH-1:0]  wr_data_d1  ;
    reg                     wr_en_d1    ;
    reg                     rd_en_d1    ;
  
  	/*--  --------------数据寄存----------------*/  
  
  	reg   [DATA_WIDTH-1:0]  Data_reg [2**ADDR_WIDTH-1:0];
  
  	/*--  --------------读写地址----------------*/ 
  	reg   [ADDR_WIDTH-1:0]  wr_addr    ;
  	reg   [ADDR_WIDTH-1:0]  rd_addr    ;
    
  	/*--  --------------二进制转格雷码------------*/ 
  	wire  [ADDR_WIDTH-1:0]  wr_gray     ;
  	wire  [ADDR_WIDTH-1:0]  rd_gray     ;
  	reg   [ADDR_WIDTH-1:0]  wr_gray_d0  ;
  	reg   [ADDR_WIDTH-1:0]  rd_gray_d0  ;
  	reg   [ADDR_WIDTH-1:0]  wr_gray_d1  ;
  	reg   [ADDR_WIDTH-1:0]  rd_gray_d1  ;
	reg   [ADDR_WIDTH-1:0]  wr_gray_d2  ;
  	reg   [ADDR_WIDTH-1:0]  rd_gray_d2  ;
    
	/*--  --------------格雷码转二进制------------*/ 
	wire  [ADDR_WIDTH-1:0]  wr_bin    ;
	wire  [ADDR_WIDTH-1:0]  rd_bin    ;
	reg   [ADDR_WIDTH-1:0]  rd_bin_d0   ;
	reg   [ADDR_WIDTH-1:0]  wr_bin_d0 ;

  	/*----------------empty 判读---------------*/ 
  	wire          empty_logic ;
	
  	/*----------------full 判读---------------*/ 
  	wire          full_logic  ;
	
	
  	/*---------------------------------------*\
  	                 输入数据打拍
  	\*---------------------------------------*/
  	always @(posedge wrclk ) begin 
  	  wr_data_d1 <= wr_data;
  	  wr_en_d1   <= wr_en  ;
  	  rd_en_d1   <= rd_en  ;
  	end
	
  	/*---------------------------------------*\
  	                     写地址
  	\*---------------------------------------*/
  	always @(posedge wrclk ) begin 
  	  if(~wr_rst_n)
  	    wr_addr<= 0;
  	  else if(wr_en_d1 && ~full) begin
  	    if(wr_addr == 'd15)
  	      wr_addr <= 0;
  	    else
  	      wr_addr <= wr_addr + 1'b1;
  	  end
  	end
	
  	/*---------------------------------------*\
  	                     读地址
  	\*---------------------------------------*/
  	  always @(posedge rdclk ) begin 
  	  if(~rd_rst_n)
  	    rd_addr<= 0;
  	  else if(rd_en_d1 && ~empty) begin
  	    if(rd_addr == 'd15)
  	      rd_addr <= 0;
  	    else
  	      rd_addr <= rd_addr + 1'b1;
  	  end
  	end
  	
  	/*---------------------------------------*\
  	                  写数据
  	\*---------------------------------------*/
  	always @(posedge wrclk ) begin 
  	  if(wr_en_d1 && ~full)
  	    Data_reg[wr_addr] <= wr_data_d1;
  	end
	
  	/*---------------------------------------*\
  	                     读数据
  	\*---------------------------------------*/
  	always @(posedge rdclk ) begin 
  	  if(rd_en_d1 && ~empty)
  	    rd_data <=  Data_reg[rd_addr];
  	end
	
  	/*---------------------------------------*\
  	              二进制转格雷码
  	\*---------------------------------------*/
  	assign wr_gray = (wr_addr >> 1) ^ wr_addr;
  	assign rd_gray = (rd_addr >> 1) ^ rd_addr;
	
  	always @(posedge wrclk ) begin 
  	  wr_gray_d0 <= wr_gray;
  	end
	
  	 always @(posedge rdclk ) begin 
  	  rd_gray_d0 <= rd_gray;
  	end
	
  	/*---------------------------------------*\
  	                格雷码转二进制
  	\*---------------------------------------*/ 
  	always @(posedge wrclk ) begin 
  	  if(!wr_rst_n)begin
  	    rd_gray_d1 <= 0;
  	    rd_gray_d2 <= 0;
  	  end
  	  else begin
  	    rd_gray_d1 <= rd_gray_d0;
  	    rd_gray_d2 <= rd_gray_d1;
  	  end
  	end
	
  	always @(posedge rdclk ) begin 
  	  if (!rd_rst_n) begin
  	    wr_gray_d1 <= 0;
  	    wr_gray_d2 <= 0;
  	  end
  	  else begin
  	    wr_gray_d1 <= wr_gray_d0;
  	    wr_gray_d2 <= wr_gray_d1;
  	  end
  	end
	
	
  	assign wr_bin[ADDR_WIDTH-1] = wr_gray_d2[ADDR_WIDTH-1];
	
  	genvar i;
  	generate
  	  for ( i = 0; i < ADDR_WIDTH-1; i=i+1) begin
  	    assign wr_bin[i] = wr_bin[i+1] ^ wr_gray_d2[i];
  	  end
  	endgenerate
	
  	assign rd_bin[ADDR_WIDTH-1] = rd_gray_d2[ADDR_WIDTH-1];
	
  	genvar j;
  	generate
  	  for ( j = 0; j < ADDR_WIDTH-1; j=j+1) begin
  	    assign rd_bin[j] = rd_bin[j+1] ^ rd_gray_d2[j];
  	  end
  	endgenerate
	
  	always @(posedge wrclk) begin 
  	  wr_bin_d0 <= wr_bin;
  	end
	
  	always @(posedge rdclk) begin 
  	  rd_bin_d0 <= rd_bin;
  	end
	
  	/*---------------------------------------*\
  	                  empty
  	\*---------------------------------------*/ 
  	assign empty_logic = ((wr_bin_d0 - rd_addr) <= EMPTY_LIMIT)? 1'b1 : 1'b0;
  	always @(posedge rdclk) begin 
  	  empty <= empty_logic;
  	end
	
  	/*---------------------------------------*\
  	                   full
  	\*---------------------------------------*/
  	assign full_logic = ((wr_addr - rd_bin_d0) >=  FULL_LIMIT)? 1'b1 : 1'b0;
  	always @(posedge wrclk) begin 
  	  full <= full_logic;
  	end
	
	
	
endmodule 	

 仿真代码:

`timescale 1ns / 1ps
module tb_async_fifo;
	parameter  	ADDR_WIDTH   = 4;
	parameter  	DATA_WIDTH   = 8;
	parameter 	EMPTY_LIMIT  = 1'b1;
	parameter  	FULL_LIMIT   = 4'd15;

	reg                   wr_rst_n;
	reg                   rd_rst_n;

	reg                   wr_en;
	reg                   rd_en;
	reg  [DATA_WIDTH-1:0] wr_data;
	wire [DATA_WIDTH-1:0] rd_data;
	wire                  empty;
	wire                  full;

	reg 					wr_clk;
	reg 					rd_clk;

	initial begin 
		wr_clk = 0;
		rd_clk = 0;
		wr_rst_n = 0;
		rd_rst_n = 0;
		wr_en = 0;
		rd_en = 0;
		#20
		wr_rst_n = 1;
		rd_rst_n = 1;
		#20
		wr_en = 1;
		#30
		rd_en = 1;
	end


	always #10 wr_clk = ~wr_clk;
	always #5  rd_clk = ~rd_clk;

	always @(posedge wr_clk ) begin 
		if(!wr_rst_n)
			wr_data <= 0;
		else if(wr_data == 15)
			wr_data <= 0;
		else if(wr_en)
			wr_data <= wr_data + 1;
	end




	async_fifo #(
			.ADDR_WIDTH(ADDR_WIDTH),
			.DATA_WIDTH(DATA_WIDTH),
			.EMPTY_LIMIT(EMPTY_LIMIT),
			.FULL_LIMIT(FULL_LIMIT)
		) inst_async_fifo (
			.wrclk    (wr_clk),
			.rdclk    (rd_clk),
			.wr_rst_n (wr_rst_n),
			.rd_rst_n (rd_rst_n),
			.wr_en    (wr_en),
			.rd_en    (rd_en),
			.wr_data  (wr_data),
			.rd_data  (rd_data),
			.empty    (empty),
			.full     (full)
		);


endmodule

 仿真波形:

五,总结

        在处理跨时钟域时,转换为格雷码处理。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

开源数据可视化大屏对接表单数据实践!

如果你需要一个表单系统&#xff0c;进行数据收集&#xff1b;可以使用tduck填鸭进行私有化部署&#xff0c;进行表单制作&#xff0c;完成数据收集。 在实际业务中&#xff0c;往往需要将收集的数据进行展示或分析&#xff1b;此时就可以使用表单数据推送到TReport中&#xf…

AMBA总线介绍

AMBA&#xff08;Advanced Microcontroller Bus Architecture&#xff09;是由ARM&#xff08;Advanced RISC Machines&#xff09;公司设计的一种高性能、高带宽的总线架构。AMBA总线广泛应用于各种嵌入式系统中&#xff0c;包括数字信号处理器、图形处理器、嵌入式处理器以及…

收银系统源码--什么是千呼智慧新零售系统?

千呼智慧新零售系统是一套针对零售行业线上线下一体化收银系统。给门店提供线下称重收银、o2o线上商城、erp进销存、精细化会员管理、丰富营销插件等一体化解决方案。多端数据打通&#xff0c;实现线上线下一体化&#xff0c;提升门店工作效率&#xff0c;实现数字化升级&#…

vue3 依赖-组件tablepage-vue3版本1.0.3更新内容

github求⭐ 可通过github 地址和npm 地址查看全部内容 vue3 依赖-组件tablepage-vue3说明文档&#xff0c;列表页快速开发&#xff0c;使用思路及范例-汇总 vue3 依赖-组件tablepage-vue3说明文档&#xff0c;列表页快速开发&#xff0c;使用思路及范例&#xff08;Ⅰ&#…

【第38天】SQL进阶-SQL设计优化-范式设计(SQL 小虚竹)

回城传送–》《100天精通MYSQL从入门到就业》 文章目录 零、前言一、练习题目二、SQL思路初始化数据什么是范式设计第一范式&#xff08;1NF&#xff09;第二范式&#xff08;2NF&#xff09;第三范式&#xff08;3NF&#xff09; 三、总结四、参考 零、前言 今天是学习 SQL …

期权和期货有什么区别?

今天期权懂带你了解期权和期货有什么区别&#xff1f;期权和期货是两种常见的衍生金融工具&#xff0c;它们在结构和盈利方式上存在一些关键的区别&#xff1a; 期权 期权是一种给予持有者在未来某个时间以特定价格买入或卖出基础资产的权利&#xff0c;但不是义务。期权的主要…

ORACLE 19C RAC DIAG进程消耗大量内存的分析

近期一个ORACLE 19C的RAC环境&#xff0c;多次出现数据库实例的后台进程DIAG消耗很多内存&#xff08;达到20G&#xff09;&#xff0c;节点1、节点2都出现过次问题。 问题分析&#xff1a;通过对DIAG进程TRACE分析&#xff0c;结合在ORACLE官方后台进行问题、BUG查询匹配&…

uniapp怎么使用jsx

安装vitejs/plugin-vue-jsx npm install vitejs/plugin-vue-jsx -Dvite.config.js配置 import { defineConfig } from "vite"; import uni from "dcloudio/vite-plugin-uni"; import vueJsx from vitejs/plugin-vue-jsxexport default defineConfig({plu…

初始Java篇(JavaSE基础语法)(7)抽象类和接口(下)

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;JavaSE 接上文&#xff1a;初始Java篇&#xff08;JavaSE基础语法&#xff09;&#xff08;7&#xff09;抽象类和接口&#xff08;上&#xf…

Netty HTTP2 示例-响应式编程-013

🤗 ApiHug {Postman|Swagger|Api...} = 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱,有温度,有质量,有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace The Next Generation API Development Platform …

上海亚商投顾:沪指缩量调整 合成生物概念股持续爆发

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 沪指昨日缩量震荡调整&#xff0c;深成指、创业板指均跌超1%。细胞免疫治疗概念股大涨&#xff0c;冠昊生物、…

运营一个在线课堂有哪些基础费用?

我是酷瓜云课堂的作者&#xff0c;对这个问题还是很有心得的。我们的系统是基于腾讯云服务的&#xff0c;下面简单罗列一些基础费用&#xff0c;价格和腾讯云官方有些许出入&#xff0c;仅供参考。 &#xff08;1&#xff09;域名 域名注册通常 60 - 80元 / 年&#xff0c;续…

【JavaEE网络】HTTP响应详解:状态码、报头与正文的全面解析

目录 HTTP响应&#xff08;Response&#xff09;认识 "状态码" (status code)认识响应 “报头”&#xff08;header&#xff09;认识响应 “正文”&#xff08;body&#xff09; HTTP响应&#xff08;Response&#xff09; 响应&#xff1a; 首行响应头空行正文 认…

AI大模型探索之路-训练篇18:大语言模型预训练-微调技术之Prompt Tuning

系列篇章&#x1f4a5; AI大模型探索之路-训练篇1&#xff1a;大语言模型微调基础认知 AI大模型探索之路-训练篇2&#xff1a;大语言模型预训练基础认知 AI大模型探索之路-训练篇3&#xff1a;大语言模型全景解读 AI大模型探索之路-训练篇4&#xff1a;大语言模型训练数据集概…

信息系统项目管理师0095:项目管理知识领域(6项目管理概论—6.4价值驱动的项目管理知识体系—6.4.4项目管理知识领域)

点击查看专栏目录 文章目录 6.4.4项目管理知识领域6.4.4项目管理知识领域 除了过程组,过程还可以按知识领域进行分类。知识领域指按所需知识内容来定义的项目管理领域,并用其所含过程、实践、输入、输出、工具和技术进行描述。 虽然知识领域相互联系,但从项目管理的角度来看…

使用unplugin-icons报错:Icon `eos-icons/ai` not found

代码&#xff1a; import IconNanobert from ~icons/eos-icons/ai 报错&#xff1a; Icon eos-icons/ai not found解决办法&#xff1a; npm i -D iconify-json/eos-icons &#xff08;把eos-icons替换成报错的那个collection-id即可&#xff0c;collection-id名称见图2&…

JVM堆内存分析

jmap工具查看堆内存 jmap:全称JVM Memory Map 是一个可以输出所有内存中对象的工具&#xff0c;可以将JVM中的heap&#xff08;堆&#xff09;&#xff0c;以二进制输出成文本&#xff0c;打印出Java进程对应的内存 找到pid jmap -heap 19792 Attaching to process ID 19792…

鸿蒙DevEco Studio 4.1 Release-模拟器启动方式错误

软件版本&#xff1a;DevEco Studio 4.1 Release 报错提示&#xff1a; 没有权限查看处理指导 Size on Disk 显示1.0MB 尝试方案&#xff08;统统无效&#xff09;&#xff1a; 1、“windows虚拟机监控程序平台”、"虚拟机平台"已开启 启用CPU虚拟化 2、C…

如何使用过滤器和监听器

Filter&#xff1a;过滤器 Listener:监听器 Filter&#xff1a;过滤器 1. 概念&#xff1a;* 生活中的过滤器&#xff1a;净水器,空气净化器&#xff0c;土匪、* web中的过滤器&#xff1a;当访问服务器的资源时&#xff0c;过滤器可以将请求拦截下来&#xff0c;完成一些特…

蓝桥杯【第15届省赛】Python B组 32.60 分

F 题列表越界访问了……省一但没什么好名次 测评链接&#xff1a;https://www.dotcpp.com/oj/train/1120/ C 语言网真是 ** 测评&#xff0c;时间限制和考试的不一样&#xff0c;E 题给我整时间超限&#xff1f; A&#xff1a;穿越时空之门 100&#x1f3c6; 【问题描述】 随…