基于 FPGA 的高级数字电路设计(1)VGA 彩色条显示设计(480 P)

这篇文章详细介绍了如何使用Verilog设计一个模块来控制VGA输出,包括像素时钟、复位、HS和VS信号,以及RGB输出。核心部分展示了横纵同步计数器、活动区域位置计算以及颜色条的生成逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

module VGA(
    input         clk, // pixel clock
    input         rst_n,
    output        hs,
    output        vs,
    output        de,
    output [23:0] RGB
);

// 640x480 25.175Mhz

parameter H_ACTIVE = 16'd640;
parameter H_FP     = 16'd16 ;
parameter H_SYNC   = 16'd96 ;
parameter H_BP     = 16'd48 ;
parameter V_ACTIVE = 16'd480;
parameter V_FP     = 16'd10 ;
parameter V_SYNC   = 16'd2  ;
parameter V_BP     = 16'd33 ;
parameter HS_POL   = 1'b0   ;
parameter VS_POL   = 1'b0   ;

parameter H_TOTAL = H_ACTIVE + H_FP + H_SYNC + H_BP; // horizontal total time (pixels)
parameter V_TOTAL = V_ACTIVE + V_FP + V_SYNC + V_BP; // vertical total time (lines)

reg hs_reg;                      // horizontal sync register
reg vs_reg;                      // vertical sync register
reg hs_reg_d0;                   // delay 1 clock of 'hs_reg'
reg vs_reg_d0;                   // delay 1 clock of 'vs_reg'
reg [11:0] h_cnt;                // horizontal counter
reg [11:0] v_cnt;                // vertical counter
reg [11:0] active_x;             // video x position
reg [11:0] active_y;             // video y position
reg [23:0] rgb_reg;              // output color bar
reg h_active;                    // horizontal video active
reg v_active;                    // vertical video active
wire video_active;               // video active(horizontal active and vertical active)
reg video_active_d0;             // delay 1 clock of video_active
assign hs = hs_reg_d0;
assign vs = vs_reg_d0;
assign video_active = h_active & v_active;
assign de = video_active_d0;
assign RGB = rgb_reg;

always@(posedge clk or negedge rst_n) begin
    if(!rst_n)
        begin
            hs_reg_d0 <= 1'b0;
            vs_reg_d0 <= 1'b0;
            video_active_d0 <= 1'b0;
        end
    else
        begin
            hs_reg_d0 <= hs_reg;
            vs_reg_d0 <= vs_reg;
            video_active_d0 <= video_active;
        end
end

always@(posedge clk or negedge rst_n) begin
    if(!rst_n)
        h_cnt <= 12'd0;
    else if(h_cnt == H_TOTAL - 1) // horizontal counter maximum value
        h_cnt <= 12'd0;
    else
        h_cnt <= h_cnt + 12'd1;
end

always@(posedge clk or negedge rst_n) begin
    if(!rst_n)
        active_x <= 12'd0;
    else if(h_cnt >= H_FP + H_SYNC + H_BP - 1) // horizontal video active
        active_x <= h_cnt - (H_FP[11:0] + H_SYNC[11:0] + H_BP[11:0] - 12'd1);
    else
        active_x <= active_x;
end

always@(posedge clk or negedge rst_n) begin
    if(!rst_n)
        v_cnt <= 12'd0;
    else if(h_cnt == H_FP  - 1) // horizontal sync time
        if(v_cnt == V_TOTAL - 1) // vertical counter maximum value
            v_cnt <= 12'd0;
        else
            v_cnt <= v_cnt + 12'd1;
    else
        v_cnt <= v_cnt;
end

always@(posedge clk or negedge rst_n) begin
    if(!rst_n)
        hs_reg <= 1'b0;
    else if(h_cnt == H_FP - 1) // horizontal sync begin
        hs_reg <= HS_POL;
    else if(h_cnt == H_FP + H_SYNC - 1) // horizontal sync end
        hs_reg <= ~hs_reg;
    else
        hs_reg <= hs_reg;
end

always@(posedge clk or negedge rst_n) begin
    if(!rst_n)
        h_active <= 1'b0;
    else if(h_cnt == H_FP + H_SYNC + H_BP - 1) // horizontal active begin
        h_active <= 1'b1;
    else if(h_cnt == H_TOTAL - 1) // horizontal active end
        h_active <= 1'b0;
    else
        h_active <= h_active;
end

always@(posedge clk or negedge rst_n) begin
    if(!rst_n)
        vs_reg <= 1'd0;
    else if((v_cnt == V_FP - 1) && (h_cnt == H_FP - 1)) // vertical sync begin
        vs_reg <= HS_POL;
    else if((v_cnt == V_FP + V_SYNC - 1) && (h_cnt == H_FP - 1)) // vertical sync end
        vs_reg <= ~vs_reg;  
    else
        vs_reg <= vs_reg;
end

always@(posedge clk or negedge rst_n) begin
    if(!rst_n)
        v_active <= 1'd0;
    else if((v_cnt == V_FP + V_SYNC + V_BP - 1) && (h_cnt == H_FP - 1)) // vertical active begin
        v_active <= 1'b1;
    else if((v_cnt == V_TOTAL - 1) && (h_cnt == H_FP - 1)) // vertical active end
        v_active <= 1'b0;
    else
        v_active <= v_active;
end

always@(posedge clk or negedge rst_n) begin
    if(!rst_n)
        rgb_reg <= 24'h000;
    else if(video_active) begin
        if(active_x == 12'd0)
            rgb_reg <= 24'hF00;
        else if(active_x == 12'd120)
            rgb_reg <= 24'h0F0;
        else if(active_x == 12'd240)
            rgb_reg <= 24'h00F;
        else if(active_x == 12'd360)
            rgb_reg <= 24'h0F0;
        else if(active_x == 12'd410)
            rgb_reg <= 24'hF00;
        else
            rgb_reg <= rgb_reg;
    end
    else
        rgb_reg <= 24'h000;
end

endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

新芯设计

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值