基于FPGA的VGA协议实现----条纹-文字-图片

news2024/11/19 15:38:00

基于FPGA的VGA协议实现----条纹-文字-图片

引言:

​ 随着数字电子技术的飞速发展,现场可编程门阵列(FPGA)因其高度的灵活性和并行处理能力,在数字系统设计中扮演着越来越重要的角色。FPGA能够实现复杂的数字逻辑,并且可以快速地进行原型开发和测试,这使得它成为教育和工业应用中的理想选择。

·

VGA(Video Graphics Array)是一种视频传输标准,广泛应用于个人计算机显示器、电视和视频投影仪等设备中。VGA协议的实现涉及到同步信号的生成、时序控制以及像素数据的传输,是数字视频处理领域的基础技术之一。

·

本实验旨在探索如何利用FPGA实现VGA协议,并在VGA显示器上展示动态内容。通过本实验,参与者将学习到FPGA编程基础、VGA接口原理以及如何设计和实现数字视频信号的生成。实验内容涵盖了从简单的条纹图案显示到复杂的文字和图片显示,逐步引导学习者深入理解数字视频信号的生成和处理过程。

·

希望你在本次学习过后,能够有一定的收获!!!

​ 冲啊!!!! ٩(͡๏̯͡๏)۶ ٩(͡๏̯͡๏)۶ ٩(͡๏̯͡๏)۶

文章目录

  • 基于FPGA的VGA协议实现----条纹-文字-图片
    • 一、任务介绍
    • 二、VGA分析
      • 1.VGA原理分析
      • 2.VGA接口分析
      • 3.VGA时序标准介绍
      • 4.VGA 显示模式及相关参数
    • 三、实验过程
      • 1.添加PLL
      • 2.字模提取
      • 3.图片转化
      • 4.添加ROM
      • 5.引脚配置图
    • 四、相关代码
      • top.v
      • key_debounce.v
      • data_drive.v
      • vga_driver.v
    • 五、效果展示
      • 按键实现-动态条纹-文字-图片
    • 六、总结

一、任务介绍

  1. 深入了解VGA协议
  2. 理解不同显示模式下的VGA控制时序参数
  3. 完成在VGA上显示对应的条纹-文字-图片

二、VGA分析

1.VGA原理分析

​ VGA 显示器显示图像,并不是直接让图像在显示器上显示出来,而是采用扫描的方式,将构成图像的像素点,在行同步信号和场同步信号的同步下,按照从上到下、由左到右的顺序扫描到显示屏上。VGA 显示器扫描方式,具体见图 1 。

在这里插入图片描述

图 1 VGA显示器扫描方式

结合 VGA 显示器扫描方式示意图,我们简要说明一下 VGA 显示器的扫描规律。

(1) 在行、场同步信号的同步作用下,扫描坐标定位到左上角第一个像素点坐标;
(2) 自左上角 ( 第一行 ) 第一个像素点坐标,逐个像素点向右扫描 ( 图中第一个水平方向箭头) ;
(3) 扫描到第一行最后一个数据,一行图像扫描完成,进行图像消隐,扫描坐标自第一行行尾转移到第二行行首( 图中第一条虚线 ) ;
(4) 重复若干次扫描至最后一行行尾,一帧图像扫描完成,进行图像消隐,扫描坐标跳转回到左上角第一行行首( 图中对角线箭头 ) ,开始下一帧图像的扫描。

​ 在扫描的过程中会对每一个像素点进行单独赋值,使每个像素点显示对应色彩信息,当一帧图像扫描结束后,开始下一帧图像的扫描,循环往复,当扫描速度足够快,加之人眼的视觉暂留特性,我们会看到一幅完整的图片,而不是一个个闪烁的像素点。这就是VGA 显示的原理。

2.VGA接口分析

​ VGA(Video Graphics Array),是模拟信号,只能传输视频信号。接口共有15针,分成3排,每排5个孔,是显卡上应用最为广泛的接口类型,绝大多数显卡都带有此种接口。它传输红、绿、蓝模拟信号以及同步信号(水平和垂直信号)。

VGA接口定义

15个针脚的名称和描述如下:

img

其对应的接口定义如下:

img

3.VGA时序标准介绍

为了适应匹配不同厂家的 VGA 显示器, VGA 视频传输接口有自己的一套 VGA 时序标准,只有遵循 VGA 的时序标准,才能正确的进行图像信息的显示。在这里我们以 VESA VGA 时序标准为例,为大家讲解一下 VGA 时序标准,具体见图 2 。

img

图 2 VESA VGA时序标准图

​ 由 VESA VGA 时序标准图可知, VGA 时序由两部分构成,行同步时序与场同步时序,为了方便大家理解,我们将行同步时序与场同步时序分开讲解。
(1) 行同步时序,具体见图 3 。

img

图 3 行同步时序图

​ 图中 Video 代表传输的图像信息, HSync 表示行同步信号。 HSync 自上升沿起到下一个上升沿止为一个完整周期,我们称之为行扫描周期。
​ 一个完整的行扫描周期,包含 6 部分: Sync (同步)、 Back Porch (后沿)、 Left Border(左边框)、 “Addressable” Video (有效图像)、 Right Border (右边框)、 Front Porch(前沿),这 6 部分的基本单位是 pixel (像素),即一个像素时钟周期。在一个完整的行扫描周期中,Video 图像信息在 HSync 行同步信号的同步下完成一行图像的扫描显示,Video 图像信息只有在 “Addressable” Video (有效图像)阶段,图像信息有效,其他阶段图像信息无效。
​ HSync 行同步信号在 Sync (同步)阶段,维持高电平,其他阶段均保持低电平,在下一个行扫描周期的 Sync (同步)阶段, HSync 行扫描信号会再次拉高,其他阶段拉低,周而复始。
​ (2) 场同步时序,具体见图 4 。

img

图 4 场同步时序图

​ 理解了行同步时序,场同步时序就更容易理解了,两者相类似,如图 28-8 所示,图中Video 代表传输的图像信息, VSync 表示场同步信号, VSync 自上升沿起到下一个上升沿止为一个完整周期,我们称之为场扫描周期。
​ 一个完整的场扫描周期,也包含 6 部分: Sync (同步)、 Back Porch (后沿)、 Top Border(上边框)、 “Addressable” Video (有效图像)、 Bottom Border (底边框)、 Front Porch(前沿),与行同步信号不同的是,这 6 部分的基本单位是 line (行),即一个完整的行扫描周期。
​ 在一个完整的场扫描周期中,Video 图像信息在 HSync (行同步信号)和 VSync (场同步信号)的共同作用下完成一帧图像的显示,Video 图像信息只有在 “Addressable” Video(有效图像)阶段,图像信息有效,其他阶段图像信息无效。VSync 行同步信号在 Sync (同步)阶段,维持高电平,其他阶段均保持低电平,完成一个场扫描周期后,进入下一帧图像的扫描。
​ 综上所述,将行同步时序图与场同步时序图结合起来就构成了 VGA 时序图,具体见图 5。

img

图 5 VGA时序图

​ 图中的红色区域表示在一个完整的行扫描周期中,Video 图像信息只在此区域有效,黄色区域表示在一个完整的场扫描周期中,Video 图像信息只在此区域有效,两者相交的橙色区域,就是 VGA 图像的最终显示区域。以上就是对 VGA 时序的讲解,请大家理解掌握。

4.VGA 显示模式及相关参数

​ 行同步时序可分为 6 个阶段,对于这 6 个阶段的参数是有严格定义的,参数配置不正确,VGA 不能正常显示。 VGA 显示器可支持多种分辨率,不同分辨率对应个阶段的参数是不同的,常用 VGA 分辨率时序参数,具体见图 6 。

img

图 6 VGA不同分辨率参数
下面我们以经典 VGA 显示模式 640x480@60 为例,为读者讲解一下 VGA 显示的相关参数。
(1) 显示模式: 640x480@60
640x480 是指 VGA 的分辨率, 640 是指有效显示图像每一行有 640 个像素点, 480 是
指每一帧图像有 480 行, 640 * 480 = 307200 ≈ 300000 ,每一帧图片包含约 30 万个像素点,之前某品牌手机广告上所说的 30 万像素指的就是这个; @60 是指 VGA 显示图像的刷新频率,60 就是指 VGA 显示器每秒刷新图像 60 次,即每秒钟需要显示 60 帧图像。
(2) 时钟 (MHz) : 25.175MHz
这是 VGA 显示的工作时钟,像素点扫描频率。
(3) 行同步信号时序 ( 像素 ) 、场同步信号时序 ( 行数 )
行同步信号时序分为 6 段, Sync (同步)、 Back Porch (后沿)、 Left Border (左边
框)、 “Addressable” Video (有效图像)、 Right Border (右边框)、 Front Porch (前沿),这 6 段构成一个行扫描周期,单位为像素时钟周期。
同步阶段,参数为 96,指在行时序的同步阶段,行同步信号需要保持 96 个像素时钟周期的高电平, 其他几个阶段与此相似。
场同步信号时序与其类似,只是单位不再是像素时钟周期,而是一个完整的行扫描周
期,在此不再赘述。
在这里,我们看回图 6,由图可知,即使 VGA 显示分辨率相同,但刷新频率不同的话,相关参数也存在差异,如 640x480@60 、 640x480@75 ,这两个显示模式虽然具有相同的分辨率,但是 640x480@75 的刷新频率更快,所以像素时钟更快,时序参数也有区别。
下面我们以显示模式 640x480@60 、 640x480@75 为例,学习一下时钟频率的计算方法。
行扫描周期 * 场扫描周期 * 刷新频率 = 时钟频率
640x480@60:
行扫描周期:800( 像素 ) ,场扫描周期: 525( 行扫描周期 ) 刷新频率: 60Hz
800 * 525 * 60 = 25,200,000 ≈ 25.175MHz (误差忽略不计)
640x480@75:
行扫描周期:840( 像素 ) 场扫描周期: 500( 行扫描周期 ) 刷新频率: 75Hz
840 * 500 * 75 = 31,500,000 = 31.5MHz
在计算时钟频率时,大家要谨记一点,要使用行扫描周期和场扫描周期的参数进行计算,不能使用有效图像的参数进行计算,虽然在有效图像外的其他阶段图像信息均无效,但图像无效阶段的扫描也花费了扫描时间。
以上就是对 VGA 显示标准中分辨率相关参数的讲解,在编写 VGA 驱动时,我们要根据 VGA 显示模式的不同调整相关参数,只有这样 VGA 图像才能正常显示。

三、实验过程

1.添加PLL

IP核里面找到ALTPLL

在这里插入图片描述

基础时钟选择50M

在这里插入图片描述

取消勾选输出使能

在这里插入图片描述

c0默认输出50M即可,c1分频到25M,如需其他时钟频率可以自己进行设置

在这里插入图片描述

在这里插入图片描述

勾选如下选项后finish

在这里插入图片描述

2.字模提取

在子模提取工具里面输入需要显示的字符并设置字符大小为 32 * 32,点阵大小为 32 * 32

在这里插入图片描述

然后点击文件-另存为,把图片保存为BMP图片

再点击文件-打开,把保存的BMP图片打开得到整体的字符

在这里插入图片描述

再点击选项按如下参数设置

在这里插入图片描述

最后点击生成字符并保存字符为文本文件

最后得到字符如下

把得到的字符在verilog里面使用即可

在这里插入图片描述

注意:char_line[0]这一行全赋值为0,也就是说增加了第一行0,其余不变

3.图片转化

原图:

在这里插入图片描述

使用工具BMP2MifV1.0把图片转为HEX文件

在转换图片之前需要先修改图片的格式,使用电脑自带的画图软件打开此图片

点击文件-另存为

注意:保存类型一定要选择为24位位图(.bmp;.dib),否则加载不成功

在这里插入图片描述

然后开始转换

在这里插入图片描述

选择输出图像格式RGB565 文件类型Hex

转换完成得到.hex,内容如图

在这里插入图片描述

4.添加ROM

由于图片数据太多需要使用ROM来存储数据

在这里插入图片描述

设置位宽度为16位,大小为图片大小400×400 = 160000

在这里插入图片描述

取消勾选下列选项

在这里插入图片描述

找到刚才生成的.hex文件

在这里插入图片描述

勾选以下选项后直接finsh即可

在这里插入图片描述

数据的读取和使用参考后面的代码部分

5.引脚配置图

在这里插入图片描述

四、相关代码

top.v

module top(
                input			wire						clk,
                input			wire						rst_n,
                input			wire		[ 2:0 ]		    key,
                output			wire						vga_clk,
                output			wire						h_sync,
                output			wire						v_sync,
                output			wire		[ 7:0 ]			rgb_r,
                output			wire		[ 7:0 ]			rgb_g,
                output			wire		[ 7:0 ]			rgb_b,
                output			reg		    [ 3:0 ]			led);

    reg			[ 27:0 ]			cnt			        ;
    wire		[ 11:0 ]		    addr_h              ;
    wire		[ 11:0 ]		    addr_v              ;
    wire		[ 23:0 ]			rgb_data			;
    wire		[ 2:0 ]			    key_flag			;
    wire		[ 2:0 ]			    key_value			;

    //vga模块
    vga_dirve u_vga_dirve(
        
    .clk      ( clk ),
    .rst_n    ( rst_n ),
    .rgb_data ( rgb_data ),
    .vga_clk  ( vga_clk ),
    .h_sync   ( h_sync ),
    .v_sync   ( v_sync ),
    .rgb_r    ( rgb_r ),
    .rgb_g    ( rgb_g ),
    .rgb_b    ( rgb_b ),
    .addr_h   ( addr_h ),
    .addr_v   ( addr_v )
    );

    //数据模块
    data_drive u_data_drive(
    .vga_clk ( vga_clk ),
    .rst_n   ( rst_n ),
    .addr_h  ( addr_h ),
    .addr_v  ( addr_v ),
    .key     ( {key_value[ 2 ] && key_flag[ 2 ], key_value[ 1 ] && key_flag[ 1 ], key_value[ 0 ] && key_flag[ 0 ] } ),
    .rgb_data  ( rgb_data )
    );


    //按键消抖
    key_debounce u_key_debounce0(
    .clk   ( vga_clk ),
    .rst_n ( rst_n ),
    .key   ( key[ 0 ] ),
    .flag  ( key_flag[ 0 ] ),
    .key_value  ( key_value[ 0 ] )
    );

    key_debounce u_key_debounce1(
    .clk   ( vga_clk ),
    .rst_n ( rst_n ),
    .key   ( key[ 1 ] ),
    .flag  ( key_flag[ 1 ] ),
    .key_value  ( key_value[ 1 ] )
    );

    key_debounce u_key_debounce2(
    .clk   ( vga_clk ),
    .rst_n ( rst_n ),
    .key   ( key[ 2 ] ),
    .flag  ( key_flag[ 2 ] ),
    .key_value  ( key_value[ 2 ] )
    );

    // led
    always @( posedge clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            cnt <= 0;
        end
        else if ( cnt == 50_000_000 - 1 ) begin
            cnt <= 0;
        end
        else begin
            cnt <= cnt + 1;
        end
    end
    always @( posedge clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            led <= 4'b0000;
        end
        else if ( cnt == 50_000_000 -1 )begin
            led <= ~led;
        end
        else begin
            led <= led;
        end
    end
endmodule // vga_top

key_debounce.v

module key_debounce(
    input 	wire	clk,
    input 	wire 	rst_n,
    input 	wire 	key,
    
    output 	reg 	flag,// 0抖动, 1抖动结束
    output 	reg	key_value//key抖动结束后的值
);
    
    parameter MAX_NUM = 20'd1_000_000;
    
    reg [19:0] delay_cnt;//1_000_000
    
    reg key_reg;//key上一次的值
    
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            key_reg <= 1;
            delay_cnt <= 0;
        end
        
        else begin
            key_reg <= key;
            //当key为1 key 为0 表示按下抖动,开始计时
            if(key_reg  != key  ) begin 
            delay_cnt <= MAX_NUM ;
            end
            else begin
                if(delay_cnt > 0)
                    delay_cnt <= delay_cnt -1;
                else
                    delay_cnt <= 0;
            end
        end
    end
    
    
    //当计时完成,获取key的值
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            flag <= 0;
            key_value <= 1;
        end
    
        else begin
            
            // 计时完成 处于稳定状态,进行赋值
            if(delay_cnt == 1) begin
                flag <= 1;
                key_value <= key;
            end
            else begin
                flag <= 0;
                key_value <= key_value;
            end
        end
    end
    
endmodule

data_drive.v

module data_drive (input			wire						vga_clk,
                input			wire						rst_n,
                input			wire		[ 11:0 ]		addr_h,
                input			wire		[ 11:0 ]		addr_v,
                input			wire		[ 2:0 ]		 key,
                output			reg		[ 23:0 ]				rgb_data);
    
   

    localparam orange = 24'd16750899;   // 11111100_11111111_00001000
    localparam yellow = 24'd16776960;   // 11111111_11111111_10000000
    localparam green  = 24'd65280;      // 00111111_11111111_00000000
    localparam blue   = 24'd255;        // 00000001_11111111_00000000
    localparam indigo = 24'd10027161;    // 01111100_10000000_00000000
    localparam purple = 24'd16738047;      // 00001111_11111111_00000000
    localparam white  = 24'd16777215;   // 11111111_11111111_11111111
    localparam black  = 24'd0;          // 00000000_00000000_00000000
    localparam red    = 24'd16711936;   // 11111111_11111111_11110000


    // 分辨率为 640*480 时行时序各个参数定义
    parameter       C_H_SYNC_PULSE      =   96  , 
                    C_H_BACK_PORCH      =   48  ,
                    C_H_ACTIVE_TIME     =   640 ,
                    C_H_FRONT_PORCH     =   16  ,
                    C_H_LINE_PERIOD     =   800 ;

    // 分辨率为 640*480 时场时序各个参数定义
    parameter       C_V_SYNC_PULSE      =   2   , 
                    C_V_BACK_PORCH      =   33  ,
                    C_V_ACTIVE_TIME     =   480 ,
                    C_V_FRONT_PORCH     =   10  ,
                    C_V_FRAME_PERIOD    =   525 ;
//


    reg [11:0]  x;
    reg [11:0]  y;

    reg turn_flag_x;
    reg turn_flag_y;

    
    //方块的长和宽
    parameter LENGTH1 = 200;
    parameter WIDTH1  = 200;
    
    reg frame_flag;             		//帧结束标志


    //帧结束标志
    always @(posedge vga_clk or negedge rst_n) begin
        if (!rst_n) begin
            frame_flag <= 1'b0;
        end
        else if ((addr_h == 23) && (addr_v == 23)) begin
            frame_flag <= 1'b1;
        end
        else begin
            frame_flag <= 1'b0;
        end
    end
    
    //变量y
    always @(posedge vga_clk or negedge rst_n) begin
        if (!rst_n) begin
            y <= 'd0;
        end
        else if ((turn_flag_y == 1'b0 && frame_flag == 1'b1 && (y == 480 - WIDTH1 - 1)) || (turn_flag_y == 1'b1 && frame_flag == 1'b1 && (y == 'd0)))begin
            y <= y;
        end
        else if (turn_flag_y == 1'b0 && frame_flag == 1'b1) begin
            y <= y + 1'b1;
        end
        else if (turn_flag_y == 1'b1 && frame_flag == 1'b1) begin
            y <= y - 1'b1;
        end
    end

    //位置变量y翻转标志
    always @(posedge vga_clk or negedge rst_n) begin
        if (!rst_n) begin
            turn_flag_y <= 1'b0;
        end
        else if ((y == 480 - WIDTH1 - 1) && frame_flag == 1'b1 && turn_flag_y == 1'b0) begin
            turn_flag_y <= 1'b1;
        end
        else if (y == 'd0 && frame_flag == 1'b1 && turn_flag_y == 1'b1) begin
            turn_flag_y <= 1'b0;
        end
    end

    //变量x
    always @(posedge vga_clk or negedge rst_n) begin
        if (!rst_n) begin
            x <= 'd0;
        end
        else if((turn_flag_x == 1'b0 && frame_flag == 1'b1 && x == (640 - LENGTH1 - 1'b1)) || (turn_flag_x == 1'b1 && frame_flag == 1'b1 && x == 'd0)) begin
            x <= x;
        end
        else if (turn_flag_x == 1'b0 && frame_flag == 1'b1) begin
            x <= x + 1'b1;
        end
        else if (turn_flag_x == 1'b1 && frame_flag == 1'b1) begin
            x <= x - 1'b1;
        end
    end

    //位置变量x翻转标志
    always @(posedge vga_clk or negedge rst_n) begin
        if (!rst_n) begin
            turn_flag_x <= 1'b0;
        end
        else if (turn_flag_x == 1'b0 && frame_flag == 1'b1 && x == 640 - LENGTH1 - 1'b1) begin
            turn_flag_x <= 1'b1;
        end
        else if (turn_flag_x == 1'b1 && frame_flag == 1'b1 && x == 'd0) begin
            turn_flag_x <= 1'b0;
        end
    end
//



    reg [ 447:0 ] char_line[ 64:0 ];
    localparam	states_1 = 1; // 彩条
    localparam	states_2 = 2; // 字符
    localparam	states_3 = 3; // 图片
    parameter	height = 400; // 图片高度
    parameter	width  = 400; // 图片宽度
    reg			[ 1:0 ]			states_current			; // 当前状态
    reg			[ 1:0 ]			states_next			    ; // 下个状态
    reg			[ 17:0 ]		rom_address				; // ROM地址
    wire			[ 23:0 ]		rom_data				; // 图片数据
    wire							flag_enable_out1			; // 文字有效区域
    wire							flag_enable_out2			; // 图片有效区域
    wire							flag_clear_rom_address		; // 地址清零
    wire							flag_begin_h			    ; // 图片显示行
    wire							flag_begin_v			    ; // 图片显示列
    //状态转移
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            states_current <= states_1;
        end
        else begin
            states_current <= states_next;
        end
    end
    //状态判断
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            states_next <= states_1;
        end
        else if ( key[ 0 ] ) begin
            states_next <= states_1;
        end
            else if ( key[ 1 ] ) begin
            states_next <= states_2;
            end
            else if ( key[ 2 ] ) begin
            states_next <= states_3;
            end
        else begin
            states_next <= states_next;
        end
    end
    //状态输出
    always @( * ) begin
        case ( states_current )
            states_1 : begin
                if ( addr_h == 0 ) begin
                    rgb_data = black;
                end
                 else if(addr_h >=  x && addr_h < x + LENGTH1 && addr_v >=  y && addr_v <  y + WIDTH1)
                    rgb_data = white;
                else if ( addr_h >0 && addr_h <81 ) begin
                    rgb_data = red;
                end
                else if ( addr_h >80 && addr_h <161 ) begin
                    rgb_data = orange;
                end
                else if ( addr_h >160 && addr_h <241 ) begin
                    rgb_data = yellow;
                end
                else if ( addr_h >240 && addr_h <321 ) begin
                    rgb_data = green;
                end
                else if ( addr_h >320 && addr_h <401 ) begin
                    rgb_data = blue;
                end
                else if ( addr_h >400 && addr_h <481 ) begin
                    rgb_data = indigo;
                end
                else if ( addr_h >480 && addr_h <561 ) begin
                    rgb_data = purple;
                end
                else if ( addr_h >560 && addr_h <641 ) begin
                    rgb_data = white;
                end
                else begin
                    rgb_data = black;
                end
                
            end
            states_2 : begin
                if ( flag_enable_out1 ) begin
                    rgb_data = char_line[ addr_v-208 ][ 532 - addr_h ]? white:black;
                end
                else begin
                    rgb_data = black;
                end
            end
            states_3 : begin
                if ( flag_enable_out2 ) begin
                    rgb_data = rom_data;
                end
                else begin
                    rgb_data = black;
                end
                
            end
            default: begin
                case ( addr_h )
                    0 : rgb_data      = black;
                    1 : rgb_data      = red;
                    81 : rgb_data     = orange;
                    161: rgb_data     = yellow;
                    241: rgb_data     = green;
                    321: rgb_data     = blue;
                    401: rgb_data     = indigo;
                    481: rgb_data     = purple;
                    561: rgb_data     = white;
                    default: rgb_data = rgb_data;
                endcase
            end
        endcase
    end
    assign flag_enable_out1 = states_current == states_2 && addr_h > 80 && addr_h < 80+448+1 && addr_v > 208  && addr_v < 273 ;
    assign flag_begin_h     = addr_h > ( ( 640 - width ) / 2 ) && addr_h < ( ( 640 - width ) / 2 ) + width + 1;
    assign flag_begin_v     = addr_v > ( ( 480 - height )/2 ) && addr_v <( ( 480 - height )/2 ) + height + 1;
    assign flag_enable_out2 = states_current == states_3 && flag_begin_h && flag_begin_v;
    //ROM地址计数器
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            rom_address <= 0;
        end
        else if ( flag_clear_rom_address  ||  key[ 2 ] ) begin //计数满清零
            rom_address <= 0;
        end
            else if ( flag_enable_out2 ) begin  //在有效区域内+1
            rom_address <= rom_address + 1;
            end
        else begin  //无效区域保持
            rom_address <= rom_address;
        end
    end
    assign flag_clear_rom_address = rom_address == height * width - 1;
    //初始化显示文字
    always@( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            char_line[0]  =  448'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
            char_line[1]  =  448'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
            char_line[2]  =  448'h0000000000010000000000000000000000000000004000000000000000002000000000000001020000000100000000000000000000000000;
            char_line[3]  =  448'h0000018000038000000000200000002000000000007060000000000000001800000000000001C38000018180000000000000000000000000;
            char_line[4]  =  448'h00000FC00007C0001FFFFFF01FFFFFF0000000000060E0000000004000001800000000000001830000038300000000000000000000000000;
            char_line[5]  =  448'h0103FE00000C300000000300000003000000000000E0C0000FFFFFE000201830000000002041831800030300000000000000000000000000;
            char_line[6]  =  448'h01FC000000300E0000008300000083000000000000C0C00000018000013FFFF8000000001FFFFFFC00820300000000000000000000000000;
            char_line[7]  =  448'h0180000000E013F800FFC30000FFC3000000000000C18000000180003FB101000000000010C183001FE60200000000000000000000000000;
            char_line[8]  =  448'h0180C000033FF8F800C0C30000C0C3000000000001818018000180003130C1C00000000010C1830010C40608000000000000000000000000;
            char_line[9]  =  448'h0100E0001C01800000C0830000C08300000000000103FFFC00018000313081800000000010C1830010C437FC000000000000000000000000;
            char_line[10]  = 448'h0300C0000001820000C0830000C08300000000000303001800018000313081800000000010C1000010C86418000000000000000000000000;
            char_line[11]  = 448'h0300C00001FFFF0000C0830000C08300000000000386103000018000313081800000000010C0000010C86418000000000000000000000000;
            char_line[12]  = 448'h0300C00000218C0000FF830000FF83000000000007840C20000180003130A1900000000010C2010010D0C818000000000000000000000000;
            char_line[13]  = 448'h0300C0000031883000C0830000C08300000000000D8C084000018000313FFFF80000000010C201C010FF881801C0000001C0000001C00000;
            char_line[14]  = 448'h0300C0301FFFFFF80100031801000318000000000988080000018018313181800000000010C1038010D1901803F8000003F8000003F80000;
            char_line[15]  = 448'h07FFFFF800C004003FFFFFFC3FFFFFFC00000000119008007FFFFFFC313181C00000000010C1030010C11418040700180407001804070018;
            char_line[16]  = 448'h0200C00001C00C0000000100000001007FFE7FFE11818800000180003131C3C00000000010C1030010C202180801C0300801C0300801C030;
            char_line[17]  = 448'h0000C00003B81A0000000100000001000000000021838880000180003133B3C00000000010C0820010C2031810003C6010003C6010003C60;
            char_line[18]  = 448'h0000C000060E318000008100000081000000000001830840000180003133B3C00000000010C0860010C40318200007C0200007C0200007C0;
            char_line[19]  = 448'h0030C4000C06C07801FFC10001FFC1000000000001830820000180003F2297A0000000001FC0C60010CC6198000000000000000000000000;
            char_line[20]  = 448'h0038C200181300980180C1000180C100000000000186083000018000312685A00700000010C04C001FDF8198000000000000000000000000;
            char_line[21]  = 448'h0060C18067FC7FC0018081000180810000000000018608180001800030E48DB00F80000010C06C0010CC0118000000000000000000000000;
            char_line[22]  = 448'h00C0C0C000C80600018081000180810000000000018C081C00018000306C89900F8000001000380010800018000000000000000000000000;
            char_line[23]  = 448'h0180C0E00FFC06200180810001808100000000000188080C0001800000489198078000001000300010001018000000000000000000000000;
            char_line[24]  = 448'h0300C07000C9FFF001FF810001FF8100000000000190080C000180000050918C01800000200038001000E018000000000000000000000000;
            char_line[25]  = 448'h0600C03000CC86400180810001808100000000000190080C0001800000A0A188030000000000EE00000F0018000000000000000000000000;
            char_line[26]  = 448'h0C00C0300CD8466001808100018081000000000001A008000001800000A081800200000000018700003C0010000000000000000000000000;
            char_line[27]  = 448'h1010C03006D066C000000100000001000000000001800800000180000100818004000000000301E0001003F0000000000000000000000000;
            char_line[28]  = 448'h200FC00005FC268800003F0000003F00000000000180F800000180000200818018000000000C00FC00000070000000000000000000000000;
            char_line[29]  = 448'h0003C0003F07FFFC000007000000070000000000018038000001800002008180000000000070003000000060000000000000000000000000;
            char_line[30]  = 448'h0001000010000000000002000000020000000000010010000001000004010100000000000180000000000000000000000000000000000000;
            char_line[31]  = 448'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;

            char_line[32]  = 448'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
            
            char_line[33]  = 448'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
            char_line[34]  = 448'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
            char_line[35]  = 448'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
            char_line[36]  = 448'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
            char_line[37]  = 448'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
            char_line[38]  = 448'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
            char_line[39]  = 448'h03F007C007E0008003C007E0008007C003C0008003C000600000000000000000000000000000000000000000000000000000000000000000;
            char_line[40]  = 448'h0F38186008380180062008380180186006200180062000600000000000000000000000000000000000000000000000000000000000000000;
            char_line[41]  = 448'h1E3C303010181F800C3010181F8030300C301F800C3000E00000000000000000000000000000000000000000000000000000000000000000;
            char_line[42]  = 448'h1C3C3018200C01801818200C0180301818180180181800E00000000000000000000000000000000000000000000000000000000000000000;
            char_line[43]  = 448'h38183018200C01801818200C0180301818180180181801600000000000000000000000000000000000000000000000000000000000000000;
            char_line[44]  = 448'h38003018300C01801808300C0180301818080180180801600000000000000000000000000000000000000000000000000000000000000000;
            char_line[45]  = 448'h78000018300C0180300C300C01800018300C0180300C02600000000000000000000000000000000000000000000000000000000000000000;
            char_line[46]  = 448'h78000018000C0180300C000C01800018300C0180300C04600000000000000000000000000000000000000000000000000000000000000000;
            char_line[47]  = 448'h7FF0003000180180300C001801800030300C0180300C04600000000000000000000000000000000000000000000000000000000000000000;
            char_line[48]  = 448'h7FF8006000180180300C001801800060300C0180300C08600000000000000000000000000000000000000000000000000000000000000000;
            char_line[49]  = 448'h7C3C03C000300180300C0030018003C0300C0180300C08600000000000000000000000000000000000000000000000000000000000000000;
            char_line[50]  = 448'h781E007000600180300C006001800070300C0180300C10600000000000000000000000000000000000000000000000000000000000000000;
            char_line[51]  = 448'h781E001800C00180300C00C001800018300C0180300C30600000000000000000000000000000000000000000000000000000000000000000;
            char_line[52]  = 448'h781E000801800180300C018001800008300C0180300C20600000000000000000000000000000000000000000000000000000000000000000;
            char_line[53]  = 448'h781E000C03000180300C03000180000C300C0180300C40600000000000000000000000000000000000000000000000000000000000000000;
            char_line[54]  = 448'h781E000C02000180300C02000180000C300C0180300C7FFC0000000000000000000000000000000000000000000000000000000000000000;
            char_line[55]  = 448'h781E300C04040180180804040180300C18080180180800600000000000000000000000000000000000000000000000000000000000000000;
            char_line[56]  = 448'h381E300C08040180181808040180300C18180180181800600000000000000000000000000000000000000000000000000000000000000000;
            char_line[57]  = 448'h3C1C300810040180181810040180300818180180181800600000000000000000000000000000000000000000000000000000000000000000;
            char_line[58]  = 448'h1C1C3018200C01800C30200C018030180C3001800C3000600000000000000000000000000000000000000000000000000000000000000000;
            char_line[59]  = 448'h1F7818303FF803C006203FF803C01830062003C0062000600000000000000000000000000000000000000000000000000000000000000000;
            char_line[60]  = 448'h07F007C03FF81FF803C03FF81FF807C003C01FF803C003FC0000000000000000000000000000000000000000000000000000000000000000;
            char_line[61]  = 448'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
            char_line[62]  = 448'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
            char_line[63]  = 448'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
            char_line[64]  = 448'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
        end
    end
    
    //实例化ROM
    ROM1	ROM1_inst (
    .address ( rom_address ),
    .clock ( vga_clk ),
    .q ( rom_data )
    );
endmodule // data_drive

vga_driver.v

module vga_dirve (input			wire						clk,            //系统时钟
                input			wire						rst_n,          //复位
                input			wire		[ 23:0 ]		rgb_data,       //16位RGB对应值
                output			wire							vga_clk,    //vga时钟 25M
                output			reg							h_sync,     //行同步信号
                output			reg							v_sync,     //场同步信号
                output			reg		[ 11:0 ]				addr_h, //行地址
                output			reg		[ 11:0 ]				addr_v,  //列地址
                output			wire		[ 7:0 ]				rgb_r,  //红基色
                output			wire		[ 7:0 ]				rgb_g,  //绿基色
                output			wire		[ 7:0 ]				rgb_b  //蓝基色
);
    
    // 640 * 480 60HZ
    localparam	 H_FRONT = 16; // 行同步前沿信号周期长
    localparam	 H_SYNC  = 96; // 行同步信号周期长
    localparam	 H_BLACK = 48; // 行同步后沿信号周期长
    localparam	 H_ACT   = 640; // 行显示周期长
    localparam	 V_FRONT = 11; // 场同步前沿信号周期长
    localparam	 V_SYNC  = 2; // 场同步信号周期长
    localparam	 V_BLACK = 31; // 场同步后沿信号周期长
    localparam	 V_ACT   = 480; // 场显示周期长
    
    // 800 * 600 72HZ
    // localparam	 H_FRONT = 40; // 行同步前沿信号周期长
    // localparam	 H_SYNC  = 120; // 行同步信号周期长
    // localparam	 H_BLACK = 88; // 行同步后沿信号周期长
    // localparam	 H_ACT   = 800; // 行显示周期长
    // localparam	 V_FRONT = 37; // 场同步前沿信号周期长
    // localparam	 V_SYNC  = 6; // 场同步信号周期长
    // localparam	 V_BLACK = 23; // 场同步后沿信号周期长
    // localparam	 V_ACT   = 600; // 场显示周期长
    
    
    localparam	H_TOTAL = H_FRONT + H_SYNC + H_BLACK + H_ACT; // 行周期
    localparam	V_TOTAL = V_FRONT + V_SYNC + V_BLACK + V_ACT; // 列周期
    
    reg			[ 11:0 ]			cnt_h			; // 行计数器
    reg			[ 11:0 ]			cnt_v			; // 场计数器
    reg			[ 23:0 ]			rgb			; // 对应显示颜色值
    
    // 对应计数器开始、结束、计数信号
    wire							flag_enable_cnt_h			;
    wire							flag_clear_cnt_h			;
    wire							flag_enable_cnt_v			;
    wire							flag_clear_cnt_v			;
    wire							flag_add_cnt_v  			;
    wire							valid_area      			;
    
    
    // 25M时钟 行周期*场周期*刷新率 = 800 * 525* 60
    wire							clk_25			;
    // 50M时钟 1040 * 666 * 72
    wire							clk_50			;
    //
    pll	pll_inst (
        .areset ( ~rst_n ),
        .inclk0 ( clk ),
        .c0 ( clk_50 ), //50M
        .c1 ( clk_25 ), //25M
        );
    //根据不同分配率选择不同频率时钟
    assign vga_clk = clk_25;
    
    
    // 行计数
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            cnt_h <= 0;
        end
        else if ( flag_enable_cnt_h ) begin
            if ( flag_clear_cnt_h ) begin
                cnt_h <= 0;
            end
            else begin
                cnt_h <= cnt_h + 1;
            end
        end
        else begin
            cnt_h <= 0;
        end
    end
    assign flag_enable_cnt_h = 1;
    assign flag_clear_cnt_h  = cnt_h == H_TOTAL - 1;
    
    // 行同步信号
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            h_sync <= 0;
        end
        else if ( cnt_h == H_SYNC - 1 ) begin // 同步周期时为1
            h_sync <= 1;
        end
            else if ( flag_clear_cnt_h ) begin // 其余为0
            h_sync <= 0;
            end
        else begin
            h_sync <= h_sync;
        end
    end
    
    // 场计数
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            cnt_v <= 0;
        end
        else if ( flag_enable_cnt_v ) begin
            if ( flag_clear_cnt_v ) begin
                cnt_v <= 0;
            end
            else if ( flag_add_cnt_v ) begin
                cnt_v <= cnt_v + 1;
            end
            else begin
                cnt_v <= cnt_v;
            end
        end
        else begin
            cnt_v <= 0;
        end
    end
    assign flag_enable_cnt_v = flag_enable_cnt_h;
    assign flag_clear_cnt_v  = cnt_v == V_TOTAL - 1;
    assign flag_add_cnt_v    = flag_clear_cnt_h;
    
    // 场同步信号
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            v_sync <= 0;
        end
        else if ( cnt_v == V_SYNC - 1 ) begin
            v_sync <= 1;
        end
            else if ( flag_clear_cnt_v ) begin
            v_sync <= 0;
            end
        else begin
            v_sync <= v_sync;
        end
    end
    
    // 对应有效区域行地址 1-640
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            addr_h <= 0;
        end
        else if ( valid_area ) begin
            addr_h <= cnt_h - H_SYNC - H_BLACK + 1;
        end
        else begin
            addr_h <= 0;
        end
    end
    // 对应有效区域列地址 1-480
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            addr_v <= 0;
        end
        else if ( valid_area ) begin
            addr_v <= cnt_v -V_SYNC - V_BLACK + 1;
        end
        else begin
            addr_v <= 0;
        end
    end
    // 有效显示区域
    assign valid_area = cnt_h >= H_SYNC + H_BLACK && cnt_h <= H_SYNC + H_BLACK + H_ACT && cnt_v >= V_SYNC + V_BLACK && cnt_v <= V_SYNC + V_BLACK + V_ACT;


    // 显示颜色
    always @( posedge vga_clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            rgb <= 24'h0;
        end
        else if ( valid_area ) begin
            rgb <= rgb_data;
        end
        else begin
            rgb <= 24'b0;
        end
    end
    assign rgb_r = rgb[ 23:16 ];
    assign rgb_g = rgb[ 15:8 ];
    assign rgb_b = rgb[ 7:0 ];

endmodule // vga_dirve

五、效果展示

  1. 条纹显示现象
    • 初始状态下,VGA显示器上呈现了均匀分布的垂直彩色条纹。
  2. 方块移动现象
    • 在屏幕上,一个或多个彩色方块在特定路径上进行移动。
    • 方块的移动可以是水平的、垂直的,或者是按照特定的轨迹进行。
  3. 文字显示现象
    • 在屏幕的指定区域,显示了对应的名称-学号。
  4. 图片显示现象
    • 显示器上展示了一张静态图片。
  5. 动态效果现象
    • 实验中实现了方块的动态移动效果,方块在屏幕上的移动流畅,过渡自然。

按键实现-动态条纹-文字-图片

实验-按键-图片-名称-动态条纹

六、总结

通过本次基于FPGA的VGA协议实现实验,我们成功地在VGA显示器上展示了条纹、文字和图片,并且实现了方块的动态移动效果。以下是实验的详细总结:

技术掌握与应用

  1. VGA协议理解:实验加深了对VGA显示原理的理解,包括同步信号的生成、时序控制和像素数据的传输。
  2. FPGA编程实践:通过编写Verilog代码,实践了FPGA编程技巧,加深了对数字逻辑设计的认识。
  3. 时序控制:掌握了如何在FPGA中实现精确的时序控制,以满足VGA显示标准。

实验成果

  1. 条纹显示:成功实现了在VGA显示器上显示不同颜色的垂直条纹,验证了FPGA生成基本图形的能力。
  2. 方块移动:实现了方块在屏幕上的水平和垂直移动,展示了FPGA处理动态图形的能力。
  3. 文字显示:在屏幕上准确显示了预定义的文字信息,证明了FPGA在字符映射方面的应用。
  4. 图片展示:成功映射并显示了静态图片,展示了FPGA在处理较高层次图像数据方面的能力。

问题解决

  1. 调试技巧:在实验过程中,遇到了一些技术难题,如信号同步问题、时序配置错误等,通过逐步调试和参数调整,成功解决了这些问题。
  2. 代码优化:为了提高显示性能和降低资源消耗,对代码进行了优化,学习了如何编写高效且简洁的Verilog代码。

创新与扩展

  1. 功能扩展:在实验要求的基础上,尝试了更多功能,如不同形状和颜色的图形显示。
  2. 性能提升:通过调整时钟频率和优化时序参数,提高了系统的显示性能。

实验心得

  1. 学习曲线:实验初期遇到了一些困难,但随着实验的深入,逐渐掌握了关键技术点,体验了学习的乐趣。
  2. 团队合作:在实验过程中,与同伴进行了有效的沟通和协作,共同解决了遇到的问题。
  3. 知识应用:将课堂上学到的理论知识应用到实际中,加深了对数字电路设计的理解。

总体来说,本次实验不仅加深了对FPGA和VGA显示技术的理解,而且提高了解决实际问题的能力,为未来的学习和工作打下了坚实的基础。希望在未来的学习中能够继续探索和创新,不断提升自己的技术水平。



最后感谢大佬友情链接:

  • FPGA VGA显示协议-腾讯云开发者社区-腾讯云 (tencent.com)
  • 【接口时序】7、VGA接口原理与Verilog实现 - jgliu - 博客园 (cnblogs.com)
  • 基于FPGA的VGA显示彩条、字符、图片_基于fpga的vga显示设计-CSDN博客
  • 【FPGA入门】第八篇、FPGA驱动VGA实现动态图像移动_基于fpga调整vga显示屏的图像位置-CSDN博客
  • VGA显示原理、时序标准及相关参数_vga时序参数-CSDN博客

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

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

相关文章

Qt官方示例---embedded

digiflip flickable flightinfo lightmaps raycasting styleexample

pycharm 关闭项目卡死

PyCharm2023.3.4 关闭一直卡在 closing projects 解决办法&#xff1a; 打开PyCharm&#xff0c; 选择 Help -> Find Action -> 输入 Registry -> 禁用ide.await.scope.completion

leetCode-hot100-数组专题之双指针

数组双指针专题 1.同向双指针1.1例题26.删除有序数组中的重复项27.移除元素80.删除有序数组中的重复项 Ⅱ 2.相向双指针2.1例题11.盛最多水的容器42.接雨水581.最短无序连续子数组 双指针在算法题中很常见&#xff0c;下面总结双指针在数组中的一些应用&#xff0c;主要分为两类…

解决“Failed to restart udev.service“

报错信息 Failed to restart udev.service: Unit systemd-udevd.service is not loaded properly: Exec format error. See system logs and ‘systemctl status udev.service’ for details. invoke-rc.d: initscript udev, action “restart” failed. ● systemd-udevd.ser…

Day25:Leetcode:669. 修剪二叉搜索树 + 108.将有序数组转换为二叉搜索树 + 538.把二叉搜索树转换为累加树

LeetCode&#xff1a;669. 修剪二叉搜索树 问题描述 解决方案&#xff1a; 1.思路 2.代码实现 class Solution {public TreeNode trimBST(TreeNode root, int low, int high) {if (root null) {return null;}if (root.val < low) {return trimBST(root.right, low, hi…

跳房子游戏-第13届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第71讲。 跳房子游戏&#…

一.ffmpeg 将内存中的H264跟PCM 数据流合成多媒体文件

在有一些嵌入式平台中&#xff0c;H264数据流一般来自芯片内部的硬编码器&#xff0c; AAC音频数据则是通过采集PCM进行软编码&#xff0c;但是如何对它实时进行封装多媒体文件 &#xff0c;参考ffmpeg example&#xff0c;花了一些时间终于实现了该功能。 流程图如下&#xf…

什么是经典蓝牙模块?

什么是经典蓝牙模块&#xff1f;   前面我们已经就蓝牙模块的概念做了了解&#xff0c;随着时间的推移&#xff0c;产品越来越智能&#xff0c;需要的蓝牙模块也就越来越广泛&#xff0c;本篇文章我们就一起了解下什么是经典蓝牙模块。   经典蓝牙模块(BT)泛指支持蓝牙协议…

ClickHouse配置与使用

静态IP配置 # 修改网卡配置文件 vim /etc/sysconfig/network-scripts/ifcfg-ens33# 修改文件内容 TYPEEthernet PROXY_METHODnone BROWSER_ONLYno BOOTPROTOstatic IPADDR192.168.18.128 NETMASK255.255.255.0 GATEWAY192.168.18.2 DEFROUTEyes IPV4_FAILURE_FATALno IPV6INIT…

AI办公自动化-kimi批量在多个Excel工作表中绘制柱状图

工作任务和目标&#xff1a;批量在多个Excel工作表中生成一个柱状图 第一步&#xff0c;在kimi中输入如下提示词&#xff1a; 你是一个Python编程专家&#xff0c;完成下面任务的Python脚本&#xff1a; 打开文件夹&#xff1a;F:\aivideo 读取里面所有的xlsx文件&#xff1…

【云原生之】K8s 管理工具 kubectl 详解(二)

一、项目的生命周期 创建–>发布–>更新–>回滚–>删除 1.1、创建kubectl create命令 创建并运行一个或多个容器镜像。创建一个deployment 或job 来管理容器。 kubectl create --help kubectl -n 命名空间 create deployment 资源名称 --image镜像 --port容器的端…

useTransition:开启React并发模式

写在前面&#xff1a;并发 并发模式&#xff08;Concurrent Mode&#xff09;1的一个关键特性是渲染可中断。 React 18 之前&#xff0c;更新内容渲染的方式是通过一个单一的且不可中断的同步事务进行处理。同步渲染意味着&#xff0c;一旦开始渲染就无法中断&#xff0c;直到…

将某一个 DIV 块全屏展示

文章目录 需求分析 需求 上节我们研究了如何将页面中的指定 div 下载为图片&#xff1a;跳转查看 本节演技一下如何将 DIV 全屏展示 全屏展示某一个 DIV 分析 其实就是模拟键盘动作 F11 var element document.getElementById(pic) var requestMethod element.requestFullS…

Alinx xc7z020 原理图

时钟引脚 CLK&#xff1a;U18 复位 RST&#xff1a;N15 扩展接口 J10 J11 PL LED

实战:生成个性化词云的Python实践【7个案例】

文本挖掘与可视化&#xff1a;生成个性化词云的Python实践【7个案例】 词云&#xff08;Word Cloud&#xff09;&#xff0c;又称为文字云或标签云&#xff0c;是一种用于文本数据可视化的技术&#xff0c;通过不同大小、颜色和字体展示文本中单词的出现频率或重要性。在词云中…

CVPR2022医疗图像-GBCNet网络:胆囊癌(GBC)超声(USG)图像检测模型

Surpassing the Human Accuracy:Detecting Gallbladder Cancer from USG Images with Curriculum Learning&#xff1a;超越人类的准确性:基于课程学习的USG图像检测胆囊癌 目录 一、背景与意义 二、介绍 三、网络框架 3.1 区域选择网络 3.2 MS-SoP分类器 3.3 多尺度块 …

前端加载excel文件数据 XLSX插件的使用

npm i xlsx import axios from axios; axios //这里用自己封装的http是不行的&#xff0c;踩过坑.get(url,{ responseType: "arraybuffer" }).then((re) > {console.log(re)let res re.datavar XLSX require("xlsx");let wb XLSX.read(r…

20240523每日运维--------聊聊docker简介(一)

dotCloud 说Docker&#xff0c;必不可免不得不说dotCloud&#xff0c;Docker本来只是dotCloud公司的内部项目&#xff0c;其公司创始人 Solomon Hykes 发了一个内部项目&#xff0c;而这个项目就是Docker&#xff0c;自从2013年docker开源以后&#xff0c;在世界范围引起相当轰…

【设计模式】JAVA Design Patterns——Bridge(桥接模式)

&#x1f50d;目的 将抽象与其实现分离&#xff0c;以便二者可以独立变化。 &#x1f50d;解释 真实世界例子 考虑一下你拥有一种具有不同附魔的武器&#xff0c;并且应该允许将具有不同附魔的不同武器混合使用。 你会怎么做&#xff1f; 为每个附魔创建每种武器的多个副本&…