diff --git a/public/doc/01_water_led/images/1.png b/public/doc/01_water_led/images/1.png new file mode 100644 index 0000000..45094e0 Binary files /dev/null and b/public/doc/01_water_led/images/1.png differ diff --git a/public/doc/01_water_led/images/2.png b/public/doc/01_water_led/images/2.png new file mode 100644 index 0000000..118cb90 Binary files /dev/null and b/public/doc/01_water_led/images/2.png differ diff --git a/public/doc/01_water_led/images/3.png b/public/doc/01_water_led/images/3.png new file mode 100644 index 0000000..49520aa Binary files /dev/null and b/public/doc/01_water_led/images/3.png differ diff --git a/public/doc/01_water_led/images/4.png b/public/doc/01_water_led/images/4.png new file mode 100644 index 0000000..a9134bb Binary files /dev/null and b/public/doc/01_water_led/images/4.png differ diff --git a/public/doc/01_water_led/water_led.md b/public/doc/01_water_led/water_led.md new file mode 100644 index 0000000..f0f0496 --- /dev/null +++ b/public/doc/01_water_led/water_led.md @@ -0,0 +1,175 @@ +# 基础-1-流水灯 + +## 1.1 章节导读 + +流水灯实验作为基础实验的第一个实验是非常合适的,本章我们利用试验箱中的LED进行点亮LED,并实现流水灯的功能。 + +## 1.2 理论学习 + +相信大家之前肯定接触过单片机等设备,而学习这些设备的第一个实验例程往往都是点亮一个LED。本次实验在点亮LED的基础上另LED灯依次闪亮,循环不止,实现“流水”的功能。其原理是依次控制连接到LED的IO口的电平高低,让LED的闪亮间隔为0.5s,以实现流水灯的效果。 + +## 1.3 实战演练 + +### 1.3.1实验目标 + +依次点亮实验板中的8个LED灯,两灯点亮间隔为0.5s,每次点亮持续0.5s,实现流水灯效果。 + +### 1.3.2硬件资源 + +实验板上有0~31共32个LED灯的资源,每4个LED灯为一组,分别是绿,红,蓝,黄四种颜色,本次实验使用8个LED进行验证。 + +
+
+ 无法显示图片时显示的文字 +
+ 图1.LED扩展板 +
+
+ +通过原理图可以得知,本试验箱的LED灯为高电平时点亮。 + +
+
+ 无法显示图片时显示的文字 +
+ 图2.LED扩展板原理图 +
+
+ +### 1.3.3程序设计 + +流水灯的设计与分频器,计数器的逻辑相似,只是多了LED灯的点亮部分。为了实现计数器肯定需要时钟信号sysclk,也需要一个复位信号rstn,同时为了驱动LED,需要8个IO口。所以模块的端口如下表所示: + +| 端口名称 | 端口位宽 | 端口类型 |功能描述 +|:----------:|:----:|:----:|:--------------------:| +| sysclk | 1Bit | Input | 输入时钟,频率27M | +| rstn | 1Bit | Input | 复位信号,低电平有效 | +| led | 8Bit | Output | LED控制信号 | + + +为了使灯点亮0.5s,我们应该设计一个计数器或者是分频器,先将板载27M高频时钟降速。在27M时钟下计数0.5s,需要计数器计数13_500_000个数,也就是计数器从0开始计数到13_499_999。所以我们定义一个寄存器cnt,每一次时钟上升沿cnt就加1,当计数到13_499_999时,led的状态改变,同时cnt归零重新开始计数。 + +为了实现8个led流水的效果,我们将0定义为led灭,1表示亮,初始状态led = 8’b0000_0001,当经过0.5s后,也就是cnt等于13_499_999的时候,第一个led灭,第二个led亮起,也就是led = 8‘b0000_0010。同理,再过0.5s,led = 8’b0000_0100,再过0.5s,led = 8‘b0000_1000以此类推。 + +根据上面的规律我们很容易发现,led的流水是靠1的移位来实现的,也就是最基本的左移(<<)和右移(>>)运算符去实现。在这里我们需要向左移位,并且每次只需要移动1位。模块的参考代码(waterled_top.v)如下所示: + +```verilog +module waterled_top( + input sysclk, //27MHz system clock + input rstn, //active low reset + output [7:0] led + ); + parameter CNT_MAX = 32'd13_499_999; + reg [7:0] led_reg; + reg [31:0] cnt; + //cnt 当cnt == CNT_MAX时变为0,计数0.5秒 + always @(posedge sysclk) begin + if (!rstn) + cnt <= 0; + else if (cnt < CNT_MAX) + cnt <= cnt + 1; + else + cnt <= 0; + end + //led_reg 当cnt == CNT_MAX时,左移一位。 + always @(posedge sysclk) begin + if (!rstn) + led_reg <= 8'b0000_0001; + else if (led_reg == 8'b1000_0000 && cnt == CNT_MAX)//led7亮0.5s后重回led0 + led_reg <= 8'b0000_0001; + else if (cnt == CNT_MAX) //0.5s后左移 + led_reg <= led_reg << 1; + else + led_reg <= led_reg; + end + //led + assign led = led_reg; +endmodule +``` + +### 1.3.4仿真验证 + +为上述模块编写仿真模块,参考代码(waterled_top_tb.v)如下: + +```verilog +`timescale 1ns/1ns +module waterled_top_tb; + + reg sysclk; + reg rstn; + wire [7:0] led; + + // 实例化待测试模块 + waterled_top #( + .CNT_MAX(32'd100)//为了加快仿真速度,将模块内部CNT_MAX由13_499_999变为1000 + )uut ( + .sysclk(sysclk), + .rstn(rstn), + .led(led) + ); + // 产生系统时钟:周期约为 27Mhz + initial begin + sysclk = 0; + forever #(500/27) sysclk = ~sysclk; + end + // 初始化和复位过程 + initial begin + // 初始化 + rstn = 0; + #100; // 保持复位100ns + rstn = 1; // 释放复位 + end +endmodule +``` + +为了加速仿真,我们在仿真文件中另CNT_MAX的值为100。同时为了便于仿真,可以直接点击sim文件夹下hebav文件夹中的do.bat文件即可利用ModuleSim对模块进行仿真,仿真波形如下: + +
+
+ 无法显示图片时显示的文字 +
+ 图3.流水灯仿真波形(一) +
+
+ +
+
+ 无法显示图片时显示的文字 +
+ 图4.流水灯仿真波形(二) +
+
+ +从图3我们可以看到,端口信号led的值经过一定时间之后就进行了左移,并且在图4中我们也可以发现,当cnt的值等于CNT_MAX的时候led进行左移,与我们设计的目标相符合,可以进行下一步上板验证了。 + +### 1.3.5上板验证 + +仿真已经通过,可以进行上板验证,上板前要先进行管脚约束。端口与对应管脚如下表所示: +| 端口名称 |信号类型| 对应管脚|功能 +|:----:|:----:|:----:|:----:| +| sysclk | Input | | 时钟 | +| rstn | Input | | 复位 | +| led[0] | Output | | LED | +| led[1] | Output | | LED | +| led[2] | Output | | LED | +| led[3] | Output | | LED | +| led[4] | Output | | LED | +| led[5] | Output | | LED | +| led[6] | Output | | LED | +| led[7] | Output | | LED | + +管脚分配可以直接编写.fdc文件,也可以使用PDS内置的工具进行分配。 + +完成管脚分配之后就可以生成sbit文件,将文件提交到网站后点击烧录,即可将sbit下载到实验板中,在摄像头页面即可观察到流水灯的现象。 + +## 1.4 章末总结 + +本次实验主要学习使用左移(<<)和右移(>>)运算符实现移位,但实际应用中也可以使用位拼接({})进行更加复杂的移位操作,各位同学可以尝试学习。 \ No newline at end of file diff --git a/public/doc/02_key/images/1.png b/public/doc/02_key/images/1.png new file mode 100644 index 0000000..a791e5c Binary files /dev/null and b/public/doc/02_key/images/1.png differ diff --git a/public/doc/02_key/images/2.png b/public/doc/02_key/images/2.png new file mode 100644 index 0000000..a64ae7d Binary files /dev/null and b/public/doc/02_key/images/2.png differ diff --git a/public/doc/02_key/images/3.png b/public/doc/02_key/images/3.png new file mode 100644 index 0000000..ad95a9c Binary files /dev/null and b/public/doc/02_key/images/3.png differ diff --git a/public/doc/02_key/images/4.png b/public/doc/02_key/images/4.png new file mode 100644 index 0000000..e05eadb Binary files /dev/null and b/public/doc/02_key/images/4.png differ diff --git a/public/doc/02_key/images/5.png b/public/doc/02_key/images/5.png new file mode 100644 index 0000000..b4f6277 Binary files /dev/null and b/public/doc/02_key/images/5.png differ diff --git a/public/doc/02_key/images/6.png b/public/doc/02_key/images/6.png new file mode 100644 index 0000000..8dc484d Binary files /dev/null and b/public/doc/02_key/images/6.png differ diff --git a/public/doc/02_key/images/7.png b/public/doc/02_key/images/7.png new file mode 100644 index 0000000..31674a7 Binary files /dev/null and b/public/doc/02_key/images/7.png differ diff --git a/public/doc/02_key/key.md b/public/doc/02_key/key.md new file mode 100644 index 0000000..4b55af9 --- /dev/null +++ b/public/doc/02_key/key.md @@ -0,0 +1,258 @@ +# 基础-2-按键检测与消抖 + +## 2.1 章节导读 + +在数字电路中,按键是最常用的人机交互输入方式。然而,机械式按键在按下或释放过程中会产生抖动信号,直接读取会引起误触发。本章我们将实现一个可靠的按键检测模块,完成信号的消抖和下降沿检测,以便为更复杂的模块如状态机切换、模式转换等提供稳定的触发信号。 + +## 2.2 理论学习 + +由于机械结构的限制,按键在触发的一瞬间,其接触点会发生数次抖动,导致输出信号在0和1之间反复跳变。这种现象称为“抖动”。为避免系统错误响应,需要对按键信号进行“消抖”处理。 + +常见的软件消抖方法包括定时器延时,而在软件中通常使用计数器。在本实验中,采用对输入信号进行采样判断,当其状态发生变化时开始计数,若持续稳定一定时长后,才认为按键真正改变。 + +在此基础上,若需检测按键的“按下事件”,则还需进一步提取其上升沿(或下降沿)作为一个单周期的“有效触发”信号。 + +## 2.3 实战演练 + +### 2.3.1 实验目标 + +实现一个具有消抖功能的按键检测模块,并进一步提取其下降沿触发信号,输出一个单时钟周期宽度的 `btn_flag` 信号,用于后级逻辑判断。同时为了使实验现象更加明显,设置8位的IO输出连接led,当检测到 `btn_flag` 信号后8位信号`led`会自加1。 + +### 2.3.2 硬件资源 + +本实验使用试验箱上普通按键输入资源,输入信号经过电平转换后进入 FPGA 芯片,输出信号可连接状态指示灯以观察效果。 + +根据原理图可知实验板的按键按下是低电平,不按为高电平。 + +
+
+ 无法显示图片时显示的文字 +
+ 图1.实验板的按键资源 +
+
+
+
+ 实验板按键原理图 +
+ 图2.实验板按键原理图 +
+
+ +
+
+ 数字孪生 +
+ 图3.远程实验界面按键 +
+
+ +### 2.3.3 程序设计 + +为了实现稳定的按键检测逻辑,设计流程如下: + +1. 对输入 `btn` 进行采样,形成 `btn_temp`; +2. 若检测到 `btn_temp` 与当前 `btn` 状态不一致,则开始计数; +3. 若计数器 `cnt` 达到设定阈值(如255),则认为按键状态稳定,更新 `btn_ggle`; +4. 实验板的按键按下是低电平,不按为高电平。所以对 `btn_ggle` 打两拍形成 `btn_flag_d0` 和 `btn_flag_d1`,再判断其下降沿,输出一个时钟周期的`btn_flag`; +5. 检测到信号`btn_flag`后,信号`led <= led + 1`。 + +该模块的参考代码如下(`btn_ggle.v`): + +```verilog +module btn_ggle( + input wire clk, + input wire rstn, + input wire btn, + output wire btn_flag, + output reg [7:0] led +); +reg btn_ggle; +reg btn_flag_d0,btn_flag_d1; +reg [7:0] cnt; +reg btn_temp; +//检测按键状态 +always @(posedge clk) btn_temp <= btn; +//按键状态改变时开始计数 +always @(posedge clk) begin + if(~rstn) cnt <= 0; + else if(btn_temp != btn) cnt <= 1; + else if(cnt != 0) cnt <= cnt + 1; + else cnt <= 0; +end +//计数到255时认为按键值稳定 +always @(posedge clk) begin + if(~rstn) btn_ggle <= btn; + else if(cnt == 8'hFF) btn_ggle <= btn_temp; + else btn_ggle <= btn_ggle; +end +//对btn_ggle信号延迟打拍 +always @(posedge clk) begin + if(~rstn) begin + btn_flag_d0 <= 0; + btn_flag_d1 <= 0; + end + else begin + btn_flag_d0 <= btn_ggle; + btn_flag_d1 <= btn_flag_d0; + end +end +//btn_flag检测btn_ggle的下降沿 +assign btn_flag = ~btn_flag_d0 && btn_flag_d1; +//检测到按键按下的标志位(btn_flag),led会加1 +always @(posedge clk) begin + if(~rstn) led <= 0; + else if(btn_flag) led <= led + 1; + else led <= led; +end +endmodule +``` + +### 2.3.4 仿真验证 + +为验证功能的正确性,设计测试平台(`btn_ggle_tb.v`),代码如下: + +```verilog +`timescale 1ns/1ns +module btn_ggle_tb; + +reg clk; +reg rstn; +reg btn; +wire btn_flag; +wire [7:0] led; +btn_ggle btn_ggle_inst ( + .clk(clk), + .rstn(rstn), + .btn(btn), + .btn_flag(btn_flag), + .led(led) +); + +// 27MHz 时钟周期约为 37.037ns,取37ns近似 +always #(500/27) clk = ~clk; // 半周期18.5ns ≈ 27MHz + +initial begin + // 初始化 + clk = 0; + rstn = 0; + btn = 1; // 按键默认未按下,高电平有效 + + // 释放复位 + #200; + rstn = 1; + + // 模拟带抖动的按下过程 + #1000 btn = 0; + #100 btn = 1; // 抖动 + #100 btn = 0; + #100 btn = 1; + #100 btn = 0; + // 稳定按下 + #100000 btn = 0; + + // 模拟抖动松开过程 + #300000 btn = 1; + #100 btn = 0; + #100 btn = 1; + #100 btn = 0; + #100 btn = 1; + // 稳定松开 + #100000 btn = 1; + + // 第二次按下 + #300000 btn = 0; + #100000 btn = 0; + + #300000 $finish; +end + +endmodule +``` + +利用ModuleSim进行仿真,部分仿真波形如下图所示: + +
+
+ 仿真波形(一) +
+ 图4.仿真波形(一) +
+
+ +
+
+ 仿真波形(二) +
+ 图5.仿真波形(二) +
+
+
+
+ 仿真波形(三) +
+ 图6.仿真波形(三) +
+
+ +从仿真波形二和三中,我们可以看到,当我们模拟按键按下(1 ----> 0),当按键抖动(`btn`在0和1之间来回跳转)时,`cnt`的值会变回1重新开始计数,直到按键稳定按下(`btn`的值稳定不变,为0),`cnt`稳定增加,当`cnt`的值增加到`8‘hFF`时,认为按键按下,`btn_ggle`存储此时的按键状态,同时`btn_flag`检测到下降沿,拉高一个时钟周期。`led`信号也加一。 + + +
+
+ 仿真波形(四) +
+ 图7.仿真波形(四) +
+
+
+
+ 仿真波形(五) +
+ 图8.仿真波形(五) +
+
+ + +从波形三和四中,我们可以看到,当模拟按键抬起时(0 ----> 1),按键的抖动也会使`cnt`重新计数,直到稳定,`cnt`计数到`8’hFF`时,更新`btn_ggle`,由于按键是抬起,`btn_flag`不变,`led`不变。 + +### 2.3.5 上板验证 + +完成仿真后,可进行上板验证。端口连接如下表所示: + +| 端口名称 | 类型 | 管脚 |说明 | +| -------- | ------ | ------ | ---------- | +| clk | Input | | 27MHz 时钟 | +| rstn | Input | | 低电平复位 | +| btn | Input | | 外部按钮 | +| btn_flag | Output | | 上升沿标志 | +| led[0] | Output | | 驱动led | +| led[1] | Output | | 驱动led | +| led[2] | Output | | 驱动led | +| led[3] | Output | | 驱动led | +| led[4] | Output | | 驱动led | +| led[5] | Output | | 驱动led | +| led[6] | Output | | 驱动led | +| led[7] | Output | | 驱动led | + +将`.sbit`文件上传至平台,并下载到实验板,多次按下按键,观察led灯跳转,如果按下1次按键led只跳转一次,那么说明达成实验目标。 + +## 2.4 章末总结 + +本实验通过一个典型的按键检测例子,介绍了数字系统中常用的消抖和边沿检测方法,掌握了如何利用计数器和触发器组合进行抖动抑制与事件捕捉。在更复杂的设计中,这类基础模块可作为控制逻辑的可靠触发信号源,具有广泛应用价值。 \ No newline at end of file diff --git a/server/src/H264Encoder.cs b/server/src/H264Encoder.cs new file mode 100644 index 0000000..e69de29 diff --git a/server/src/H264MediaSource.cs b/server/src/H264MediaSource.cs new file mode 100644 index 0000000..e69de29 diff --git a/server/src/VideoStreamService.cs b/server/src/VideoStreamService.cs new file mode 100644 index 0000000..e69de29 diff --git a/src/views/ProjectView.vue b/src/views/ProjectView.vue index 204aee0..6dc81c4 100644 --- a/src/views/ProjectView.vue +++ b/src/views/ProjectView.vue @@ -53,159 +53,16 @@ const showDocPanel = ref(false); const documentContent = ref(''); // 切换文档面板和属性面板 -function toggleDocPanel() { +async function toggleDocPanel() { showDocPanel.value = !showDocPanel.value; // 如果切换到文档面板,则获取文档内容 if (showDocPanel.value) { - fetchDocumentation(); + const response = await fetch("/public/doc/01_water_led/water_led.md"); + documentContent.value = await response.text(); } } -// 模拟获取文档的函数 -function fetchDocumentation() { - // 这里模拟API请求,返回固定的Markdown内容 - const mockDocContent = ` -# FPGA WebLab 用户指南 - -## 简介 - -FPGA WebLab是一个基于Web的FPGA设计和实验平台,允许用户在浏览器中进行FPGA设计、仿真和验证。该平台提供了丰富的组件库和直观的界面,使FPGA学习和设计变得简单高效。 - -## 功能特点 - -- **可视化设计**:拖拽式界面,无需编写底层代码 -- **组件库**:包含多种常用FPGA组件 -- **实时验证**:设计完成后可立即进行验证和测试 -- **远程编程**:支持远程将设计烧录到物理FPGA设备 -- **协作功能**:支持多人同时在线编辑和查看 - -## 快速入门 - -### 创建项目 - -1. 点击主界面的"新建项目"按钮 -2. 输入项目名称和描述 -3. 选择目标FPGA设备型号 -4. 点击"创建"完成项目初始化 - -### 添加组件 - -1. 在左侧组件库中找到需要的组件 -2. 将组件拖拽到设计区域 -3. 通过右侧属性面板配置组件参数 - -### 连接组件 - -1. 点击一个组件的输出引脚 -2. 拖动连线到目标组件的输入引脚 -3. 松开鼠标完成连接 -4. 连线会自动显示信号名称和类型 - -### 验证设计 - -1. 点击工具栏中的"验证"按钮 -2. 系统会自动检查设计中的错误和警告 -3. 如有问题,可查看错误日志进行修复 - -### 模拟仿真 - -1. 点击"仿真"按钮进入仿真模式 -2. 设置输入信号和仿真参数 -3. 运行仿真并查看波形输出 -4. 可通过时间轴查看不同时刻的信号状态 - -### 烧录到设备 - -1. 确保FPGA设备已连接 -2. 点击"合成"按钮生成比特流文件 -3. 点击"烧录"将设计下载到物理设备 -4. 查看烧录日志确认操作成功 - -## 组件说明 - -### 基础逻辑组件 - -- **AND/OR/XOR门**:基本逻辑门,可设置输入数量 -- **MUX多路复用器**:数据选择器,根据选择信号输出不同输入 -- **触发器/寄存器**:存储单元,可选D、T、JK等不同类型 -- **计数器**:可配置位宽、计数方向等参数 - -### 接口组件 - -- **按钮/开关**:用户输入控制元件 -- **LED指示灯**:显示数字输出状态 -- **七段数码管**:显示数字信息 -- **UART接口**:串行通信接口 - -### 高级组件 - -- **RAM/ROM**:存储模块,可配置数据位宽和深度 -- **PLL/DCM**:时钟控制模块 -- **DSP模块**:数字信号处理单元 -- **MCU集成**:可嵌入微控制器核心 - -## 常见问题 - -### 设计无法编译 - -检查以下可能的原因: -- 组件之间连线不完整 -- 组件参数设置不正确 -- 存在时序冲突 -- 资源使用超出目标设备限制 - -### 模拟结果与预期不符 - -可能的解决方法: -- 检查输入激励是否正确 -- 验证时钟设置和复位信号 -- 调整仿真时间步长 -- 查看信号完整传播路径 - -### 设备烧录失败 - -常见原因及解决方法: -- 检查USB连接和驱动安装 -- 确认选择了正确的设备型号 -- 验证生成的比特流文件是否有效 -- 重新安装FPGA开发工具 - -## 高级技巧 - -### 层次化设计 - -对于复杂项目,建议按功能模块划分设计层次,创建子模块后再进行顶层连接。 - -### 自定义组件 - -可以将常用电路打包为自定义组件,方便在不同项目中重复使用。 - -### 版本控制 - -定期保存设计快照,利用版本历史功能跟踪设计变更。 - -### 性能优化 - -- 减少关键路径上的组件数量 -- 优化时钟树结构 -- 合理布局减小互连延迟 -- 使用流水线结构提高吞吐量 - -## 联系我们 - -如有任何问题或建议,请通过以下方式联系我们: -- 邮箱:support@fpgaweblab.com -- 论坛:forum.fpgaweblab.com -- 微信公众号:FPGA_WebLab - -感谢您使用FPGA WebLab! -`; - - // 更新文档内容 - documentContent.value = mockDocContent; -} - // --- 元器件管理 --- const showComponentsMenu = ref(false); const diagramData = ref({