项目:串口接收—ram存储—TFT显示(完整设计)

该博客详细描述了一个FPGA系统如何通过UART串口接收RGB565像素数据,然后将其存储到内部RAM中,再根据TFT显示屏的控制器请求,从RAM读取数据并在显示屏上按指定区域显示。设计中包含了串口接收模块、数据写入RAM模块、从RAM读取数据模块以及TFT显示屏控制模块,同时考虑了显示屏的分辨率限制和数据传输延迟。
摘要由CSDN通过智能技术生成

目的:

1.使用uart串口接收模块接收待显示的串行数据(像素RGB值)。

2.把待显示的数据写入ram中。

3.从ram中读取像素值到TFT显示屏中显示,并对应输出该像素的坐标值。

注意:

1.遵循uart协议的一个数据位宽为8,一个RGB565像素值位宽为16,所以接收两个再存入RAM中的一个存储单元。

2.由显示屏控制器发出读取数据的请求信号,再从ram中读出数据,传输到显示屏显示,总共慢了两拍,因此请求信号应该提前两拍发出。

3.在读取ram模块中可以控制在显示屏中显示的区域。用参数划定区域,然后区域内读取ram值并输出显示,区域外不读数据,输出0(黑屏)。

4.由于每个fpga芯片上的ram存储资源是有限的,只能存储定量的像素值,所以如果显示屏的分辨率太高,只能显示一部分区域。

5.ram资源的查找方法:①看fpga芯片有几个块ram资源

            ②到手册上查看该芯片上每个ram的存储容量。

            ③两个值相乘即是最大容量。

6.把两位低位宽数据存储成一位高位宽数据,可以利用计数器的奇偶,或者取它的高位。如:

  

框图:

实现:把之前的模块进行连线,并增加写入模块和读出模块。(为了相互适配,旧模块在本次设计中代码有所调整)

`timescale 1ns /1ns
module uart_ram_TFT_send_tb(   );

    reg clk ;
    reg reset ;
    reg uart_tx ;
    wire [15:0]RGB565_data ;
    wire [15:0]vish_axis ;//显示的行坐标
    wire [15:0]visv_axis ;//显示的列坐标   
    reg [7:0] rand;
    reg [16:0]input_cnt ;
    uart_ram_TFT uart_ram_TFT_sim_send(//顶层连线
    clk,//50MHz
    reset,
    uart_tx ,
    RGB565_data,//输出的内容数据
    vish_axis ,//显示的行坐标
    visv_axis //显示的列坐标
    );
    
    initial clk = 1 ;
    always #10 clk = ! clk ;
    initial begin
    reset = 0 ;
    uart_tx = 1;
    input_cnt = 0 ;
    rand = 0 ;
    input_cnt = 0 ;
    #201 ;
    reset = 1 ;
    #800000;
    repeat(65536)begin
        #20 ;
        rand = {$random} % 255;
        #20 ;
        uart_input(rand);   
        input_cnt = input_cnt + 1 ;           
        end
    #1000 ;
    $stop ;
    end

    
    task uart_input ;//设定一个任务uart_inpt,有一个输入端uart_tx_data_stm 。在这个task里可以对task外的变量进行赋值
        input [7:0]uart_tx_data_stm ;//不返回值,所以不能用x=uart_input。而是直接uart_input。
        begin   //结构简单的begin-end
        uart_tx = 1 ;
        #20 ;
        uart_tx  = 0 ;
        #8640 ;
        uart_tx = uart_tx_data_stm[0] ;
        #8640 ;
        uart_tx = uart_tx_data_stm[1] ;
        #8640 ;
        uart_tx = uart_tx_data_stm[2] ;
        #8640 ;
        uart_tx = uart_tx_data_stm[3] ;
        #8640 ;
        uart_tx = uart_tx_data_stm[4] ;
        #8640 ;
        uart_tx = uart_tx_data_stm[5] ;
        #8640 ;
        uart_tx = uart_tx_data_stm[6] ;
        #8640 ;
        uart_tx = uart_tx_data_stm[7] ;
        #8640 ;
        uart_tx  = 1 ;
        #8640 ;
        end     
    endtask
    
    
endmodule
module uart_ram_TFT(//顶层连线模块
    clk,//50MHz
    reset,
    uart_tx ,
    RGB565_data,//输出的内容数据
    vish_axis ,//显示的行坐标
    visv_axis //显示的列坐标
    );
  
  input clk ;
  input reset ;
  input uart_tx ;
  output [15:0]RGB565_data ;
  output [15:0]vish_axis ;//显示的行坐标
  output [15:0]visv_axis ;//显示的列坐标 
  
  //内部变量
  wire [7:0]parallel_data ;//串口接收模块接收的并行数据8位
  wire rx_done ;//串口接收模块接收8位数据结束信号
  
  
  //uart接收模块
  uart_receive_1 uart_receive(//串口接收模块
    .clk(clk) ,
    .reset(reset) ,
    .baud_rate(5) ,
    .uart_tx(uart_tx), 
    .data(parallel_data) ,
    .rx_done(rx_done)   
    );  
  
  
  //内部变量
  wire [15:0]addr_write ;//串口接收模块接收的并行数据8位
  wire [15:0]data_write ;//串口接收模块接收8位数据结束信号
  wire write_enable ;//写入使能信号
  
  //uart接收的数据存入ram模块
  uart_to_ram uart_to_ram(//将uart串口接收模块输出的数据写入ram中
    .clk(clk) ,
    .reset(reset) ,
    .data(parallel_data),
    .rx_done(rx_done),
    .addr(addr_write) ,
    .dout(data_write) ,
    .wenable(write_enable )    
    ); 
  
  //内部变量
  wire clk_b ;//串口接收模块接收的并行数据8位
  wire [15:0]addr_read ;
  wire read_ram_request ;
  wire [15:0]read_data ;
  
  //ram存储模块
  RAM_DISPLAY RAM (
  .clka(clk),    // input wire clka
  .ena(1),      // input wire ena
  .wea(write_enable),      // input wire [0 : 0] wea
  .addra(addr_write),  // input wire [15 : 0] addra
  .dina(data_write),    // input wire [15 : 0] dina
  .clkb(clk_b),    // input wire clkb
  .enb(read_ram_request),      // input wire enb
  .addrb(addr_read),  // input wire [15 : 0] addrb
  .doutb(read_data)  // output wire [15 : 0] doutb
);
  
   //内部变量
  wire disp_request ;
  wire [15:0]disp_data ;
  
  //从ram读数据模块
  ram_to_display ram_to_display(//读ram数据到显示屏模块
    .clka(clk),//输入时钟
    .reset(reset),//复位
    .data(read_data),//ram读出的数据16位
    .data_request(disp_request),//显示屏控制的的数据请求信号
    .h_axis(vish_axis) ,//行坐标
    .v_axis(visv_axis) ,//列坐标
    .clkb(clk_b),//显示屏控制器的输入时钟
    .addr_read(addr_read),//读ram的地址
    .read_ram_request(read_ram_request),//读ram请求信号 
    .display_data(disp_data)//显示屏控制器的数据输入信号    
    );
    
  //屏幕显示器控制模块
  VGA TFT_control(
    .clk(clk_b),
    .reset(reset),
    .content_data_request(disp_request),//数据请求信号
    .content_data(disp_data),//要显示的内容数据
    .RGB_data(RGB565_data),//输出的内容数据
    .vis_h_axis(vish_axis) ,//显示的行坐标
    .vis_v_axis(visv_axis) ,//显示的列坐标
    .vis_sig()//内容显示同步信号(高电平时显示)
    );  
    
    
endmodule
module uart_receive(//串口接收模块
    clk ,
    reset ,
    baud_rate ,
    uart_tx, 
    data ,
    rx_done   
    );
    input  clk ;
    input reset ;
    input [2:0]baud_rate ;
    input uart_tx ;
    output reg [7:0]data ;
    output reg rx_done ;
    reg rx_done_sig ;
    
    reg [2:0]r_data[7:0] ;//接收每一位数据
    reg [2:0]sta_bit ;
    reg [2:0]sto_bit ;
    
    reg [17:0]bit_tim ;//每一位持续的时间(计数)
    always@(baud_rate)  //在这里一个 码元由一位组成,所以波特率=比特率
        begin
            case(baud_rate)         //常见的串口传输波特率
            3'd0 : bit_tim = 1000000000/300/20 ; //波特率为300
            3'd1 : bit_tim = 1000000000/1200/20 ; //波特率为1200
            3'd2 : bit_tim = 1000000000/2400/20 ; //波特率为2400
            3'd3 : bit_tim = 1000000000/9600/20 ; //波特率为9600
            3'd4 : bit_tim = 1000000000/19200/20 ; //波特率为19200
            3'd5 : bit_tim = 1000000000/115200/20 ; //波特率为115200
            default bit_tim = 1000000000/9600/20 ;   //多余的寄存器位置放什么:默认速率
            endcase
     end
    
    wire [17:0]bit_tim_16 ;//每1/16位的持续时间(计数)
    assign bit_tim_16 = bit_tim / 16;
    
    wire [8:0]bit16_mid ; //在中心点产生采样脉冲 
    assign bit16_mid = bit_tim_16 / 2 ;
    
    //边沿检测
    reg [1:0]edge_detect ;
    always @( posedge clk or negedge reset )
    begin
        if (!reset )
            edge_detect <= 2'd0 ;
        else 
            begin
            edge_detect[0] <= uart_tx ;
            edge_detect[1] <= edge_detect[0] ;
            end
    end    

    wire byte_sta_neg ;
    assign byte_sta_neg = ( edge_detect == 2'b10 ) ? 1 : 0 ;//输入的数据开始出现下降沿,说明出现了起始位(一直运行?)
         
    reg receive_en ;//接收使能端
    reg [17:0]div_cnt ;//每1/16bit内的计数
     reg [7:0]bit16_cnt ;//计数到了第几个状态(10位,每位分成16份,总共160个状态)
    always @( posedge clk or negedge reset )
    begin
         if (!reset )
            receive_en <= 1'd0 ;
        else if ( byte_sta_neg )    //检测到下降沿,使能段有效(只要有下降沿就使能?)
            receive_en <= 1'd1 ;
        else if ( (rx_done) || (sta_bit >= 3'd4 ))    
            receive_en <= 1'd0 ;    //检测到结束信号,使能端无效
        else if ( ( bit16_cnt == 8'd159 ) && (div_cnt == bit_tim_16 - 1'd1 ) )//跑完159后re_en置零
            receive_en <= 1'd0 ;
    end
             
    
    always@( posedge clk or negedge reset )
    begin
        if ( ! reset )
            div_cnt <= 18'd0 ;
        else if (receive_en)
        begin
            if ( div_cnt == bit_tim_16 - 1'd1 )//计数,每1/16bit清零
                div_cnt <= 18'd0 ;               
            else
                div_cnt <= div_cnt + 1'b1 ; 
        end
        else 
            div_cnt <= 18'd0 ;
    end
    
    reg bit16_pulse ;//产生采样脉冲
    always@( posedge clk or negedge reset )
    begin
        if ( ! reset )
            bit16_pulse <= 18'd0 ;
        else if (receive_en)
            if ( div_cnt == bit16_mid )
                bit16_pulse <= 1'd1 ;
            else
                bit16_pulse <= 1'd0 ;
        else
                bit16_pulse <= 1'd0 ;                
    end       
   
    always@( posedge clk or negedge reset )
    begin
        if ( ! reset )
            bit16_cnt <= 8'd0 ;
        else if (receive_en)
        begin    
            if (( bit16_cnt == 8'd159 ) && (div_cnt == bit_tim_16 - 1'd1 ))
                bit16_cnt <= 8'd0 ;
            else if ( div_cnt == bit_tim_16 - 1'd1 )
                bit16_cnt <= bit16_cnt + 1'b1 ;
        end
    end
      
    always@(posedge clk or negedge reset)
    begin
    if(!reset)
    begin
        sta_bit   <= 3'd0 ;
        r_data[0] <= 3'd0 ;
        r_data[1] <= 3'd0 ;
        r_data[2] <= 3'd0 ;
        r_data[3] <= 3'd0 ;
        r_data[4] <= 3'd0 ;
        r_data[5] <= 3'd0 ;
        r_data[6] <= 3'd0 ;
        r_data[7] <= 3'd0 ;
        sto_bit   <= 3'd0 ;
    end
    else if (bit16_pulse)//舍弃前5后4取中7
        case(bit16_cnt)
            0: 
            begin 
            sta_bit   <= 3'd0 ;
            r_data[0] <= 3'd0 ;
            r_data[1] <= 3'd0 ;
            r_data[2] <= 3'd0 ;
            r_data[3] <= 3'd0 ;
            r_data[4] <= 3'd0 ;
            r_data[5] <= 3'd0 ;
            r_data[6] <= 3'd0 ;
            r_data[7] <= 3'd0 ;
            sto_bit   <= 3'd0 ;
            end
            5,6,7,8,9,10,11 : sta_bit <= sta_bit + uart_tx ;
            21,22,23,24,25,26,27 : r_data[0] <= r_data[0] + uart_tx ;
            37,38,39,41,42,43,44 : r_data[1] <= r_data[1] + uart_tx ; 
            53,54,55,56,57,58,59 : r_data[2] <= r_data[2] + uart_tx ;
            69,70,71,72,73,74,75 : r_data[3] <= r_data[3] + uart_tx ;
            85,86,87,88,89,90,91 : r_data[4] <= r_data[4] + uart_tx ;
            101,102,103,104,105,106,107 : r_data[5] <= r_data[5] + uart_tx ;
            117,118,119,120,121,122,123 : r_data[6] <= r_data[6] + uart_tx ;
            133,134,135,136,137,138,139 : r_data[7] <= r_data[7] + uart_tx ;
            149,150,151,152,153,154,155 : sto_bit <= sto_bit + uart_tx ;
            default ;
        endcase
    end

    always@( posedge clk or negedge reset )
    begin
        if ( ! reset )
            rx_done_sig <= 8'd0 ;
        else if ( ( bit16_cnt == 8'd159 ) && (div_cnt == bit_tim_16 - 2'd2 ) )//跑完159后产生一个rx_done信号
            rx_done_sig <= 8'd1 ;
        else if (rx_done_sig <= 8'd1 )
            rx_done_sig <= 8'd0 ;
    end         
    
    always@( posedge clk or negedge reset )//接收完数据发出rx_done
    if(!reset )
        rx_done <= 0 ;
    else if (rx_done_sig)
        rx_done <= 1 ;
    else if (rx_done )
        rx_done <= 0 ;
    
    
    always@( posedge clk or negedge reset )//接收完数据发出rx_done后,把数据从r_data传递给data
    begin
        if ( ! reset )
            data <= 8'd0 ;
        else if ( rx_done_sig )
        begin
            data[0] = ( r_data[0] >3 ) ? 1 : 0 ;
            data[1] = ( r_data[1] >3 ) ? 1 : 0 ;
            data[2] = ( r_data[2] >3 ) ? 1 : 0 ;
            data[3] = ( r_data[3] >3 ) ? 1 : 0 ;
            data[4] = ( r_data[4] >3 ) ? 1 : 0 ;
            data[5] = ( r_data[5] >3 ) ? 1 : 0 ;
            data[6] = ( r_data[6] >3 ) ? 1 : 0 ;
            data[7] = ( r_data[7] >3 ) ? 1 : 0 ;
        end
//        else if ( receive_en )
//            data <= 8'd0 ;
    end
         
endmodule
module uart_to_ram(//将uart串口接收模块输出的数据写入ram中
    clk ,
    reset ,
    data,
    rx_done,
    addr ,
    dout ,
    wenable    
    );
    input clk ;
    input reset ;
    input [7:0]data;
    input rx_done;
    output reg [15:0]addr ;
    output reg [15:0]dout ;
    output reg wenable ;
    
    //ram的容量为256*256个像素,每个像素位宽16,共需256*256*2个8位的数据(131072)
    //用计数器来计数
    reg [16:0]pixel_cnt ;//131072
    always@(posedge clk or negedge reset)
    if(!reset)
        pixel_cnt <= 17'd0 ;
    else if ( ( pixel_cnt < 131071 ) && ( rx_done ) )
        pixel_cnt <= pixel_cnt + 1 ;
    else if (( pixel_cnt >= 131071 ) && ( rx_done ))
        pixel_cnt <= 17'd0 ;
   
   //需要一个寄存器,存两个8位,共16位
   reg [15:0]data_register ;
   always@(posedge clk or negedge reset)
    if(!reset)
        data_register <= 16'd0 ;
    else if ( rx_done  )
        data_register <= { data_register[7:0] , data  } ;   
   
   //添加一个变化条件信号
   reg change_sig ;
   always@(posedge clk or negedge reset)
    if(!reset)
        change_sig <= 1'd0 ;
    else if ( rx_done && ( pixel_cnt[0] == 1 )  )
        change_sig <= 1'd1 ;
    else if ( change_sig == 1'd1  )
        change_sig <= 1'd0 ;
    
   //把每16位数据存进ram中,即输出16位数据
    always@(posedge clk or negedge reset)
    if(!reset)
        dout <= 16'd0 ;
    else if ( change_sig )
        dout <= data_register ;
    
    //产生一个写入ram的使能信号
    always@(posedge clk or negedge reset)
    if(!reset)
        wenable <= 0 ;
    else if ( change_sig )
        wenable <= 1 ;
    else if (wenable == 1)
        wenable <= 0 ;
    
    //产生写入ram的地址 //比weanbel和data提前变化,不然不满足下面除于2的条件,第0个地址将没有数据
    always@(posedge clk or negedge reset)
    if(!reset)
        addr <= 16'd0 ;
    else if (  rx_done && ( pixel_cnt[0] == 1 )  )
        addr <= pixel_cnt[16:1] ; //除于2 即舍弃最后一位(右移一位)
        
    
endmodule
module ram_to_display(//读ram数据到显示屏模块
    clka,//输入时钟
    reset,//复位
    data,//ram读出的数据16位
    data_request,//显示屏控制的的数据请求信号
    h_axis ,//行坐标
    v_axis ,//列坐标
    clkb,//显示屏控制器的输入时钟
    addr_read,//读ram的地址
    read_ram_request,//读ram请求信号
    display_data//显示屏控制器的数据输入信号    
    );
    input  clka ;//输入时钟
    input reset ;//复位
    input [15:0]data;//ram读出的数据16位
    input data_request;//显示屏控制的的数据请求信号
    input [15:0]h_axis ;
    input [15:0]v_axis ;
    output clkb;//显示屏控制器的输入时钟
    output reg [15:0]addr_read ;//ram的读地址 输入信号
    output read_ram_request ;
    output wire [15:0]display_data;//显示屏控制器的数据输入信号
    
    
    my_PLL PLL//锁相环
   (
    .clk_out1(clkb),  //40MHz
    .clk_in1(clka)//50MHz
    );  
    
    //接下来设置两个区域信号,之所以分开,是为了控制地址和显示刚刚好,因为从显示屏发送读数据请求到ram的数据送到显示屏这个过程有两个周期的延迟
    //显示区域的地址
    wire field_h_addr ;//要显示区域的行范围
    assign field_h_addr = ( (h_axis >= 0 ) && ( h_axis < 255 ) ) ? 1 : 0 ;//到254
    wire field_v_addr ;//要显示区域的行范围
    assign field_v_addr = ( (v_axis >= 0 ) && ( v_axis <= 256 ) ) ? 1 : 0 ;
    //显示区域的范围
    wire my_field_addr ;
    assign my_field_addr = ( field_h_addr && field_v_addr && ( data_request ) ) ? 1 : 0 ;
    
    //显示区域的数据
    wire field_h_data ;//要显示区域的行范围
    assign field_h_data = ( (h_axis >= 0 ) && ( h_axis < 256 ) ) ? 1 : 0 ;//到255
    wire field_v_data ;//要显示区域的行范围
    assign field_v_data = ( (v_axis >= 0 ) && ( v_axis <= 256 ) ) ? 1 : 0 ;
    //显示区域的范围
    wire my_field_data ;
    assign my_field_data = ( field_h_data && field_v_data && ( data_request ) ) ? 1 : 0 ;
    
    //显示区域内读ram请求信号
    wire field_h_display ;//要显示区域的行范围
    assign field_h_display = ( (h_axis >= 0 ) && ( h_axis <= 256 ) ) ? 1 : 0 ;//到256
    wire field_v_display ;//要显示区域的行范围
    assign field_v_display = ( (v_axis >= 0 ) && ( v_axis <= 256 ) ) ? 1 : 0 ;
    assign read_ram_request = ( field_h_display && field_v_display && ( data_request ) ) ? 1 : 0 ;//( data_request ) ? 1 : 0 ;
    
    //读ram中的数据
   always@(posedge clkb or negedge reset )
   if(!reset )
        addr_read <= 0 ;
   else if (  my_field_addr )
        addr_read <= addr_read + 1 ;
   
   //显示屏控制器的数据输入信号
    assign display_data = ( my_field_data ) ? ( data ) : 0 ;
endmodule
module VGA(
    clk,
    reset,
    content_data_request,//数据请求信号
    content_data,//要显示的内容数据
    RGB_data,//输出的内容数据
    vis_h_axis ,//显示的行坐标
    vis_v_axis ,//显示的列坐标
    vis_sig//内容显示同步信号(高电平时显示)
    );
    input clk   ;
    input reset ;
    input  [15:0]content_data ;
    output content_data_request ;
    reg adjust_sig ;//数据请求信号
    output reg [15:0]vis_h_axis ;//显示的行坐标
    output reg [15:0]vis_v_axis ;//显示的列坐标
    reg horizontal_sig ;
    reg vertical_sig  ;   
    output reg [15:0]RGB_data ;
    output reg vis_sig ;//内容显示同步信号
    reg h_vis_sig ;//行内容显示同步信号
    reg v_vis_sig ;//列内容显示同步信号
    
    `include "VGA_resolution_parameter.v"
    //定义时间节点参数
    //行参数
    parameter h_pulse_start = 0 ; //行起始脉冲开始信号
    parameter h_pulse_end  = `H_Sync_Time ;// 行起始脉冲结束信号 
    parameter h_content_start  = `H_Sync_Time + `H_Back_Porch + `H_Left_Border ;//行内容开始信号 
    parameter h_content_end  = `H_Sync_Time + `H_Back_Porch + `H_Left_Border + `H_Data_Time ;//行内容结束信号 
    parameter h_end = `H_Sync_Time + `H_Back_Porch + `H_Left_Border + `H_Data_Time + `H_Right_Border + `H_Front_Porch;//行结束信号 
    
    //列参数
    parameter v_pulse_start = 0 ; //列起始脉冲开始信号
    parameter v_pulse_end  = `V_Sync_Time ;//列起始脉冲结束信号 
    parameter v_content_start  = `V_Sync_Time + `V_Back_Porch + `V_Top_Border ;//列内容开始信号 
    parameter v_content_end  = `V_Sync_Time + `V_Back_Porch + `V_Top_Border + `V_Data_Time ;//列内容结束信号 
    parameter v_end = `V_Sync_Time + `V_Back_Porch + `V_Top_Border + `V_Data_Time + `V_Bottom_Border + `V_Front_Porch;//列结束信号 
       
    //行与列 计数器
    reg [11:0]h_cnt ;
    reg [11:0]v_cnt ;
    
    always@(posedge clk or negedge reset)//行计数
    if(!reset)
        h_cnt <= 0 ;
    else if ( h_end - 1 <= h_cnt  )//0-799
        h_cnt <= 0 ;
    else 
        h_cnt <= h_cnt + 1 ;
        
    always@(posedge clk or negedge reset)//列计数
    if(!reset)
        v_cnt <= 0 ;
    else if  (( v_end - 1  <= v_cnt ) && ( h_end - 1 <= h_cnt ))//0-524
        v_cnt <= 0 ;
    else if  (( h_end - 1 <= h_cnt ) && ( v_end - 1  > v_cnt ))
        v_cnt <= v_cnt + 1 ;   
        
    //产生行起始脉冲    
    always@(posedge clk or negedge reset)//
    if(!reset)
        horizontal_sig <= 1 ;
    else if( h_cnt == 0 )
        horizontal_sig <= 0 ;//1-96 共96
    else if ( h_cnt == h_pulse_end  )
        horizontal_sig <= 1 ; 
        
    //产生列起始脉冲    
    always@(posedge clk or negedge reset)//
    if(!reset)
        vertical_sig <= 1 ;
    else if(( v_cnt == 0 )&& ( h_end - 1 <= h_cnt ) )
        vertical_sig <= 0 ;//1-2 共2
    else if (( v_cnt == v_pulse_end )&& ( h_end - 1 <= h_cnt ) )
        vertical_sig <= 1 ; 
        
    //产生行显示同步信号
    always@(posedge clk or negedge reset)//
    if(!reset)  
        h_vis_sig <= 0 ;
    else if (( h_content_start - 2 <= h_cnt ) &&  ( h_content_end - 1 - 2 >= h_cnt )) //提前两拍保证输出在第145拍开始    
        h_vis_sig <= 1 ;//146 - 785共 
    else
        h_vis_sig <= 0 ;  
    
    //行坐标
    always@(posedge clk or negedge reset)//
    if(!reset)  
        vis_h_axis <= 0 ;
    else if (  adjust_sig )begin
    if ( h_content_start - 1  == h_cnt ) 
        vis_h_axis <= 1 ;//146 - 785共     
    else 
        vis_h_axis <= vis_h_axis + 1 ;  
    end
    else if ( h_content_end  <= h_cnt )
        vis_h_axis <= 0 ;
    
    //产生列显示同步信号
    always@(posedge clk or negedge reset)//
    if(!reset)  
        v_vis_sig <= 0 ;
    else if (( v_content_start  <= v_cnt ) &&  ( v_content_end  >= v_cnt ) && (  h_end - 1 <= h_cnt  ) )     
        v_vis_sig <= 1 ;
    else if (( v_content_start  > v_cnt ) ||  ( v_content_end  < v_cnt ) ) 
        v_vis_sig <= 0 ;   
    
    //列坐标
    always@(posedge clk or negedge reset)//
    if(!reset)  
        vis_v_axis <= 0 ;
    else if (( v_content_start == v_cnt ) && ( h_end - 1 <= h_cnt ) ) 
        vis_v_axis <= 1 ;//
    else if  (( h_end - 1 <= h_cnt ) && ( v_content_end   > v_cnt ) && ( v_content_start  <= v_cnt ) )
        vis_v_axis <= vis_v_axis + 1 ;   
    else if (( h_end - 1 <= h_cnt ) && (v_content_end   <= v_cnt) )
        vis_v_axis <= 0 ;
             
    //调整信号 
    always@(posedge clk or negedge reset)
    if(!reset) 
        adjust_sig <= 0 ;//
    else if ( ( v_vis_sig ) && ( h_vis_sig ) )
        adjust_sig <= 1 ;
    else 
        adjust_sig <= 0 ;
        
    //请求信号
    assign content_data_request = ( ( v_vis_sig ) && ( h_vis_sig ) ) ? 1 : 0  ;
    
    //显示同步信号
    always@(posedge clk or negedge reset)//
    if(!reset) 
        vis_sig <= 0 ;
    else if ( adjust_sig )
        vis_sig <= 1 ;
    else 
        vis_sig <= 0 ;
        
    //显示
    always@(posedge clk or negedge reset)//
    if(!reset) 
        RGB_data <= 0 ;
    else if ( adjust_sig )
        RGB_data <= content_data ;//
    else 
        RGB_data <= 0 ;
        
        
        
endmodule
`define Resolution_480x272 1  //刷新率为60Hz其时钟频率为 9MHz
//`define Resolution_640x480 1 //刷新率为60Hz其时钟频率为 25.2MHz
//`define Resolution_800x480 1 //刷新率为60Hz其时钟频率为 33.264MHz
//`define Resolution_800x600 1 //刷新率为60Hz其时钟频率为 40MHz
//`define Resolution_1024x600 1 //刷新率为60Hz其时钟频率为 50.64MHz
//`define Resolution_1024x768 1 //刷新率为60Hz其时钟频率为 65MHz
//`define Resolution_1280x720 1 //刷新率为60Hz其时钟频率为 74.25MHz
//`define Resolution_1920x1080 1 //(1080p)刷新率为60Hz其时钟频率为 148.5MHz
//时钟频率计算公式:f = 1 / (( 1 / 60 ) / ( H_Total_Time * V_Total_Time ) )

`ifdef Resolution_480x272
    `define H_Right_Border 0
    `define H_Front_Porch 2
    `define H_Sync_Time 41
    `define H_Back_Porch 2
    `define H_Left_Border 0
    `define H_Data_Time 480
    `define H_Total_Time 525
    `define V_Bottom_Border 0
    `define V_Front_Porch 2
    `define V_Sync_Time 10
    `define V_Back_Porch 2
    `define V_Top_Border 0
    `define V_Data_Time 272
    `define V_Total_Time 286
    
`elsif Resolution_640x480
    `define H_Right_Border 8
    `define H_Front_Porch 8
    `define H_Sync_Time 96
    `define H_Back_Porch 40
    `define H_Left_Border 8
    `define H_Data_Time 640
    `define H_Total_Time 800
    `define V_Bottom_Border 8
    `define V_Front_Porch 2
    `define V_Sync_Time 2
    `define V_Back_Porch 25
    `define V_Top_Border 8
    `define V_Data_Time 480
    `define V_Total_Time 525

`elsif Resolution_800x480
    `define H_Right_Border 0
    `define H_Front_Porch 40
    `define H_Sync_Time 128
    `define H_Back_Porch 88
    `define H_Left_Border 0
    `define H_Data_Time 800
    `define H_Total_Time 1056
    `define V_Bottom_Border 8
    `define V_Front_Porch 2
    `define V_Sync_Time 2
    `define V_Back_Porch 25
    `define V_Top_Border 8
    `define V_Data_Time 480
    `define V_Total_Time 525     
    
`elsif Resolution_800x600
    `define H_Right_Border 0
    `define H_Front_Porch 40
    `define H_Sync_Time 128
    `define H_Back_Porch 88
    `define H_Left_Border 0
    `define H_Data_Time 800
    `define H_Total_Time 1056
    `define V_Bottom_Border 0
    `define V_Front_Porch 1
    `define V_Sync_Time 4
    `define V_Back_Porch 23
    `define V_Top_Border 0
    `define V_Data_Time 600
    `define V_Total_Time 628
    
`elsif Resolution_1024x600
    `define H_Right_Border 0
    `define H_Front_Porch 24
    `define H_Sync_Time 136
    `define H_Back_Porch 160
    `define H_Left_Border 0
    `define H_Data_Time 1024
    `define H_Total_Time 1344
    `define V_Bottom_Border 0
    `define V_Front_Porch 1
    `define V_Sync_Time 4
    `define V_Back_Porch 23
    `define V_Top_Border 0
    `define V_Data_Time 600
    `define V_Total_Time 628      
    
`elsif Resolution_1024x768
    `define H_Right_Border 0
    `define H_Front_Porch 24
    `define H_Sync_Time 136
    `define H_Back_Porch 160
    `define H_Left_Border 0
    `define H_Data_Time 1024
    `define H_Total_Time 1344
    `define V_Bottom_Border 0
    `define V_Front_Porch 3
    `define V_Sync_Time 6
    `define V_Back_Porch 29
    `define V_Top_Border 0
    `define V_Data_Time 768
    `define V_Total_Time 806       
    
`elsif Resolution_1280x720
    `define H_Right_Border 0
    `define H_Front_Porch 110
    `define H_Sync_Time 40
    `define H_Back_Porch 220
    `define H_Left_Border 0
    `define H_Data_Time 1280
    `define H_Total_Time 1650
    `define V_Bottom_Border 0
    `define V_Front_Porch 5
    `define V_Sync_Time 5
    `define V_Back_Porch 20
    `define V_Top_Border 0
    `define V_Data_Time 720
    `define V_Total_Time 750    

`elsif Resolution_1960x1080
    `define H_Right_Border 0
    `define H_Front_Porch 88
    `define H_Sync_Time 44
    `define H_Back_Porch 148
    `define H_Left_Border 0
    `define H_Data_Time 1920
    `define H_Total_Time 2200
    `define V_Bottom_Border 0
    `define V_Front_Porch 4
    `define V_Sync_Time 5
    `define V_Back_Porch 36
    `define V_Top_Border 0
    `define V_Data_Time 1080
    `define V_Total_Time 1125    
    
`endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值