模块框图:
时序图:
代码:
/*
// 24'h000000 4324 9Mhz 480*272
// 24'h800000 7084 33Mhz 800*480
// 24'h008080 7016 50Mhz 1024*600
// 24'h000080 4384 33Mhz 800*480
// 24'h800080 1018 70Mhz 1280*800
*/
module rd_id(input wire sys_clk ,input wire sys_rst_n ,input wire [23:0] lcd_rgb , output reg [15:0] lcd_id
);reg rd_flag ;always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) rd_flag <= 1'b1 ;elserd_flag <= 1'b0 ;endalways @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) lcd_id <= 24'd0 ;else if(rd_flag) begincase (lcd_rgb)24'h000000: lcd_id <= 16'd4324 ;24'h800000: lcd_id <= 16'd7084 ;24'h008080: lcd_id <= 16'd7016 ;24'h000080: lcd_id <= 16'd4384 ;24'h800080: lcd_id <= 16'd1018 ;default : lcd_id <= 16'd1018 ;endcaseendendendmodule
module clk_div(input wire sys_clk ,input wire sys_rst_n ,input wire [15:0] lcd_id ,output reg clk_lcd ,output wire rst_n
);wire clk_9Mhz ; wire clk_33Mhz ;wire clk_50Mhz ;wire clk_70Mhz ;wire locked ; assign rst_n = (sys_rst_n && locked) ;always @(*) begincase (lcd_id)16'd4324: clk_lcd <= clk_9Mhz ;16'd7084: clk_lcd <= clk_33Mhz ;16'd7016: clk_lcd <= clk_50Mhz ;16'd4384: clk_lcd <= clk_33Mhz ;16'd1018: clk_lcd <= clk_70Mhz ;default : clk_lcd <= 1'b0 ;endcaseendpll pll_inst(.clk_in ( sys_clk ) ,.resetn ( sys_rst_n ) ,.clk_9Mhz ( clk_9Mhz ) ,.clk_33Mhz ( clk_33Mhz ) ,.clk_50Mhz ( clk_50Mhz ) ,.clk_70Mhz ( clk_70Mhz ) ,.locked ( locked )
);endmodule
// 根据传进来的有效图像坐标信息,产生有效的像素数据。
module lcd_display (input wire sys_clk ,input wire sys_rst_n ,input wire [10:0] axi_x ,input wire [10:0] axi_y ,input wire [10:0] H_SYNC ,input wire [10:0] H_BACK ,input wire [10:0] H_DISP ,input wire [10:0] V_SYNC ,input wire [10:0] V_BACK ,input wire [10:0] V_DISP ,output reg [23:0] pix_data
);localparam BLACK = 24'h000000 , // 黑色WHITE = 24'hFFFFFF , // 白色RosyBrown = 24'hBC8F8F , // 玫瑰褐RED = 24'hFF0000 , // 红色APRICOT = 24'hE69966 , // 杏黄色VIOLET = 24'h8B00FF , // 紫罗兰色LINEN = 24'hFAF0E6 , // 亚麻色KHAKI = 24'h996B1F , // 卡其色PEACH = 24'hFFE5B4 , // 桃色GOLDEN = 24'hFFD700 , // 金色SkyBule = 24'h87CEEB ; // 天空蓝always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) pix_data <= BLACK ;else if((axi_y >= V_SYNC + V_BACK) && (axi_y <= V_SYNC + V_BACK + V_DISP - 1)) begin// 在场同步有效区间内if((axi_x >= H_SYNC + H_BACK) && (axi_x <= H_SYNC + H_BACK + H_DISP/10 - 1)) pix_data <= WHITE ; else if((axi_x >= H_SYNC + H_BACK + H_DISP/10) && (axi_x <= H_SYNC + H_BACK + (H_DISP/10)*2 - 1))pix_data <= BLACK ;else if((axi_x >= H_SYNC + H_BACK + (H_DISP/10)*2) && (axi_x <= H_SYNC + H_BACK + (H_DISP/10)*3 - 1))pix_data <= RosyBrown ;else if((axi_x >= H_SYNC + H_BACK + (H_DISP/10)*3) && (axi_x <= H_SYNC + H_BACK + (H_DISP/10)*4 - 1))pix_data <= APRICOT ;else if((axi_x >= H_SYNC + H_BACK + (H_DISP/10)*4) && (axi_x <= H_SYNC + H_BACK + (H_DISP/10)*5 - 1))pix_data <= RED ;else if((axi_x >= H_SYNC + H_BACK + (H_DISP/10)*5) && (axi_x <= H_SYNC + H_BACK + (H_DISP/10)*6 - 1))pix_data <= VIOLET ;else if((axi_x >= H_SYNC + H_BACK + (H_DISP/10)*6) && (axi_x <= H_SYNC + H_BACK + (H_DISP/10)*7 - 1))pix_data <= KHAKI ;elseif((axi_x >= H_SYNC + H_BACK + (H_DISP/10)*7) && (axi_x <= H_SYNC + H_BACK + (H_DISP/10)*8 - 1))pix_data <= PEACH ;elseif((axi_x >= H_SYNC + H_BACK + (H_DISP/10)*8) && (axi_x <= H_SYNC + H_BACK + (H_DISP/10)*9 - 1))pix_data <= GOLDEN ;elseif((axi_x >= H_SYNC + H_BACK + (H_DISP/10)*9) && (axi_x <= H_SYNC + H_BACK + (H_DISP/10)*10 - 1))pix_data <= SkyBule ;elsepix_data <= BLACK ;endelse pix_data <= BLACK ;endendmodule
// 接口模块,产生接口时序。又名驱动模块。
// 产生像素信息,有效信号。其余信号直接赋值1
module lcd_driver (input wire sys_clk ,input wire sys_rst_n ,input wire [23:0] pix_data ,input wire [15:0] lcd_id ,output wire [10:0] H_SYNCtoDIS ,output wire [10:0] H_BACKtoDIS ,output wire [10:0] H_DISPtoDIS ,output wire [10:0] V_SYNCtoDIS ,output wire [10:0] V_BACKtoDIS ,output wire [10:0] V_DISPtoDIS ,output reg lcd_de ,output wire [23:0] lcd_rgb_out ,output wire lcd_bl ,output wire lcd_rstn ,output wire lcd_hsync ,output wire lcd_vsync ,output wire lcd_clk ,output wire [10:0] axi_x , output wire [10:0] axi_y
);// localparam
// 4.3' 480*272 localparam H_SYNC_4342 = 11'd41 , H_BACK_4342 = 11'd2 , H_DISP_4342 = 11'd480 , H_FRONT_4342 = 11'd2 , H_TOTAL_4342 = 11'd525 , V_SYNC_4342 = 11'd10 , V_BACK_4342 = 11'd2 , V_DISP_4342 = 11'd272 , V_FRONT_4342 = 11'd2 , V_TOTAL_4342 = 11'd286 , // 7' 800*480 H_SYNC_7084 = 11'd128 , H_BACK_7084 = 11'd88 , H_DISP_7084 = 11'd800 , H_FRONT_7084 = 11'd40 , H_TOTAL_7084 = 11'd1056 , V_SYNC_7084 = 11'd2 , V_BACK_7084 = 11'd33 , V_DISP_7084 = 11'd480 , V_FRONT_7084 = 11'd10 , V_TOTAL_7084 = 11'd525 , // 7' 1024*600 H_SYNC_7016 = 11'd20 , H_BACK_7016 = 11'd140 , H_DISP_7016 = 11'd1024 , H_FRONT_7016 = 11'd160 , H_TOTAL_7016 = 11'd1344 , V_SYNC_7016 = 11'd3 , V_BACK_7016 = 11'd20 , V_DISP_7016 = 11'd600 , V_FRONT_7016 = 11'd12 , V_TOTAL_7016 = 11'd635 , // 10.1' 1280*800 H_SYNC_1018 = 11'd10 , H_BACK_1018 = 11'd80 , H_DISP_1018 = 11'd1280 , H_FRONT_1018 = 11'd70 , H_TOTAL_1018 = 11'd1440 , V_SYNC_1018 = 11'd3 , V_BACK_1018 = 11'd10 , V_DISP_1018 = 11'd800 , V_FRONT_1018 = 11'd10 , V_TOTAL_1018 = 11'd823 , // 4.3' 800*480 H_SYNC_4384 = 11'd128 , H_BACK_4384 = 11'd88 , H_DISP_4384 = 11'd800 , H_FRONT_4384 = 11'd40 , H_TOTAL_4384 = 11'd1056 , V_SYNC_4384 = 11'd2 , V_BACK_4384 = 11'd33 , V_DISP_4384 = 11'd480 , V_FRONT_4384 = 11'd10 , V_TOTAL_4384 = 11'd525 ; // 不同分辨率时序参数不同reg [10:0] H_SYNC ;reg [10:0] H_BACK ;reg [10:0] H_DISP ;reg [10:0] H_FRONT ;reg [10:0] H_TOTAL ;reg [10:0] V_SYNC ;reg [10:0] V_BACK ;reg [10:0] V_DISP ;reg [10:0] V_FRONT ;reg [10:0] V_TOTAL ;// reg signal define reg [10:0] cnt_row ; // 行计数器,记录一行中的第几列。行计数器归零,说明一行扫描完。reg [10:0] cnt_col ; // 列计数器,记录一列中的第几行。列计数器归零,说明一帧图像扫描完。// wire signal definewire valid_H ; // 行时序有效信号wire valid_V ; // 列时序有效信号wire valid_HV; // 图像有效信号,由于lcd_display模块中产生像素数据信息是时序逻辑,所以lcd_de信号要对图像有效信号打1拍。/**************************************************************************************************************************************main code*********************************************************************************************************************************/// 时序参数赋值always @(*) begincase(lcd_id)16'd4324: beginH_SYNC = H_SYNC_4342 ;H_BACK = H_BACK_4342 ;H_DISP = H_DISP_4342 ;H_FRONT = H_FRONT_4342 ;H_TOTAL = H_TOTAL_4342 ;V_SYNC = V_SYNC_4342 ;V_BACK = V_BACK_4342 ;V_DISP = V_DISP_4342 ;V_FRONT = V_FRONT_4342 ;V_TOTAL = V_TOTAL_4342 ;end16'd7084: beginH_SYNC = H_SYNC_7084 ;H_BACK = H_BACK_7084 ;H_DISP = H_DISP_7084 ;H_FRONT = H_FRONT_7084 ;H_TOTAL = H_TOTAL_7084 ;V_SYNC = V_SYNC_7084 ;V_BACK = V_BACK_7084 ;V_DISP = V_DISP_7084 ;V_FRONT = V_FRONT_7084 ;V_TOTAL = V_TOTAL_7084 ;end16'd7016: beginH_SYNC = H_SYNC_7016 ;H_BACK = H_BACK_7016 ;H_DISP = H_DISP_7016 ;H_FRONT = H_FRONT_7016 ;H_TOTAL = H_TOTAL_7016 ;V_SYNC = V_SYNC_7016 ;V_BACK = V_BACK_7016 ;V_DISP = V_DISP_7016 ;V_FRONT = V_FRONT_7016 ;V_TOTAL = V_TOTAL_7016 ;end16'd4384: beginH_SYNC = H_SYNC_4384 ;H_BACK = H_BACK_4384 ;H_DISP = H_DISP_4384 ;H_FRONT = H_FRONT_4384 ;H_TOTAL = H_TOTAL_4384 ;V_SYNC = V_SYNC_4384 ;V_BACK = V_BACK_4384 ;V_DISP = V_DISP_4384 ;V_FRONT = V_FRONT_4384 ;V_TOTAL = V_TOTAL_4384 ;end16'd1018: beginH_SYNC = H_SYNC_1018 ;H_BACK = H_BACK_1018 ;H_DISP = H_DISP_1018 ;H_FRONT = H_FRONT_1018 ;H_TOTAL = H_TOTAL_1018 ;V_SYNC = V_SYNC_1018 ;V_BACK = V_BACK_1018 ;V_DISP = V_DISP_1018 ;V_FRONT = V_FRONT_1018 ;V_TOTAL = V_TOTAL_1018 ;enddefault : beginH_SYNC = H_SYNC_1018 ;H_BACK = H_BACK_1018 ;H_DISP = H_DISP_1018 ;H_FRONT = H_FRONT_1018 ;H_TOTAL = H_TOTAL_1018 ;V_SYNC = V_SYNC_1018 ;V_BACK = V_BACK_1018 ;V_DISP = V_DISP_1018 ;V_FRONT = V_FRONT_1018 ;V_TOTAL = V_TOTAL_1018 ;endendcaseend// // reg signal define // reg [10:0] cnt_row ; // 行计数器,记录一行中的第几列。行计数器归零,说明一行扫描完。always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) cnt_row <= 11'd0 ;else if(cnt_row == (H_TOTAL - 1))cnt_row <= 11'd0 ;else cnt_row <= cnt_row + 1'b1 ;end// reg [10:0] cnt_col ; // 列计数器,记录一列中的第几行。列计数器归零,说明一帧图像扫描完。always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) cnt_col <= 11'd0 ;else if((cnt_col == (V_TOTAL - 1)) && (cnt_row == (H_TOTAL - 1)))cnt_col <= 11'd0 ;else if(cnt_row == (H_TOTAL - 1))cnt_col <= cnt_col + 1'b1 ;else cnt_col <= cnt_col ;end// // wire signal define// wire valid_H ; // 行时序有效信号assign valid_H = ((cnt_row >= H_SYNC + H_BACK) && (cnt_row <= H_SYNC + H_BACK + H_DISP - 1)) ? 1'b1 : 1'b0 ;// wire valid_V ; // 列时序有效信号assign valid_V = ((cnt_col >= V_SYNC + V_BACK) && (cnt_col <= V_SYNC + V_BACK + V_DISP - 1)) ? 1'b1 : 1'b0 ;// wire valid_HV; // 图像有效信号,由于lcd_display模块中产生像素数据信息是时序逻辑,所以lcd_de信号要对图像有效信号打1拍。assign valid_HV = (valid_H && valid_V) ;// output wire [10:0] axi_x , assign axi_x = (valid_HV) ? cnt_row : 11'd0 ;// output wire [10:0] axi_y ,assign axi_y = (valid_HV) ? cnt_col : 11'd0 ;// output wire [23:0] lcd_rgb_out ,assign lcd_rgb_out = pix_data ;// output reg lcd_de ,always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) lcd_de <= 1'b0 ;else lcd_de <= valid_HV ;end// 本实验没用到的信号,赋值1;assign lcd_bl = 1'b1 ;assign lcd_rstn = 1'b1 ;assign lcd_hsync = 1'b1 ;assign lcd_vsync = 1'b1 ;assign lcd_clk = (sys_rst_n == 1'b1) ? sys_clk : 1'b0 ;// 传给像素数据生成模块的时序参数assign H_SYNCtoDIS = H_SYNC ;assign H_BACKtoDIS = H_BACK ;assign H_DISPtoDIS = H_DISP ;assign V_SYNCtoDIS = V_SYNC ;assign V_BACKtoDIS = V_BACK ;assign V_DISPtoDIS = V_DISP ;endmodule
module top (input wire sys_clk ,input wire sys_rst_n ,inout wire [23:0] lcd_rgb ,output wire lcd_de ,output wire lcd_bl ,output wire lcd_rstn ,output wire lcd_hsync ,output wire lcd_vsync ,output wire lcd_clk
);// inoutwire [23:0] lcd_rgb_out ;wire [23:0] lcd_rgb_in ;assign lcd_rgb = (lcd_de) ? lcd_rgb_out : 24'dz ;assign lcd_rgb_in = lcd_rgb ;// 例化间连线wire [15:0] lcd_id ;wire clk_lcd ;wire rst_n ;wire [10:0] H_SYNCtoDIS ;wire [10:0] H_BACKtoDIS ;wire [10:0] H_DISPtoDIS ;wire [10:0] V_SYNCtoDIS ;wire [10:0] V_BACKtoDIS ;wire [10:0] V_DISPtoDIS ;wire [10:0] axi_x ; wire [10:0] axi_y ;wire [23:0] pix_data ; rd_id rd_id_inst(.sys_clk ( sys_clk ) ,.sys_rst_n ( sys_rst_n ) ,.lcd_rgb ( lcd_rgb_in ) , .lcd_id ( lcd_id )
);clk_div clk_div_inst(.sys_clk ( sys_clk ) ,.sys_rst_n ( sys_rst_n ) ,.lcd_id ( lcd_id ) ,.clk_lcd ( clk_lcd ) ,.rst_n ( rst_n )
);lcd_driver lcd_driver_inst(.sys_clk ( clk_lcd ) ,.sys_rst_n ( rst_n ) ,.pix_data ( pix_data ) ,.lcd_id ( lcd_id ) ,.H_SYNCtoDIS ( H_SYNCtoDIS ) ,.H_BACKtoDIS ( H_BACKtoDIS ) ,.H_DISPtoDIS ( H_DISPtoDIS ) ,.V_SYNCtoDIS ( V_SYNCtoDIS ) ,.V_BACKtoDIS ( V_BACKtoDIS ) ,.V_DISPtoDIS ( V_DISPtoDIS ) ,.lcd_de ( lcd_de ) ,.lcd_rgb_out ( lcd_rgb_out ) ,.lcd_bl ( lcd_bl ) ,.lcd_rstn ( lcd_rstn ) ,.lcd_hsync ( lcd_hsync ) ,.lcd_vsync ( lcd_vsync ) ,.lcd_clk ( lcd_clk ) ,.axi_x ( axi_x ) , .axi_y ( axi_y )
);lcd_display lcd_display_inst(.sys_clk ( clk_lcd ) ,.sys_rst_n ( rst_n ) ,.axi_x ( axi_x ) , .axi_y ( axi_y ) ,.H_SYNC ( H_SYNCtoDIS ) ,.H_BACK ( H_BACKtoDIS ) ,.H_DISP ( H_DISPtoDIS ) ,.V_SYNC ( V_SYNCtoDIS ) ,.V_BACK ( V_BACKtoDIS ) ,.V_DISP ( V_DISPtoDIS ) ,.pix_data ( pix_data )
);endmodule
`timescale 1ns/1ns
module test_top();reg sys_clk ;reg sys_rst_n ;wire [23:0] lcd_rgb ;wire lcd_de ;wire lcd_bl ;wire lcd_rstn ;wire lcd_hsync ;wire lcd_vsync ;wire lcd_clk ;assign lcd_rgb = lcd_de ? {24{1'bz}} : 24'h80;top top_inst(.sys_clk ( sys_clk ) ,.sys_rst_n ( sys_rst_n ) ,.lcd_rgb ( lcd_rgb ) ,.lcd_de ( lcd_de ) ,.lcd_bl ( lcd_bl ) ,.lcd_rstn ( lcd_rstn ) ,.lcd_hsync ( lcd_hsync ) ,.lcd_vsync ( lcd_vsync ) ,.lcd_clk ( lcd_clk )
);parameter CYCLE = 20 ;initial beginsys_clk = 1'b1 ;sys_rst_n <= 1'b0 ;#( CYCLE * 10 ) ;#2 ;sys_rst_n <= 1'b1 ;#( CYCLE * 1000 ) ;$stop ;endalways #( CYCLE / 2 ) sys_clk = ~sys_clk ;endmodule