ZYNQ—BRAM全双工PS_PL数据交互(开源)

article/2025/10/9 10:08:24

本资源实现了:采用ZYNQ7010vivado 2018.3xilinx sdk;正点原子XCOM串口助手,PS与PL均读写操作。
1、PS写0-9地址 0-9数据,触发start给PL
2、PL接收到触发后,做两次的打拍,再遍历一遍,然后PL将0-9地址的数据读取,分别+2,写在10-19地址上
3、PS再读取10-19地址上的数据并显示。
博主认为,这才是真正完成了PS与PL之间的数据交互,而非仅仅使用了BRAM资源,而且有给定len长度与地址长判断,可以实现仅修改
len为20,实现PS0-19地址写入,PL读取后写在20-39。

先看效果图:
在这里插入图片描述
接下来让我们看如何操作。

ZYNQ如何实现PS与PL的数据交互

相信大家都看过采用AXI接口通过BRAM,实现PS、PL之间的数据交互,但是网上的教程不尽人意,要么只是将PL的BRAM资源拿出来使用,实际上还是PS自己进行回环,基本上没有什么意义,如下图1。
在这里插入图片描述图1 BRAM内的数据回环
目前大部分厂商所构建的BRAM数据回环是下面这张图:但是基本上也都是假通信
在这里插入图片描述
图2 常见BRAM数据通信回环

本博客实现的不同点

我也是使用正点原子历程,但是这类代码基本上都是同样的结果:PS写入BRAM,PL的BRAM读取并非把数据读出来,而是搞个ILA可以实时看,这只有学习意义,也是假通信,而博主也是费尽心思,终于搞定了:
1、PS写0-9地址 0-9数据,触发start给PL。
2、PL接收到触发后,做两次的打拍,再遍历一遍,然后PL将0-9地址的数据实时读取,分别+2,写在10-19地址上
3、PS再读取10-19地址上的数据并显示。
博主认为,这才是真正完成了PS与PL之间的数据交互,而非仅仅使用了BRAM资源。接下来让我们看如何操作。

实现方案

可以直接用正点原子等网上那些的BRAM历程,对三个.v文件修改即可。

pl_bram_rd_v1_0_S00_AXI.v

主要是修改端口和例化bram_rd模块

// Users to add ports here//bram portinput  wire    [31:0]  din,	 //写入BRAMoutput wire [31:0]  dout,//读出BRAMoutput wire         en,//BRAM使能output wire [3:0]   we,//写读选择output wire [31:0]  addr,//地址output wire         intr,         //interrupt输出给PS做中断output   wire           bramclk,//bram时钟output     wire         bramrst_n,//bram复位// Add user logic herebram_rd u_bram_rd(.clk          (S_AXI_ACLK),.rst_n        (S_AXI_ARESETN),.start        (slv_reg0[0]),//PS写完数据后输出的一个脉冲触发.init_data    (slv_reg1),//未用到.len          (slv_reg2),//PS写入数据的长度.start_addr   (slv_reg3),    //PS写BRAM的起始地址//RAM端口   .din  (din),.en       (en     ),.addr     (addr   ),.we       (we     ),.dout  (dout),.bramclk(bramclk),.bramrst_n(bramrst_n),//bram port	 //control signal.intr(intr)       //start to read and write bram);// User logic ends

可以看到其实现了对外部的信号接口、例化了bram_rd模块。

pl_bram_rd_v1_0.v

	// Users to add ports here//bram portinput  wire    [31:0]  din,	 output wire [31:0]  dout,output wire         en,output wire [3:0]   we,output wire [31:0]  addr,output wire         intr,         //interruptoutput   wire           bramclk,output     wire         bramrst_n,pl_bram_rd_v1_0_S00_AXI_inst (//RAM端口   .din  (din),.en       (en     ),.addr     (addr   ),.we       (we     ),.dout  (dout),.bramclk(bramclk),.bramrst_n(bramrst_n),//bram port	 //control signal.intr(intr),       //start to read and write bram.S_AXI_ACLK(s00_axi_aclk),.S_AXI_ARESETN(s00_axi_aresetn),.S_AXI_AWADDR(s00_axi_awaddr),.S_AXI_AWPROT(s00_axi_awprot),.S_AXI_AWVALID(s00_axi_awvalid),.S_AXI_AWREADY(s00_axi_awready),.S_AXI_WDATA(s00_axi_wdata),.S_AXI_WSTRB(s00_axi_wstrb),.S_AXI_WVALID(s00_axi_wvalid),.S_AXI_WREADY(s00_axi_wready),.S_AXI_BRESP(s00_axi_bresp),.S_AXI_BVALID(s00_axi_bvalid),.S_AXI_BREADY(s00_axi_bready),.S_AXI_ARADDR(s00_axi_araddr),.S_AXI_ARPROT(s00_axi_arprot),.S_AXI_ARVALID(s00_axi_arvalid),.S_AXI_ARREADY(s00_axi_arready),.S_AXI_RDATA(s00_axi_rdata),.S_AXI_RRESP(s00_axi_rresp),.S_AXI_RVALID(s00_axi_rvalid),.S_AXI_RREADY(s00_axi_rready));

这个文件的内容和上个文件相辅相成

bram_rd.v

module bram_rd(input              clk,input              rst_n,//bram portinput      [31:0]  din,	 output reg [31:0]  dout,output reg         en,output reg [3:0]   we,output reg [31:0]  addr,//control signalinput              start,       //start to read and write braminput      [31:0]  init_data,   //没有用到output reg         start_clr,   //没有用到input      [31:0]  len,         //data countinput      [31:0]  start_addr,   //start bram address//Interruptinput              intr_clr,    //clear interruptoutput reg         intr,         //interruptoutput              bramclk,output              bramrst_n);assign bramclk = clk ;
assign bramrst_n = 1'b0 ;localparam IDLE      = 4'd0 ;  //上电初始化
localparam READ_INIT      = 4'd1 ;   //每次循环读的初始化
localparam INIT      = 4'd2 ;   //每次循环的初始化
localparam READ_START      = 4'd3 ;  //准备读前的初始化
localparam READ_RAM  = 4'd4 ; //读
localparam READ_END  = 4'd5 ;//读结束
localparam WRITE_START  = 4'd6 ;//准备写的初始化
localparam WRITE_RAM = 4'd7 ; //写
localparam WRITE_END = 4'd8 ;//写结束
localparam END = 4'd9 ;//结束reg [3:0] state ;
reg [31:0] len_tmp ;
reg [31:0] start_addr_tmp ;
reg [31:0] start_addr_tmp2 ;
reg [31:0] read_data_temp;
reg [31:0] read_addr;
reg [31:0] write_addr;reg start_rd_d0;
reg start_rd_d1;
//wire define
wire pos_start_rd;
assign pos_start_rd = ~start_rd_d1 & start_rd_d0;
//延时两拍,采 start_rd 信号的上升沿  因为BRAM_B读取数据需要延迟两拍,即在PS写好数据,需要等一下才能读到RAM数据
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginstart_rd_d0 <= 1'b0; start_rd_d1 <= 1'b0;endelse beginstart_rd_d0 <= start; start_rd_d1 <= start_rd_d0; endend//Main statement
always @(posedge clk or negedge rst_n)
beginif (!rst_n)beginstate      <= IDLE  ;dout       <= 32'd0 ;en         <= 1'b0  ;we         <= 4'd0  ;addr       <= 32'd0 ;intr       <= 1'b0  ;start_clr  <= 1'b0  ;len_tmp    <= 32'd0 ;						  end	elsebegincase(state)IDLE            : beginif (pos_start_rd)beginaddr<=start_addr;read_addr  <= start_addr;						  start_addr_tmp <= start_addr ;start_addr_tmp2<= start_addr+len ;  //从已有数据的后一位开始写write_addr<=start_addr+len ;  //从已有数据的后一位开始写len_tmp <= len ;	intr       <= 1'b0  ;  //读取到后取消触发state <= INIT     ; en    <= 1'b1;we   <= 4'd0;							  						  				  end			else begin state <= IDLE;intr  <= 1'b0;			              		en    <= 1'b0;addr  <= addr;we   <= 4'd0;						  						  			              				endendREAD_INIT        : beginif ((addr - start_addr_tmp) >= (len_tmp))   //当读取的遍历结束一遍beginstate <= INIT ;						  en    <= 1'b0  ;we    <= 4'd0  ;addr<=start_addr_tmp;  //获取读地址  提前两个周期read_addr<=start_addr_tmp; endelse beginstate <= READ_INIT;  //继续遍历addr<=read_addr;  //获取读地址 遍历read_addr<=read_addr+32'd4;read_data_temp<=din; 	end  endINIT        : beginstate <= READ_START     ;we    <= 4'b0000 ;en    <= 1'b1 ;  //先en1addr<=read_addr;  //获取读地址  提前两个周期//read_data_temp<=din; 	  end					  READ_START        : beginen    <= en;we    <= we;  //保持一个周期//read_data_temp<=din;state <= READ_RAM ;end  READ_RAM        : begin	 read_data_temp<=din;                   state <= READ_END  ;	                    					end					  READ_END        : beginread_addr<=read_addr+32'd4;en    <= 1'b0;		                                          state <= WRITE_START  ;					    end  WRITE_START        : beginen    <= 1'b1;we    <= 4'b1111;state <= WRITE_RAM  ;	addr  <= write_addr ;					     end							   	  					   WRITE_RAM       : beginif ((addr - start_addr_tmp2) >= (len_tmp))   //write completedbeginstate <= END ;						  en    <= 1'b0  ;we    <= 4'd0  ;endelsebegindout<=read_data_temp+32'd2; //到最后一位就不再写了  												  					  state <= WRITE_END ;endendWRITE_END       : beginwrite_addr  <= write_addr+32'd4 ;dout<=32'd0;addr<=read_addr;  //获取读地址  提前两个周期	en    <= 1'b0  ;we    <= 4'd0  ;state <= INIT ;					    endEND       : beginaddr <= 32'd0 ;dout  <= 32'd0; intr <= 1'b1 ;state <= IDLE ;					    end	default         : state <= IDLE ;endcaseend
end	
endmodule

其实现了捕获PS端输出的一个start脉冲,通过AXI-Lite接口得到start_addr起始地址和len数据长度,依次遍历后(保证数据的刷新),再进入后续状态机,读数据到reg变量,对该变量+2,写入到len长度后的BRAM块,最终读写完成后,输出一个高电平脉冲intr触发PS中断。

VIVADO的BD文件开发

相信大家应该都有用过正点之类厂商的代码,也看过相应的流程,同样的本博客的也是采用图2的方式,通过构建BRAM,一端接在axi_bram_ctrl_0也就是由PS可控制,一端接在PL构建的IP核:pl_bram_rd_0,接下来首先看BD文件都需要什么。
1、PL->PS的中断:我们知道AXI接口可以实现PL与PS的基本数据交互,但是不能实现中断,对于PL端来说,因为是并行数据处理,我们可以仅仅通过判断AXI的一个位是否为高电平做触发, 但是对于PS这样的ARM,不可能让他自己在那里循环等待,(当然可以实现,但是比较呆)。因此,我们需要有一个PL到PS的中断,使得PL数据写好后,触发中断给PS,PS响应中断后读取数据即可,如下图。
在这里插入图片描述
这样我们就实现了一个PL->PS的中断接口。
2、串口数据交互,由于博主用的板子只有PS端的串口有芯片,但是不能接收电脑数据,因此用了FPGA的PL端做串口,但是是采用的EMIO,也就是说操作还是在PS端,
在这里插入图片描述
在这里插入图片描述
如图采用的PL串口,是需要进行RUN Synthesis后进行绑定管脚,然后用一个CH340的串口模块,通过连接GND、RX、TX后实现与电脑的通信,如果大家是正点的板子,就不用考虑这个问题了。
在这里插入图片描述
然后再生成bit流,并export,launch sdk即可。

VIVADO SDK开发PS端

#include "xil_printf.h"
#include "xbram.h"
#include <stdio.h>
#include "pl_bram_rd.h"
#include "xscugic.h"#define BRAM_CTRL_BASE      XPAR_AXI_BRAM_CTRL_0_S_AXI_BASEADDR
#define BRAM_CTRL_HIGH      XPAR_AXI_BRAM_CTRL_0_S_AXI_HIGHADDR
#define PL_RAM_BASE         XPAR_PL_BRAM_RD_0_S00_AXI_BASEADDR
#define PL_RAM_CTRL         PL_BRAM_RD_S00_AXI_SLV_REG0_OFFSET
#define PL_RAM_INIT_DATA    PL_BRAM_RD_S00_AXI_SLV_REG1_OFFSET//没用到
#define PL_RAM_LEN          PL_BRAM_RD_S00_AXI_SLV_REG2_OFFSET
#define PL_RAM_ST_ADDR      PL_BRAM_RD_S00_AXI_SLV_REG3_OFFSET#define START_MASK   0x00000001   //b01
#define INTRCLR_MASK 0x00000002   //b10
#define INTC_DEVICE_ID	     XPAR_SCUGIC_SINGLE_DEVICE_ID
#define INTR_ID              XPAR_FABRIC_PL_BRAM_RD_0_INTR_INTR#define TEST_START_VAL      0x0
/** BRAM bytes number*/
#define BRAM_BYTENUM        4//每个数据占的字节大小,一般默认用4字节即32bitXScuGic INTCInst;char ch_data[1024];            //写入BRAM的字符数组
int Len=10  ;//单次写入长度
int Start_Addr=0 ;//写地址起始位即偏移0
int Intr_flag ;
/** Function declaration*/
int bram_read_write() ;
int IntrInitFuntion(u16 DeviceId);
void IntrHandler(void *InstancePtr);int main()
{int Status;Intr_flag = 1 ;IntrInitFuntion(INTC_DEVICE_ID) ;while(1){if (Intr_flag){Intr_flag = 0 ;Status = bram_read_write() ;if (Status != XST_SUCCESS){xil_printf("Bram Test Failed!\r\n") ;xil_printf("******************************************\r\n");Intr_flag = 1 ;}sleep(2);}}
}// 对BRAM的读写操作
int bram_read_write()
{u32 Write_Data = TEST_START_VAL ; // 要写入的数据int i ;/** if exceed BRAM address range, assert error*/if ((Start_Addr + Len) > (BRAM_CTRL_HIGH - BRAM_CTRL_BASE + 1)/4){xil_printf("******************************************\r\n");xil_printf("Error! Exceed Bram Control Address Range!\r\n");return XST_FAILURE ;}/** Write data to BRAM*/ //写地址长度0-9for(i = BRAM_BYTENUM*Start_Addr ; i < BRAM_BYTENUM*(Start_Addr + Len) ; i += BRAM_BYTENUM){XBram_WriteReg(XPAR_BRAM_0_BASEADDR, i , Write_Data) ;Write_Data += 1 ;  //写0-9}printf("完成PS写入BRAM\t\n等待捕获PL写BRAM结束中断\t\n");//Set ram read and write lengthPL_BRAM_RD_mWriteReg(PL_RAM_BASE, PL_RAM_LEN , BRAM_BYTENUM*Len) ;//写寄存器,告诉PL数据长度//Set ram start addressPL_BRAM_RD_mWriteReg(PL_RAM_BASE, PL_RAM_ST_ADDR , BRAM_BYTENUM*Start_Addr) ;//写寄存器,告诉PL数据起始地址//Set pl initial data  没用到//PL_BRAM_RD_mWriteReg(PL_RAM_BASE, PL_RAM_INIT_DATA , (Start_Addr+1)) ;//Set ram start signalPL_BRAM_RD_mWriteReg(PL_RAM_BASE, PL_RAM_CTRL , START_MASK) ;  //输出高电平脉冲触发startreturn XST_SUCCESS ;
}int IntrInitFuntion(u16 DeviceId)//接收PL端的intr中断
{XScuGic_Config *IntcConfig;int Status ;//check device idIntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);//intializationStatus = XScuGic_CfgInitialize(&INTCInst, IntcConfig, IntcConfig->CpuBaseAddress) ;if (Status != XST_SUCCESS)return XST_FAILURE ;XScuGic_SetPriorityTriggerType(&INTCInst, INTR_ID,0xA0, 0x3);Status = XScuGic_Connect(&INTCInst, INTR_ID,(Xil_ExceptionHandler)IntrHandler,(void *)NULL) ;if (Status != XST_SUCCESS)return XST_FAILURE ;XScuGic_Enable(&INTCInst, INTR_ID) ;Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&INTCInst);Xil_ExceptionEnable();return XST_SUCCESS ;}void IntrHandler(void *CallbackRef)//中断服务函数
{int Read_Data ;int i ;printf("捕获到PL写BRAM结束中断\t\n");//clear interrupt statusPL_BRAM_RD_mWriteReg(PL_RAM_BASE, PL_RAM_CTRL , INTRCLR_MASK) ;for(i = BRAM_BYTENUM*Start_Addr ; i < BRAM_BYTENUM*(Start_Addr + Len+15) ; i += BRAM_BYTENUM)  //len+10即可,只是多打几位,验证PL写的正确性{Read_Data = XBram_ReadReg(XPAR_BRAM_0_BASEADDR , i) ;printf("Address is %d\t Read data is %d\t\n",  i/BRAM_BYTENUM ,Read_Data) ;}Intr_flag = 1 ;
}

可以看到,定义数据传输的长度为10,BRAM_BYTENUM 大小为4,也就是说,一次占用4个字节即32bit,在BRAM端表现就是一个深度。
Start_Addr起始地址为0。
PL写完数据后,触发PS端在中断读取,速度绝对比轮询要快得多。
最终效果:
在这里插入图片描述
可以看到,当PS写入数据触发PL的start高电平,PL实时捕获到start后,开始读取BRAM的len长度数据分别+2,写在原数据的后面。
而且有给定len长度与地址长判断,可以实现仅修改
len为20,实现PS0-19地址写入,PL读取后写在20-39。

总结

本博客介绍了,PS写数据到BRAM,触发PL读取,PL读取并+2分别写入到后面地址上,触发PS中断读取。
网上找半天,都没有PL和PS联合BRAM的例子,大多都是搞个Xilinx官方历程,PS写好数据后,PL就遍历地址,通过ila查看数据。


http://chatgpt.dhexx.cn/article/a06VP0ui.shtml

相关文章

FPGA — BRAM 队列实践

使用软件&#xff1a; Vivado 开发板&#xff1a; EGO1采用Xilinx Artix-7系列XC7A35T-1CSG324C FPGA BRAM 队列实践 功能描述功能实现1. 添加BRAM的IP2. 数码管显示3. 时钟分频4. 按键消抖5. 顶层设计 结果遇到问题及解决仿真测试 功能描述 数码管3位显示数字&#xff0c;可以…

Vivado综合生成BRAM及与LUTRAM的区别

使用vivado中的BRAM可以通过例化Block Memory Generator这一ip并进行相关的设定。 另外可以通过直接编写符合BRAM规范的代码&#xff0c;借助综合工具直接将其综合为BRAM。这时需要通过(*ram_style"block"*)对array进行修饰。 下面给出一种看似可以综合为BRAM的示例…

Xilinx BRAM IP介绍

BRAM IP核介绍 BRAM简介BRAM类型三种读写模式写优先读优先No change 总线支持输出寄存 BRAM简介 BRAM&#xff0c;即Block RAM&#xff0c;是FPGA中一种重要的存储资源&#xff0c;另一种常见的存储资源是DRAM(Distributed RAM)&#xff0c;Distributed RAM 经过综合工具综合&…

vivado中bram简单使用

bram设置为简单双口 建议取消勾选这个&#xff0c;这样读出来的数据是差一个时钟周期的 vivado中的bram&#xff0c;写的时候&#xff0c;写使能&#xff0c;写地址&#xff0c;写数据一起赋值 读的时候&#xff0c;读使能&#xff0c;读地址可以一起赋值&#xff0c;数据为…

使用VIVADO中的MIG控制DDR3(AXI接口)二——用AXI4读写BRAM测试

上篇文章主要讲了一些关于AXI的知识&#xff0c;有了这些理论&#xff0c;让我们进行一些简单的实验测试&#xff0c;加深对AXI协议的理解。本次实验使用的平台是VIVADO2019.1。 1. 首先创建一个工程&#xff0c;名称和路径自己决定。 2.然后按照图中所示&#xff0c;点击新建和…

URAM和BRAM有什么区别

无论是7系列FPGA、UltraScale还是UltraScale Plus系列FPGA&#xff0c;都包含Block RAM&#xff08;BRAM&#xff09;&#xff0c;但只有UltraScale Plus芯片有UltraRAM也就是我们所说的URAM。BRAM和URAM都是重要的片上存储资源&#xff0c;但两者还是有些显著的区别。 容量 B…

【FPGA】AXI4-Lite总线读写BRAM

博主参考和学习的博客 AXI协议基础知识 。这篇博客比较详细地介绍了AXI总线&#xff0c;并且罗列了所有的通道和端口&#xff0c;写代码的时候可以方便地进行查表。AXI总线&#xff0c;AXI_BRAM读写仿真测试 。 这篇文章为代码的书写提供大致的思路&#xff0c;比如状态机和时…

如何对bram/ram进行初始化赋值呢?

1、首先对于常规的情况&#xff0c;即加载.coe文件的方式实现初始化&#xff08;与rom相同&#xff09; 点击load initial file, 在右侧可以直接添加.coe文件&#xff0c;或者选择edit进行手动编辑&#xff08;数据量不大的情况下可选&#xff0c;但是不推荐&#xff09;&#…

vivado中bram的种类与使用

vivado中bram的种类与使用 vivado中bram的分类单端口ram初始化工作时序仿真验证 简化的双端口RAM初始化端口定义仿真结果 双端口RAM初始化端口定义功能仿真单端口读数双端口读数双端口一读一写双端口写数据 vivado中bram的分类 在vivado中打开IP catalog&#xff0c;在其中搜索…

BRAM的使用

使用Block Memory Generator IP核&#xff0c;PL读取BRAM数据 软件环境&#xff1a;Vivado 2018.3 IP核&#xff1a;Block Memory Generator 8.4(Rev.2) 1、点击IP Catalog 2、搜索”Block Memory Generator“双击选择RAMs & ROMs & BRAM下的IP核 3、配置IP核为Si…

FPGA — BRAM学习笔记—读写操作

使用软件&#xff1a; Vivado 开发板&#xff1a; EGO1采用Xilinx Artix-7系列XC7A35T-1CSG324C FPGA BRAM笔记 BRAM介绍同步双端口BRAMBRAM读写操作(1)读操作(2)写操作(3)写模式写优先模式读优先模式不变模式 双端口块内存接口BRAM IP的使用及仿真验证IP核使用coe文件将IP核添…

FPGA从入门到精通(8)-BRAM

所使用EDA软件&#xff1a;VIVADO2018.3 FPGA型号&#xff1a;xc7a35tcsg325-2 很久没写了&#xff0c;随便写一篇BRAM的吧。说到BRAM &#xff0c;很多人都喜欢拿它来DRAM比较 &#xff0c;两者都有啥优缺点&#xff0c;其实我也拿不准。不过一般来说&#xff0c;存储较大的数…

Xilinx系列学习(一) BRAM的使用,并用PL读取BRAM数据

Xilinx系列学习(一) BRAM的使用,并用PL读取BRAM数据 一,Xilinx BRAM介绍二,BRAM对应的IP核调用和使用1,BRAM对应的IP核介绍2,BMG例化IP核的调用一,Xilinx BRAM介绍 BRAM 就是Block Memory,是Zynq的PL端的存储RAM单元。可以利用BRAM,在PS和PL之间进行数据的交换。Zyn…

FPGA设计中BRAM(Block RAMs)资源的使用(综合为BRAM)

FPGA设计中BRAM&#xff08;Block RAMs&#xff09;资源的使用 RAM分为BRAM&#xff08;Block RAMs&#xff09;和DRAM&#xff08;Distributed RAM&#xff09;&#xff0c;即块RAM与分布式RAM&#xff0c;这两个差别在于BRAM是FPGA上固有的一些存储资源&#xff08;针对不同型…

web测试与app测试的区别

目录 前言 首先从系统架构来看 专项测试 安装、卸载、更新&#xff1a; 界面操作&#xff1a; 前言 仅仅从功能测试的层面上来讲的话&#xff0c;在流程和功能测试上是没有区别的。那么区别在哪里呢&#xff1f; 我个人觉得就是由于载体不一样&#xff0c;所以系统测试和…

APP测试与WEB测试

APP测试与WEB测试的区别(异同) 相同点&#xff1a; 功能测试层面而言&#xff1a;APP测试和web测试都是使用相同的测试用例测试方法&#xff08;都用到等价类划分、边界值分析、正常和异常情况去考虑测试点&#xff09; UI界面测试&#xff1a;都需要按照原型图和设计图检查UI…

web测试,App测试,小程序测试区别

最近项目真的太忙了&#xff0c;不过&#xff0c;今天无论如何我都要更文章了&#xff0c;谢谢大家的支持&#xff0c;不断努力进步 这篇文章&#xff0c;我就是要梳理一下&#xff0c;web测试&#xff0c;app测试&#xff0c;和小程序的区别 话不多说&#xff0c;上主题 web…

WEB端与移动端测试区别和总结

WEB端与移动端测试区别总结如下&#xff1a; 1、系统架构 WEB端 B/S结构&#xff0c;WEB端的前端一般不做端的区分 WEB端的上线不管是预发布还是N环上线&#xff0c;server上线后&#xff0c;前端同步更新&#xff0c;一般是不存在多个版本的问题; 移动端 C/S结构&#xff0c;移…

Apifox简单了解——WEB端测试的集大成者

文章目录 0 引入1、Postman2、Swagger &#xff08;丝袜哥&#xff09;3、Mock4、JMeter5、Apifox6、引用 0 引入 Apifox Postman Swagger Mock JMeter 1、Postman 1 作用 Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件&#xff0c;简单易用的接口测试…

web测试的基本流程

1、web测试流程&#xff1a; (1)web测试 1)参与一个web新项目的测试前&#xff0c;先搜集测试相关的资料&#xff0c;包括原型图、各种需求文档、业务相关等需求相关材料 2)结合第一步搜集到的需求相关资料&#xff0c;自行熟悉系统&#xff0c;同时列出不明白的点&#xff0c;…