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

2023-11-01


目的:

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • FPGA零基础学习之Vivado-ROM使用教程

    FPGA零基础学习之Vivado ROM使用教程 本系列将带来FPGA的系统性学习 从最基本的数字电路基础开始 最详细操作步骤 最直白的言语描述 手把手的 傻瓜式 讲解 让电子 信息 通信类专业学生 初入职场小白及打算进阶提升的职业开发者都
  • DDR3学习总结(一)

    简介 DDR3 SDRAM常 简称 DDR3 是当今较为常见的一种储存器 在计算机及嵌入式产品中得到广泛应用 特别是应用在涉及到大量数据交互的场合 比如电脑的内存条 对DDR3的读写操作大都借助IP核来完成 本次实验将采用 Xilinx公司
  • 【Xilinx Vivado时序分析/约束系列6】FPGA开发时序分析/约束-IO时序输入延时

    目录 源同步FPGA输入时序分析的模型 input delay约束 极限input delay 往期系列博客 源同步FPGA输入时序分析的模型 以下为源同步FPGA输入时序分析的模型的示意图 在之前的文章中介绍过 在此介绍一下各个时钟延时的
  • 8x8LED点阵

    点量这个只需要把9高电平 13低电平就可以了 共阳极点阵 行线是led的正极 列线是led的列线 左上角点亮 显示多个灯是动态扫描的 一个一个显示的 然后间隔速度要快就可以造成显示 点阵由两篇74Hc595级联在一起驱动的 只需要三个io口
  • Verilog:【1】时钟分频电路(clk_divider.sv)

    碎碎念 作为Basic Verilog的第一个学习笔记 打算用这种命名方式来对博客进行命名 应该有助于检索 简单阅览了部分工程的代码 发现里面有很多嵌套关系 因此决定先从基础模块开始 也是为了整个博客内容的流畅性 读者朋友有问题的话 也可以
  • 数字芯片流程

    芯片设计分为前端设计和后端设计 前端设计 逻辑设计 和后端设计 物理设计 并没有同意严格的界限 这个过程中涉及到了与工艺有关的设计就是后端设计 一 需求分析 产品需要解决的问题 预测3 5年的趋向和走势 确保前瞻性 确保芯片是有卖点的 客户
  • 基于单光子探测的多脉冲周期符合远距离测距

    激光测距技术通过发射主动激光信号对目标进行探测 接收由目标漫反射回来的回波信号并进行统计 处理及换算 从而得到目标的距离 速度信息 实现对目标距离信息的探测 凭借其系统简单 操作灵活 高精度等特点 被广泛运用于民用 科研及军事等各类场合 基
  • DDR的VTT有源端接和无源端接(slua886a笔记)

    DDR的VTT有源端接和无源端接 slua886a笔记 背景 对于DDR的VTT端接 一直有说法是有源端接可降低功耗 之前一直没仔细理解其中原因 现在找了些相关的资料来介绍和对比有源和无源端接 理解有源端接的优点和降低功耗的原理 主要基于读
  • MIPI D-PHY介绍(二) FPGA

    MIPI D PHY介绍 二 FPGA 随着移动设备的广泛普及 MIPI D PHY作为其最主要的物理层标准之一 被越来越多地使用在各种嵌入式系统中 本文将详细介绍MIPI D PHY的工作原理和在FPGA设计中的实现方法 MIPI D P
  • Verilog HDL——分频 计数

    分频 计数 module traffic Clk 50M Rst Clk30 Clk 1Hz input Clk 50M Rst output Clk30 Clk 1Hz 分频器 reg Clk 1Hz 分频器 50M分频 reg 31 0
  • 二、RISC-V SoC内核注解——译码 代码讲解

    tinyriscv这个SoC工程的内核cpu部分 采用经典的三级流水线结构进行设计 即大家所熟知的 取值 gt 译码 gt 执行三级流水线 另外 在最后一个章节中会上传额外添加详细注释的工程代码 完全开源 如有需要可自行下载 上一篇博文中注
  • FPGA的基本设计流程

    FPGA开发主要包括系统设计 设计输入 功能仿真 综合优化 综合后仿真 实现与布局布线 时序方针与验证 板级方针与验证 芯片编程与调试等9个部分 如下图所示 1 电路设计 在系统设计之前 首先要进行的是方案论证 系统设计和FPGA芯片选择等
  • 【Xilinx DDR3 MIG】Xilinx FPGA DDR3读写实验相关用户接口引脚解释

    目录 DDR3读写实验 实验框图 时钟模块 DDR3读写及LED指示模块 MIG IP核 用户接口解释
  • 八段数码管动态显示(输入数据为BCD编码)

    八段数码管动态显示 输入数据为BCD编码 一 数码管概述 图1 八段共阴数码管内部等效原理图 图2 八段共阳数码管内部等效原理图 上面两图分别是对应八段共阴 共阳的数码管内部等效图 共阴是将八个LED数码管的阴极连接在一起接低 阳极segm
  • Verilog HDL——Modelsim仿真

    常用testbench语法 finish 和 stop finish任务用于终止仿真并跳出仿真器 stop任务则用于中止仿真 timescale time unit time precision time unit指定计时和延时的测量单位
  • 【电子技术】什么是LFSR?

    目录 0 前言 1 数学基础 1 1 逻辑异或 1 2 模2乘法 和 模2除法 2 线性反馈移位寄存器LFSR 3 抽头和特征多项式 4 阶线性反馈移位寄存器实例 0 前言 线性反馈移位寄存器 Linear Feedback Shift R
  • 【FMC141】基于VITA57.4标准的4通道2.8GSPS 16位DA播放子卡(2片DAC39J84)

    FMC141是一款基于VITA57 4标准的4通道2 8GSPS 2 5GSPS 1 6GSPS采样率16位DA播放FMC子卡 该板卡为FMC 标准 符合VITA57 4与VITA57 1规范 16通道的JESD204B接口通过FMC 连接
  • 串口通信知识点总结

    串口是串行接口 serial port 的简称 也称为串行通信接口或COM接口 串口通信是指采用串行通信协议 serial communication 在一条信号线上将数据一个比特一个比特地逐位进行传输的通信模式 串口按电气标准及协议来划分
  • Matlab图像处理系列——图像复原之噪声模型仿真

    微信公众号上线 搜索公众号 小灰灰的FPGA 关注可获取相关源码 定期更新有关FPGA的项目以及开源项目源码 包括但不限于各类检测芯片驱动 低速接口驱动 高速接口驱动 数据信号处理 图像处理以及AXI总线等 本节目录 一 图像复原的模型 二
  • TRICONEX MA2211-100 芯片上相互连接

    TRICONEX MA2211 100 芯片上相互连接 TRICONEX MA2211 100 所有相同的组件 io的电源 处理器 和内存将需要 但是 你可以看到所有这些带存储器和处理器的OO板 针不能嵌入到一个小的单片机上 现在是 普拉克

随机推荐

  • Chromedriver安装教程【无需翻墙】

    第一步 查看你当前Chrome浏览器的版本 如下图所示 第二步 查看当前Chrome浏览器的版本号 如下图所示 版本 108 0 5359 125 正式版本 64 位 中的 108就是我们的版本号 第三步 到谷歌驱动下载地址 https n
  • spring全家桶

    目录 一 Spring基础 1 Spring的核心模块 2 Spring中用到的设计模式 3 Spring SpringMVC SpringBoot SpringCloud 二 SpringIOC 1 IOC的理解 2 Spring中的循环
  • java基础

    java简介 Java是一门面向对象的编程语言 不仅吸收了C 语言的各种优点 还摒弃了C 里难以理解的多继承 指针等概念 因此Java语言具有功能强大和简单易用两个特征 Java语言作为静态面向对象编程语言的代表 极好地实现了面向对象理论
  • psql的使用与常用参数

    使用psql时默认使用安装数据库时的用户登录 端口默认5432 默认连接数据库是用户名db 使用默认用户登录时是超级用户 不需要密码 但是第一次登录会因为未创建该用户名的数据库而登录失败 首次登录需要手动创建用户名数据库或者选择默认的pos
  • Linux中source命令的用法

    source命令 source命令也称为 点命令 也就是一个点符号 source命令通常用于重新执行刚修改的初始化文件 使之立即生效 而不必注销并重新登录 用法 source filename 或 filename source命令除了上述
  • BUUCTF 之 [ACTF2020 新生赛]Exec(命令执行漏洞)

    BUUCTF 之 ACTF2020 新生赛 Exec 命令执行漏洞 相关 观察 进攻 相关 项目 内容 难度 简单 类型 WEB 靶场 BUUCTF 坐标 Exec 观察 这界面和这网页标题结合起来 相信给位都能猜到这个靶场中很有可能存在命
  • 类和对象的学习

    类和对象的学习 1 什么是类 class 就是声明一个类 概念 一类事物的总体描述 及该事物包含方法的总称 属性 描述这个事物的 方法 这个事物特有的行为 定义一个学生类 属性 名字 年龄 性别 方法 吃饭 睡觉 学习 打游戏 2 封装一个
  • 《创新创业实训》网课答案解析

    创新创业实训 网课答案解析 一 网课的简单介绍 二 部分习题的展示 三 获取全部内容 一 网课的简单介绍 创新创业实训 是我之前选的一门网课 由于其比较小众 所以很多课后题很难在网上找到答案 为了帮助后续选择这门课的同学 这里我将该网课所涉
  • Zabbix--API接口

    一 API的简单介绍 Zabbix API允许你以编程方式检索和修改Zabbix的配置 并提供对历史数据的访问 1 应用 1 创建新的应用程序以使用Zabbix 2 将Zabbix与第三方软件集成 3 自动执行常规任务 2 意义 abbix
  • RabbitMQ多种问题出现的解决方案

    消息丢失 1 只要订单完成我们就会发送一条消息给MQ 这个途中突然MQ服务器网络中断 导致消息无法抵达 做好容错方法需要在消息发送前加上异常处理 try rabbitTemplate convertAndSend order event e
  • 区间和

    模板 模板来自AcWing vector
  • IDEA中新建一个java类,无法实现Servlet接口或者继承HttpServlet类

    有道云笔记链接可查看 IDEA中新建一个java类 无法实现Servlet接口或者继承HttpServlet类 问题描述 新建一个java类 无法实现Servlet接口或者继承HttpServlet类 原因 缺少tomcat的librari
  • SQL每日一练(牛客新题库)——第2天: 条件查询

    文章目录 1 查找后排序 2 查找后多列排序 3 查找后降序排列 4 查找学校是北大的学生信息 5 查找年龄大于24岁的用户信息 6 如何让刷题变得更高效 1 查找后排序 题目 现在运营想要取出用户信息表中的用户年龄 请取出相应数据 并按照
  • linux日志系统介绍 —— syslog(),openlog(),closelog()

    函数使用介绍 这里面的三个函数openlog syslog closelog是一套系统日志写入接口 另外那个vsyslog和syslog功能一样 仅仅是參数格式不同 通常 syslog守护进程读取三种格式的记录消息 此守护进程在启动时读一个
  • 毕业两年月薪36k,有时候人与人的差距比人和狗还大

    想起两年前交流过的一个应届生 当时他刚毕业技术水平不高 进了一个小公司做Java后端实习工作 最近联系上了 不问不知道 一问吓一跳 他现在已经进了某一线大厂 月薪36K 这位朋友其实也没比别人强多少 关键在于面试前做足了准备 许多人迫切需要
  • 有序表的合并

    目录 前言 一 有序表合并的两种方式 二 两种实现方式的具体操作 1 顺序表 2 链式 三 两种实现方式的比较 四 总结 前言 通过对线性表的学习 我们对其相关概念已经一定的认识 下面我们通过一些简单的实例应用来增进对线性表相关知识的认识并
  • Synthtext 数据集

    Synth text 数据集官网下载的主要包含图像文件夹和gt mat标注文件 共85万 858750 多张图片数据 该数据集中包含了词级别标注 字符级别标注和文本识别内容 可用于文本检测和文本识别模型 1 mat格式标注文件读取 采用sc
  • pythonscipy教程_Python学习教程(Python学习路线):Python—SciPy精讲

    SciPy 是 Python 里处理科学计算 scientific computing 的包 使用它遇到问题可访问它的官网 https www scipy org 去找答案 在使用 scipy 之前 需要引进它 语法如下 import sc
  • transformer 全总结

    这篇大概写于好几个月之前 最近又很多东西要重新开始 于是重新写起笔记 这是写给我自己看的笔记 所以读者看不明白是很正常的 但我并不觉得完全没有参考价值 毕竟之前看的trans介绍 要么只有encoder 要么没有训练过程 transform
  • 项目:串口接收—ram存储—TFT显示(完整设计)

    目的 1 使用uart串口接收模块接收待显示的串行数据 像素RGB值 2 把待显示的数据写入ram中 3 从ram中读取像素值到TFT显示屏中显示 并对应输出该像素的坐标值 注意 1 遵循uart协议的一个数据位宽为8 一个RGB565像素