FPGA:有限状态机

从以下6个实验理解状态机的概念
在这里插入图片描述
开发板频率为 50 M H z 50MHz 50MHz,一个时钟周期是 20 n s 20ns 20ns

1、实验一:LED灯亮0.25秒、灭0.75秒的状态循环

通过之前的分析,我们实现频闪灯时,是让led灯在0.5秒实现一次翻转,而这里虽然总时长都是一秒,但是要求亮的时间和不亮的时间缺不是相等的。 1 s ÷ 20 n s = 5 × 1 0 7 T 1s÷20ns=5\times10^7T 1s÷20ns=5×107T,即一秒钟有 50000000 50000000 50000000个时钟周期,而 ⌈ l o g 2 50000000 ⌉ = 26 ⌈log_250000000⌉=26 log250000000=26,所以计数器需要26位。我们可以在前0.75秒保持灯灭,在0.75秒-1秒保持灯亮,即可实现对应的要求。
对应的verilog代码如下:

module led_flash1(clk,Reset_n,led
);
input clk;
input Reset_n;
output reg led;
reg [25:0] counter;
parameter MCNT=50000000;
always @(posedge clk or negedge Reset_n)if(!Reset_n)counter<=0;else if(counter==MCNT-1)counter<=0;elsecounter<=counter+1'b1;
always @(posedge clk or negedge Reset_n)if(!Reset_n)led<=0;else if(counter==(3*MCNT)/4-1)  //0.75秒时1秒的3/4led<=1;else if(counter==MCNT-1)led<=0;
endmodule

对应的测试文件如下:

`timescale 1ns/1ps
module led_flash_tb();
reg clk;
reg Reset_n;
wire led;
led_flash1 led_flash_inst(.clk(clk),.Reset_n(Reset_n),.led(led)
);
defparam led_flash_inst.MCNT=50000;
initial clk=1;
always #10 clk=!clk;
initial beginReset_n=0;#201;Reset_n=1;#2000000;$stop;end
endmodule

进行仿真,对应的波形图如下所示:
在这里插入图片描述

和我们分析的结果一致,前面还有对应的零头使我们复位的用时。但是通过add_maker可以发现和预想结果一致。

2、实验二:LED灯亮0.25秒,灭0.5秒,亮0.75秒,灭1秒顺序循环

此时总时间周期为 0.25 + 0.5 + 0.75 + 1 = 2.5 s 0.25+0.5+0.75+1=2.5s 0.25+0.5+0.75+1=2.5s
2.5 s ÷ 20 n s = 125000000 T 2.5s \div 20ns=125000000T 2.5s÷20ns=125000000T,而 ⌈ l o g 2 125000000 ⌉ = 27 ⌈log_2125000000⌉=27 log2125000000=27,所以计数器需要27位,其余实现思路类似。
比如从开始分析,复位时令led为1,然后亮0.25秒,即十分之一个周期,然后灭0.5秒,即在0.25秒到0.75秒为灭,0.75秒为十分之三个周期,0.75秒到1.5秒为亮,1.5秒为五分之三个总周期,1.5秒-2.5秒为灭。这就是一个周期。对应的verilog代码如下:

module led_flash2(clk,Reset_n,led
);
input clk;
input Reset_n;
output reg led;
reg [26:0] counter;
parameter MCNT=125000000;
always @(posedge clk or negedge Reset_n)if(!Reset_n)counter<=0;else if(counter==MCNT-1)counter<=0;elsecounter<=counter+1'b1;
always @(posedge clk or negedge Reset_n)if(!Reset_n)led<=1;else if(counter==MCNT/10-1)led<=0;else if(counter==(MCNT)*3/10-1)led<=1;else if(counter==(MCNT)*3/5-1)led<=0;else if(counter==MCNT-1)led<=1;
endmodule

测试文件如下

`timescale 1ns/1ps
module led_flash_tb();
reg clk;
reg Reset_n;
wire led;
led_flash2 led_flash_inst(.clk(clk),.Reset_n(Reset_n),.led(led)
);
defparam led_flash_inst.MCNT=125000;
initial clk=1;
always #10 clk=!clk;
initial beginReset_n=0;#201;Reset_n=1;#20000000;$stop;end
endmodule

打开仿真如下所示:
在这里插入图片描述

3、实验三:LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机制定,以0.25秒为一个变化周期,8个变化状态为一个循环。

这个实验的思路就是加上一个端口[7:0]ctrl,用来记录状态,每过0.25秒的时候,转换到下一个状态,计算可得,单个总时长为 0.25 × 8 = 2 s 0.25×8=2s 0.25×8=2s,单个周期内的时钟周期数: 2 × 1 0 9 ÷ 20 = 100000000 T 2×10^9÷20=100000000T 2×109÷20=100000000T,需要27位计数器,所以可以定义一个变量让其等于 1000000000 1000000000 1000000000,每经过八分之一个周期切换一次状态即可。具体实现的verilog代码如下:

module led_flash3(clk,Reset_n,led,ctrl
);
input clk;
input Reset_n;
output reg led;
input [7:0] ctrl;
reg [26:0] counter;
parameter MCNT=100000000;
always @(posedge clk or negedge Reset_n)if(!Reset_n)counter<=0;else if(counter==MCNT-1)counter<=0;elsecounter<=counter+1'b1;
always @(posedge clk or negedge Reset_n)if(!Reset_n)led<=0;else if(counter==MCNT/8-1)led<=ctrl[0];else if(counter==(MCNT)*2/8-1)led<=ctrl[1];else if(counter==(MCNT)*3/8-1)led<=ctrl[2];else if(counter==(MCNT)*4/8-1)led<=ctrl[3];else if(counter==(MCNT)*5/8-1)led<=ctrl[4];else if(counter==(MCNT)*6/8-1)led<=ctrl[5];else if(counter==(MCNT)*7/8-1)led<=ctrl[6];else if(counter==MCNT-1)led<=ctrl[7];
endmodule

测试文件代码如下:

`timescale 1ns/1ps
module led_flash3_tb();
reg clk;
reg Reset_n;
reg[7:0] ctrl;
wire led;
led_flash3 led_flash_inst(.clk(clk),.Reset_n(Reset_n),.led(led),.ctrl(ctrl)
);
defparam led_flash_inst.MCNT=100000;
initial clk=1;
always #10 clk=!clk;
initial beginReset_n=0;#201;Reset_n=1;ctrl = 8'b0101_0110;    //初始的ctrl状态#20000000;$stop;end
endmodule

仿真波形如下:
注意高低位的判断,ctrl[0]=0,ctrl[1]=1,ctrl[2]=1,ctrl[3]=0,ctrl[4]=1,ctrl[5]=0,ctrl[6]=1,ctrl[7]=0,所以显示应该为01101010,测试文件里面我们定义MCNT为100000, 100000 × 20 ÷ 8 = 250 μ s 100000×20÷8=250μs 100000×20÷8=250μs,所以仿真内一个变化周期为 250 μ s 250μs 250μs,观察可知相符。
在这里插入图片描述

4、实验四:让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机制定,8个变化状态为一个循环,每个变化状态的时间值可以根据不同的应用场景选择。

实验思路:加入一个时间端口Time,计数器1专门用来计数,计数器2专门用来计状态,当计数器1满一个Time则计数器2加1。此处设Time位宽为32位,即[31:0]。所以计数器1要和它一样长,否则会出现溢出,只有8种状态,需要3位二进制表示。具体verilog代码如下:

module led_flash3(clk,Reset_n,led,ctrl,Time
);
input clk;
input Reset_n;
output reg led;
input [7:0] ctrl;
input [31:0] Time;
reg [31:0] counter;
reg [2:0] counter2;
always @(posedge clk or negedge Reset_n)if(!Reset_n)counter<=0;else if(counter==Time-1)counter<=0;elsecounter<=counter+1'b1;
always @(posedge clk or negedge Reset_n)if(!Reset_n)counter2<=0;else if (counter==Time-1)counter2<=counter2+1'b1;
always @(posedge clk or negedge Reset_n)if(!Reset_n)led<=0;elsecase(counter2)0:led<=ctrl[0];1:led<=ctrl[1];2:led<=ctrl[2];3:led<=ctrl[3];4:led<=ctrl[4];5:led<=ctrl[5];6:led<=ctrl[6];7:led<=ctrl[7];default:led<=led;endcase
endmodule

测试文件如下:

`timescale 1ns/1ps
module led_flash4_tb();
reg clk;
reg Reset_n;
reg[7:0] ctrl;
reg [31:0] Time;
wire led;
led_flash4 led_flash_inst(.clk(clk),.Reset_n(Reset_n),.led(led),.ctrl(ctrl),.Time(Time)
);
initial clk=1;
always #10 clk=!clk;
initial beginReset_n=0;ctrl=0;Time=0;#201;Reset_n=1;Time = 2500;ctrl = 8'b1110_1101;#20000000;$stop;end
endmodule

这里Time定义为2500,即一个小周期2500个时钟周期,即 2500 × 20 n s = 50 μ s 2500×20ns=50μs 2500×20ns=50μs,仿真波形如下
在这里插入图片描述

5、实验五:让多个LED灯按照设置的模式各自在一个变化循环内独立亮灭变换

实验思路:和之前一样,这里在输入端口上加上8位的LED控制对应的LED灯即可。(为了简化输入输出,在这里time和ctrl都设置为定值),对应verilog代码如下:

module led_flash5(clk,Reset_n,led,ctrl
);
input clk;
input Reset_n;
input [7:0] ctrl;
output reg[7:0] led;
parameter Time=24999999;
reg [31:0] counter;
reg [2:0] counter2;
always @(posedge clk or negedge Reset_n)if(!Reset_n)counter<=0;else if(counter==Time-1)counter<=0;elsecounter<=counter+1'b1;
always @(posedge clk or negedge Reset_n)if(!Reset_n)counter2<=0;else if (counter==Time-1)counter2<=counter2+1'b1;
always @(posedge clk or negedge Reset_n)if(!Reset_n)led<=0;elsecase(counter2)0:beginled[0]<=ctrl[0];led[1]<=ctrl[0];led[2]<=ctrl[0];led[3]<=ctrl[0];led[4]<=ctrl[0];led[5]<=ctrl[0];led[6]<=ctrl[0];led[7]<=ctrl[0];end1:beginled[0]<=ctrl[1];led[1]<=ctrl[1];led[2]<=ctrl[1];led[3]<=ctrl[1];led[4]<=ctrl[1];led[5]<=ctrl[1];led[6]<=ctrl[1];led[7]<=ctrl[1];end2:beginled[0]<=ctrl[2];led[1]<=ctrl[2];led[2]<=ctrl[2];led[3]<=ctrl[2];led[4]<=ctrl[2];led[5]<=ctrl[2];led[6]<=ctrl[2];led[7]<=ctrl[2];end3:beginled[0]<=ctrl[3];led[1]<=ctrl[3];led[2]<=ctrl[3];led[3]<=ctrl[3];led[4]<=ctrl[3];led[5]<=ctrl[3];led[6]<=ctrl[3];led[7]<=ctrl[3];end4:beginled[0]<=ctrl[4];led[1]<=ctrl[4];led[2]<=ctrl[4];led[3]<=ctrl[4];led[4]<=ctrl[4];led[5]<=ctrl[4];led[6]<=ctrl[4];led[7]<=ctrl[4];end5:beginled[0]<=ctrl[5];led[1]<=ctrl[5];led[2]<=ctrl[5];led[3]<=ctrl[5];led[4]<=ctrl[5];led[5]<=ctrl[5];led[6]<=ctrl[5];led[7]<=ctrl[5];end6:beginled[0]<=ctrl[6];led[1]<=ctrl[6];led[2]<=ctrl[6];led[3]<=ctrl[6];led[4]<=ctrl[6];led[5]<=ctrl[6];led[6]<=ctrl[6];led[7]<=ctrl[6];end7:beginled[0]<=ctrl[7];led[1]<=ctrl[7];led[2]<=ctrl[7];led[3]<=ctrl[7];led[4]<=ctrl[7];led[5]<=ctrl[7];led[6]<=ctrl[7];led[7]<=ctrl[7];enddefault:beginled[0]<=led[0];led[1]<=led[1];led[2]<=led[2];led[3]<=led[3];led[4]<=led[4];led[5]<=led[5];led[6]<=led[6];led[7]<=led[7];endendcase
endmodule

测试文件如下:

`timescale 1ns/1ps
module led_flash5_tb();
reg clk;
reg Reset_n;
reg [7:0] ctrl;
wire [7:0]led;
led_flash5 led_flash_inst(.clk(clk),.Reset_n(Reset_n),.led(led),.ctrl(ctrl)
);
defparam led_flash_inst.Time=2500;
initial clk=1;
always #10 clk=!clk;
initial beginReset_n=0;ctrl=0;#201;Reset_n=1;ctrl=8'b1101_1010;#20000000;$stop;end
endmodule

Time依旧采用2500,即 50 μ s 50μs 50μs,在测试文件中,令ctrl=1101_1010,注意这是ctrl[7]-ctrl[0]顺序,仿真波形如下:
在这里插入图片描述
这里我们进行引脚分配并进行班级调试,将ctrl分配给八个开关,led分配给对应的led灯,Reset_n分配给按键S0,clk分配给时钟单元。
引脚分配
生成比特流,烧到开发板进行调试,分析一下:当我们按键上推表示在对应小周期就是亮的,如果SW7-SW0是按照10101010,那就是之前所说的频闪灯,只不过这里是0.5s,前0.25秒亮,后0.25秒灭,如果是0000_1111,那就是后一秒亮,前1秒不亮,频闪周期2秒。全0则全不亮,全1则全亮。接下来验证一下上面的分析:

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

6、实验六:每隔10ms,让LED灯的一个8状态循环执行一次(每10ms执行一次)

10 m s ÷ 20 n s = 500000 T 10ms÷20ns=500000T 10ms÷20ns=500000T,8个状态最多在10ms内运行完成 500000 ÷ 8 = 62500 T 500000÷8=62500T 500000÷8=62500T,即每个小周期最多有62500个时钟周期。 ⌈ l o g 2 62500 ⌉ = 16 ⌈log_262500⌉=16 log262500=16,即Time最多16位,接下来我们定义一个计时器为10ms, ⌈ l o g 2 500000 ⌉ = 19 ⌈log_2500000⌉=19 log2500000=19,即最多需要19位。再增加一共标志位,当计数状态慢8状态时,标志位为0,即阻塞不再执行,当计数器3(计时10毫秒)满时,标志位重新恢复为1.对应verilog代码如下:

module led_flash6(clk,Reset_n,led,ctrl,Time
);
input clk;
input Reset_n;
output reg led;
input [7:0] ctrl;
input [15:0] Time;
reg [15:0] counter;
reg [2:0] counter2;
reg [18:0]counter3;
reg logo; //标志位
always @(posedge clk or negedge Reset_n)   //单个小周期计数器if(!Reset_n)counter<=0;else if(logo)beginif(counter==Time-1)counter<=0;elsecounter<=counter+1'b1;endelsecounter<=0;
always @(posedge clk or negedge Reset_n)   // 状态计数器if(!Reset_n)counter2<=0;else if (logo)beginif(counter==Time-1)counter2<=counter2+1'b1;endelsecounter2<=0;
always @(posedge clk or negedge Reset_n)   //计数10毫秒if(!Reset_n)counter3<=0; //复位else if(counter2 == 500000-1)   //counter3<=0;elsecounter<=counter+1;
always @(posedge clk or negedge Reset_n)  //标志位if(!Reset_n)logo<=0;else if(counter3==0)logo<=1;else if((counter2==7)&&(counter==Time-1))logo<=0;
always @(posedge clk or negedge Reset_n)if(!Reset_n)led<=0;else case(counter2)0:led<=ctrl[0];1:led<=ctrl[1];2:led<=ctrl[2];3:led<=ctrl[3];4:led<=ctrl[4];5:led<=ctrl[5];6:led<=ctrl[6];7:led<=ctrl[7];default:led<=led;endcase
endmodule                                                                                                                                                                                                                              

测试文件代码如下:

`timescale 1ns/1ps
module led_flash6_tb();
reg clk;
reg Reset_n;
reg[7:0] ctrl;
reg [15:0] Time;
wire led;
led_flash6 led_flash_inst(.clk(clk),.Reset_n(Reset_n),.led(led),.ctrl(ctrl),.Time(Time)
);
initial clk=1;
always #10 clk=!clk;
initial beginReset_n=0;ctrl=0;Time=0;#201;Reset_n=1;Time = 2500;ctrl = 8'b1110_1101;#20000000;$stop;end
endmodule

执行仿真,波形图如下所示。
在这里插入图片描述

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

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

相关文章

经典文献阅读之--World Models for Autonomous Driving(自动驾驶的世界模型:综述)

Tip: 如果你在进行深度学习、自动驾驶、模型推理、微调或AI绘画出图等任务&#xff0c;并且需要GPU资源&#xff0c;可以考虑使用UCloud云计算旗下的Compshare的GPU算力云平台。他们提供高性价比的4090 GPU&#xff0c;按时收费每卡2.6元&#xff0c;月卡只需要1.7元每小时&…

html+css 实现水波纹按钮

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽效果&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 文…

vue3前端开发-小兔鲜项目-使用pinia插件完成token的本地存储

vue3前端开发-小兔鲜项目-使用pinia插件完成token的本地存储&#xff01;实际业务开发中&#xff0c;token是一个表示着用户登录状态的重要信息&#xff0c;它有自己的生命周期。因此&#xff0c;这个参数值必须实例化存储在本地中。不能跟着pinia。因为pinia是基于内存设计的模…

事务和函数索引

事务 事务的定义 事务&#xff08;Transaction&#xff09;&#xff0c;就是将一组SQL语句放在同一批次内去执行&#xff0c;如果一个SQL语句出错&#xff0c;则该批次内 的所有SQL都将被取消执行。 事务的特点 一个事务中如果有一个数据库操作失败&#xff0c;那么整个 事务…

若依框架 : 生成代码

6.生成代码 6.1.配置生成设置 ruoyi-generator -> src -> main -> resources -> generator.yml 由于 案例中 表都有 前缀 为 tta_ , 这里设置去掉 6.2.生成代码 6.2.1.导入数据库中的表 6.2.2.修改设置 6.2.2.1.设置生成信息 点击 编辑 -> 生成信息 特别…

m4a怎么转mp3?m4a转mp3的几种方法教程

m4a怎么转mp3&#xff1f;M4A音频格式的全称MPEG-4 Audio&#xff0c;是一种音频压缩格式。这种格式以其卓越的音质和相对较小的文件大小而广受欢迎&#xff0c;尤其是在音乐存储、在线流媒体以及音频编辑等领域。M4A格式被广泛应用于苹果公司的产品中&#xff0c;如iPhone、iP…

开放式耳机会成为未来的主流吗?开放式耳机推荐指南

开放式耳机是否会成为未来的主流&#xff0c;是一个值得探讨的问题。 从目前的市场趋势和技术发展来看&#xff0c;有一些因素支持开放式耳机可能成为主流。 一方面&#xff0c;人们对于健康和舒适的关注度不断提高。长时间佩戴传统耳机可能导致耳部不适&#xff0c;而开放式…

在Linux中,部署及优化Tomcat

tomcat概述 自 2017 年 11月编程语言排行榜 Java 占比 13%,高居榜首&#xff0c;Tomcat 也一度成为 Java开发人员的首选。其开源、占用系统资源少、跨平台等特性深受广大程序员喜爱。本章主要学习如何部署 Tomcat 服务&#xff0c;根据生产环境实现多个虚拟主机的配置&#xf…

【QGroundControl二次开发】五.python生成自定义MAVLink消息及使用

一 . 环境配置 参考&#xff1a; MAVLink代码生成-C# 二. 生成MAVLINK协议 在MAVlink源码下找到message_definitions/common.xml&#xff0c;修改其中的内容。 例如&#xff1a; <message id"12" name"DISTANCE_SENSOR"><description>Dedi…

【Code Complete2】Note-1 [启发式编程、管理复杂度、隐藏设计]

【Code Complete2】_Note-1 [启发式编程、管理复杂度、隐藏设计] 文章目录 【Code Complete2】_Note-1 [启发式编程、管理复杂度、隐藏设计]启发式编程管理复杂度隐藏设计--减少“改动所影响的代码量” 启发式编程 ​ **设计是一个启发的过程&#xff0c;充满了不确定性&#…

记录|cmd方式恢复U盘中的数据

目录 前言一、CMD恢复Step1.Step2. 更新时间 前言 参考文章&#xff1a; u盘数据误删怎么恢复&#xff1f;安利8款数据恢复软件免费版&#xff08;2024 NEW&#xff09; 回家后&#xff0c;家人说U盘里的歌突然没有了。我就用电脑看了看&#xff0c;发现电脑中能看到U盘中是满的…

修改启动方案

AMP设置为1Linux&#xff08;CPU0&#xff09; 3HAL&#xff08;CPU1、 2、 3&#xff09; 配置。 用vscode打开its 配置文件rk3568_amp_linux.its文件修改 /* SPDX-License-Identifier: BSD-3-Clause */ /** Copyright (c) 2022 Rockchip Electronics Co., Ltd.*//dts-v1/; /…

【优秀python算法毕设】基于python时间序列模型分析气温变化趋势的设计与实现

1 绪论 1.1 研究背景与意义 在气候变化日益受到全球关注的背景下&#xff0c;天气气温的变化已经对人们的生活各方面都产生了影响&#xff0c;人们在外出时大多都会在手机上看看天气如何&#xff0c;根据天气的变化来决定衣物的穿着和出行的安排。[1]如今手机能提供的信息已经…

【大模型】基于LoRA微调Gemma大模型(1)

文章目录 一、LoRA工作原理1.1 基本原理1.2 实现步骤 二、LoRA 实现2.1 PEFT库&#xff1a;高效参数微调LoraConfig类&#xff1a;配置参数 2.2 TRL库SFTTrainer 类 三、代码实现3.1 核心代码3.2 完整代码 参考资料 大模型微调技术有很多&#xff0c;如P-Tuning、LoRA 等&#…

操作系统杂项(八)

目录 一、简述互斥锁的机制&#xff0c;互斥锁与读写的区别 1、互斥锁机制 2、互斥锁和读写锁 二、简述信号量及其作用 1、概念 2、原理 3、作用 三、简述进程、线程的中断切换过程 1、进程上下文切换 2、线程上下文切换 四、简述自旋锁和互斥锁的使用场景 1、互斥…

宝塔单ip,新建多站点

报错如上&#xff1a; 那么如何新建多站点呢 先随便写个名字上去&#xff0c;然后再重新绑定别的端口… 这个时候访问99端口即可 。 如果是有域名&#xff0c;则不需要这样做 、直接80端口也可以多站点

数据缺失补全方法综述

数据缺失补全方法综述 摘要1. 引言2. 数据缺失的类型3. 数据缺失补全方法3.1 简单插补方法3.1.1 均值插补3.1.2 中位数插补3.1.3 众数插补3.1.4 前向填充和后向填充3.1.5 线性插值3.1.6 多重插补 3.2 基于模型的插补方法3.2.1 线性回归插补3.2.2 加权回归插补3.2.3 主成分分析&…

STM32智能工业监控系统教程

目录 引言环境准备智能工业监控系统基础代码实现&#xff1a;实现智能工业监控系统 4.1 数据采集模块 4.2 数据处理与控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;工业监控与优化问题解决方案与优化收尾与总结 1. 引言 智能工业监控系统通…

Navicat premium最新【16/17 版本】安装下载教程,图文步骤详解(超简单,一步到位,免费下载领取)

文章目录 软件介绍软件下载安装步骤激活步骤 软件介绍 Navicat是一款快速、可靠且功能全面的数据库管理工具&#xff0c;专为简化数据库的管理及降低系统管理成本而设计。以下是对Navicat的详细介绍&#xff1a; 一、产品概述 开发目的&#xff1a;Navicat旨在通过其直观和设计…

HTML前端面试题之<iframe>标签

面试题&#xff1a;iframe 标签的作用是什么?有哪些优缺点 ? 讲真&#xff0c;刷这道面试题之前我根本没有接触过iframe&#xff0c;网课没讲过&#xff0c;项目实战没用过&#xff0c;但却在面试题里出现了&#xff01;好吧&#xff0c;我只能说&#xff1a;前端路漫漫&…