东北大学2024春季数字逻辑实验LCD驱动使用说明

在交通系统全部完成,仿真也没有问题后,

(1)在顶层文件中增加液晶驱动lcd_top模块用到的输入输出端口(如果交通灯系统中未包含clk_50M,增加“input  wire clk_50M,”,如果已包含,不需要重复声明),新增端口包括:

input wire reset_btn,

output wire [2:0] video_red,    //红色像素_3使

output wire [2:0] video_green,  //绿色像素_3使

output wire [1:0] video_blue,   //蓝色像素_2使

output wire       video_hsync,  //行同步(水平同步)信叿

output wire       video_vsync,  //场同步(垂直同步)信叿

output wire       video_clk,    //像素时钟输出

output wire       video_de      //行数据有效信号,用于区分消隐匿

(2)如果不修改已经编辑好的顶层文件,可以新建一个工程,在新工程中例化你的交通系统和lcd_top;;两种方式任选一即可。

lcd_top.sv

`default_nettype none `timescale 1ns / 1ps

module lcd_top (
    input wire CP,
    input wire RESETn,
    input wire [3:0] countA_shi,
    input wire [3:0] countA_ge,
    input wire [3:0] countB_shi,
    input wire [3:0] countB_ge,
    input wire [3:0] countC_shi,
    input wire [3:0] countC_ge,
    input wire [3:0] countD_shi,
    input wire [3:0] countD_ge,
    input wire [3:0] countE_shi,
    input wire [3:0] countE_ge,
    input wire [3:0] countF_shi,
    input wire [3:0] countF_ge,
    output wire AG,
    output wire AY,
    output wire AR,
    output wire BG,
    output wire BY,
    output wire BR,
    output wire video_hsync,
    output wire video_vsync,
    output wire video_clk,
    output wire video_de
);

  logic clk_pix;
  logic clk_pix_locked;


  clock_divider clock_div_inst (
      .clk(CP),
      .rst(RESETn),
      .clk_div(clk_pix)
  );
  //  wire [15:0] line_2_ascii;
  dvi_module dvi_inst (
      .clk(clk_pix),
      .clk_locked(RESETn),
      .AG(AG),
      .AY(AY),
      .AR(AR),
      .BG(BG),
      .BY(BY),
      .BR(BR),
      .video_hsync(video_hsync),
      .video_vsync(video_vsync),
      .video_clk(video_clk),
      .video_de(video_de),
      .line_0_ascii(line_0),
      .line_1_ascii(line_1)
    //  .line_2_number( )
    //  .line_2_number(number)
    //  .line_2_ascii_to_top(line_2_ascii)
  );

 
 //line_2_ascii[15:0];

  wire [79:0] line_0; 
  wire [79:0] line_1; 
//  wire [7:0] countA_shi;
//  wire [7:0] countA_ge;
//  wire [7:0] countB_shi;
//  wire [7:0] countB_ge;
//  wire [7:0] countC_shi;
//  wire [7:0] countC_ge;
//  wire [7:0] countD_shi;
//  wire [7:0] countD_ge;
//  assign countA_shi=ascii;
//  assign countA_ge=ascii;
//  assign countB_shi=ascii;
//  assign countB_ge=ascii;
//  assign countC_shi=ascii;
//  assign countC_ge=ascii;
//  assign countD_shi=ascii;
//  assign countD_ge=ascii;
 // assign line_0 = {{8{ascii}},countA_shi+30,countA_shi+30,countA_shi+30,countA_shi+30, line_2_ascii};
  assign line_0 = {8'h20,countA_shi+8'h30,countA_ge+8'h30,countC_shi+8'h30,countC_ge+8'h30,8'h20,countD_shi+8'h30,countD_ge+8'h30,8'h20,8'h20};
assign line_1 = {8'h20,countE_shi+8'h30,countE_ge+8'h30,8'h20,8'h20,countF_shi+8'h30,countF_ge+8'h30, 8'h20,8'h20,8'h20};
// assign line_1 = 80'h3a_39_38_37_36_35_34_33_32_31_30;


localparam CNT_1S = 27'd50_000_000;
reg [26:0] cnt;
wire cnt_eq_1s;
assign cnt_eq_1s = cnt==(CNT_1S-1);
always @(posedge CP)
begin
    if (RESETn)
    begin
        cnt <= 27'd0;
    end
    else if (cnt_eq_1s)
    begin
        cnt <= 27'd0;
    end
    else
    begin
        cnt <= cnt + 1'b1;
    end
end

reg [7:0] ascii;
always @(posedge CP)
begin
    if (RESETn)
    begin
        ascii <= 8'd0;
    end
    else if (cnt_eq_1s)
    begin
        if (ascii == 8'd9)
        begin
            ascii <= 8'd0;
        end
        else
        begin
            ascii <= ascii + 1'b1;
        end
    end
end

reg [4:0] number;
always @(posedge CP)
begin
    if (RESETn)
    begin
        number <= 5'h0;
    end
    else if (cnt_eq_1s)
    begin
        number <= number + 5'b1;
    end
end

endmodule

module ascii_rom_async (
    input  wire  [10:0] addr,
    output reg   [7:0] data
);

always @(*) begin
    case (addr)
        // code x30 (0)
			11'h300: data = 8'b00000000;	//
			11'h301: data = 8'b00000000;	//
			11'h302: data = 8'b00111000;	//  ***  
			11'h303: data = 8'b01101100;	// ** **
			11'h304: data = 8'b11000110;	//**   **
			11'h305: data = 8'b11000110;	//**   **
			11'h306: data = 8'b11000110;	//**   **
			11'h307: data = 8'b11000110;	//**   **
			11'h308: data = 8'b11000110;	//**   **
			11'h309: data = 8'b11000110;	//**   **
			11'h30a: data = 8'b01101100;	// ** **
			11'h30b: data = 8'b00111000;	//  ***
			11'h30c: data = 8'b00000000;	//
			11'h30d: data = 8'b00000000;	//
			11'h30e: data = 8'b00000000;	//
			11'h30f: data = 8'b00000000;	//
			// code x31 (1)
			11'h310: data = 8'b00000000;	//
			11'h311: data = 8'b00000000;	//
			11'h312: data = 8'b00011000;	//   **  
			11'h313: data = 8'b00111000;	//  ***
			11'h314: data = 8'b01111000;	// ****
			11'h315: data = 8'b00011000;	//   **
			11'h316: data = 8'b00011000;	//   **
			11'h317: data = 8'b00011000;	//   **
			11'h318: data = 8'b00011000;	//   **
			11'h319: data = 8'b00011000;	//   **
			11'h31a: data = 8'b01111110;	// ******
			11'h31b: data = 8'b01111110;	// ******
			11'h31c: data = 8'b00000000;	//
			11'h31d: data = 8'b00000000;	//
			11'h31e: data = 8'b00000000;	//
			11'h31f: data = 8'b00000000;	//
			// code x32 (2)
			11'h320: data = 8'b00000000;	//
			11'h321: data = 8'b00000000;	//
			11'h322: data = 8'b11111110;	//*******  
			11'h323: data = 8'b11111110;	//*******
			11'h324: data = 8'b00000110;	//     **
			11'h325: data = 8'b00000110;	//     **
			11'h326: data = 8'b11111110;	//*******
			11'h327: data = 8'b11111110;	//*******
			11'h328: data = 8'b11000000;	//**
			11'h329: data = 8'b11000000;	//**
			11'h32a: data = 8'b11111110;	//*******
			11'h32b: data = 8'b11111110;	//*******
			11'h32c: data = 8'b00000000;	//
			11'h32d: data = 8'b00000000;	//
			11'h32e: data = 8'b00000000;	//
			11'h32f: data = 8'b00000000;	//
			// code x33 (3)
			11'h330: data = 8'b00000000;	//
			11'h331: data = 8'b00000000;	//
			11'h332: data = 8'b11111110;	//*******  
			11'h333: data = 8'b11111110;	//*******
			11'h334: data = 8'b00000110;	//     **
			11'h335: data = 8'b00000110;	//     **
			11'h336: data = 8'b00111110;	//  *****
			11'h337: data = 8'b00111110;	//  *****
			11'h338: data = 8'b00000110;	//     **
			11'h339: data = 8'b00000110;	//     **
			11'h33a: data = 8'b11111110;	//*******
			11'h33b: data = 8'b11111110;	//*******
			11'h33c: data = 8'b00000000;	//
			11'h33d: data = 8'b00000000;	//
			11'h33e: data = 8'b00000000;	//
			11'h33f: data = 8'b00000000;	//
			// code x34 (4)
			11'h340: data = 8'b00000000;	//
			11'h341: data = 8'b00000000;	//
			11'h342: data = 8'b11000110;	//**   **  
			11'h343: data = 8'b11000110;	//**   **
			11'h344: data = 8'b11000110;	//**   **
			11'h345: data = 8'b11000110;	//**   **
			11'h346: data = 8'b11111110;	//*******
			11'h347: data = 8'b11111110;	//*******
			11'h348: data = 8'b00000110;	//     **
			11'h349: data = 8'b00000110;	//     **
			11'h34a: data = 8'b00000110;	//     **
			11'h34b: data = 8'b00000110;	//     **
			11'h34c: data = 8'b00000000;	//
			11'h34d: data = 8'b00000000;	//
			11'h34e: data = 8'b00000000;	//
			11'h34f: data = 8'b00000000;	//
			// code x35 (5)
			11'h350: data = 8'b00000000;	//
			11'h351: data = 8'b00000000;	//
			11'h352: data = 8'b11111110;	//*******  
			11'h353: data = 8'b11111110;	//*******
			11'h354: data = 8'b11000000;	//**
			11'h355: data = 8'b11000000;	//**
			11'h356: data = 8'b11111110;	//*******
			11'h357: data = 8'b11111110;	//*******
			11'h358: data = 8'b00000110;	//     **
			11'h359: data = 8'b00000110;	//     **
			11'h35a: data = 8'b11111110;	//*******
			11'h35b: data = 8'b11111110;	//*******
			11'h35c: data = 8'b00000000;	//
			11'h35d: data = 8'b00000000;	//
			11'h35e: data = 8'b00000000;	//
			11'h35f: data = 8'b00000000;	//
			// code x36 (6)
			11'h360: data = 8'b00000000;	//
			11'h361: data = 8'b00000000;	//
			11'h362: data = 8'b11111110;	//*******  
			11'h363: data = 8'b11111110;	//*******
			11'h364: data = 8'b11000000;	//**
			11'h365: data = 8'b11000000;	//**
			11'h366: data = 8'b11111110;	//*******
			11'h367: data = 8'b11111110;	//*******
			11'h368: data = 8'b11000110;	//**   **
			11'h369: data = 8'b11000110;	//**   **
			11'h36a: data = 8'b11111110;	//*******
			11'h36b: data = 8'b11111110;	//*******
			11'h36c: data = 8'b00000000;	//
			11'h36d: data = 8'b00000000;	//
			11'h36e: data = 8'b00000000;	//
			11'h36f: data = 8'b00000000;	//
			// code x37 (7)
			11'h370: data = 8'b00000000;	//
			11'h371: data = 8'b00000000;	//
			11'h372: data = 8'b11111110;	//*******  
			11'h373: data = 8'b11111110;	//*******
			11'h374: data = 8'b00000110;	//     **
			11'h375: data = 8'b00000110;	//     **
			11'h376: data = 8'b00000110;	//     **
			11'h377: data = 8'b00000110;	//     **
			11'h378: data = 8'b00000110;	//     **
			11'h379: data = 8'b00000110;	//     **
			11'h37a: data = 8'b00000110;	//     **
			11'h37b: data = 8'b00000110;	//     **
			11'h37c: data = 8'b00000000;	//
			11'h37d: data = 8'b00000000;	//
			11'h37e: data = 8'b00000000;	//
			11'h37f: data = 8'b00000000;	//
			// code x38 (8)
			11'h380: data = 8'b00000000;	//
			11'h381: data = 8'b00000000;	//
			11'h382: data = 8'b11111110;	//*******  
			11'h383: data = 8'b11111110;	//*******
			11'h384: data = 8'b11000110;	//**   **
			11'h385: data = 8'b11000110;	//**   **
			11'h386: data = 8'b11111110;	//*******
			11'h387: data = 8'b11111110;	//*******
			11'h388: data = 8'b11000110;	//**   **
			11'h389: data = 8'b11000110;	//**   **
			11'h38a: data = 8'b11111110;	//*******
			11'h38b: data = 8'b11111110;	//*******
			11'h38c: data = 8'b00000000;	//
			11'h38d: data = 8'b00000000;	//
			11'h38e: data = 8'b00000000;	//
			11'h38f: data = 8'b00000000;	//
			// code x39 (9)
			11'h390: data = 8'b00000000;	//
			11'h391: data = 8'b00000000;	//
			11'h392: data = 8'b11111110;	//*******  
			11'h393: data = 8'b11111110;	//*******
			11'h394: data = 8'b11000110;	//**   **
			11'h395: data = 8'b11000110;	//**   **
			11'h396: data = 8'b11111110;	//*******
			11'h397: data = 8'b11111110;	//*******
			11'h398: data = 8'b00000110;	//     **
			11'h399: data = 8'b00000110;	//     **
			11'h39a: data = 8'b11111110;	//*******
			11'h39b: data = 8'b11111110;	//*******
			11'h39c: data = 8'b00000000;	//
			11'h39d: data = 8'b00000000;	//
			11'h39e: data = 8'b00000000;	//
			11'h39f: data = 8'b00000000;	//
			// code x3a (:)
			11'h3a0: data = 8'b00000000;	//
			11'h3a1: data = 8'b00000000;	//
			11'h3a2: data = 8'b00000000;	//
			11'h3a3: data = 8'b00000000;	//
			11'h3a4: data = 8'b00011000;	//   **
			11'h3a5: data = 8'b00011000;	//   **
			11'h3a6: data = 8'b00000000;	//
			11'h3a7: data = 8'b00000000;	//
			11'h3a8: data = 8'b00011000;	//   **
			11'h3a9: data = 8'b00011000;	//   **
			11'h3aa: data = 8'b00000000;	//   
			11'h3ab: data = 8'b00000000;	//   
			11'h3ac: data = 8'b00000000;	//
			11'h3ad: data = 8'b00000000;	//
			11'h3ae: data = 8'b00000000;	//
			11'h3af: data = 8'b00000000;	//
            
            default: data = 8'b00000000;
endcase
end
endmodule

module bin2bcd(
    input wire [4:0] bin,
    output wire [7:0] bcd
);

integer i;

// always @(bin) begin
//     bcd = 8'b0;
//     for (i = 0; i < 5; i = i + 1) begin
//         if (bcd[3:0] >= 5) begin
//             bcd[3:0] = bcd[3:0] + 3;
//         end
//         if (bcd[7:4] >= 5) begin
//             bcd[7:4] = bcd[7:4] + 3;
//         end
//         bcd = {bcd[6:0], bin[5-i]};
//     end
// end

reg [3:0] ones;
reg [3:0] tens;

always @(bin) begin
    ones = 4'b0;
    tens = 4'b0;

    for (i = 4; i >=0; i = i - 1) begin
        if (ones >= 5) begin
            ones = ones + 3;
        end
        if (tens >= 5) begin
            tens = tens + 3;
        end
        tens = {tens[2:0], ones[3]};
        ones = {ones[2:0], bin[i]};
    end
end
assign bcd = {tens, ones};

endmodule

module clock_divider(
    input wire clk,
    input wire rst,
    output reg clk_div
);
always @(posedge clk) begin
    if (rst) begin
        clk_div <= 1'b0;
    end else begin
        clk_div <= ~clk_div;
    end
end
    
endmodule

module dvi_module (
    input   wire          clk,
    input     wire        clk_locked,
    output wire AG,
    output wire AY,
    output wire AR,
    output wire BG,
    output wire BY,
    output wire BR,
    output wire       video_hsync,
    output wire       video_vsync,
    output wire       video_clk,
    output wire       video_de,

    input wire [79:0] line_0_ascii,
    input wire [79:0] line_1_ascii
//    input wire [ 4:0] line_2_number,
//    output wire [15:0] line_2_ascii_to_top

);

//  assign line_2_ascii_to_top = line_2_ascii[15:0];
//  wire [ 7:0] line_2_bcd;
//  wire [79:0] line_2_ascii;
//  bin2bcd bcd_inst (
 //     .bin(line_2_number),
 //     .bcd(line_2_bcd)
//  );

//  assign line_2_ascii[7:0]  = line_2_bcd[3:0] + 8'h30;
//  assign line_2_ascii[15:8]  = line_2_bcd[7:4] + 8'h30;
//  assign line_2_ascii[79:16] = 64'h0;

  // display sync signals and coordinaties
  localparam CORDW = 10;  // screen coordinate width in bits
  logic [CORDW-1:0] sx, sy;
  logic hsync, vsync, de;
  simple_480p display_inst (
      .clk_pix(clk),
      .rst_pix(clk_locked),  // wait for clock lock
      .sx,
      .sy,
      .hsync,
      .vsync,
      .de
  );

  wire [3:0] column_from_left;
  wire [3:0] line_from_top;
  localparam MAX_COLUMN = 10;
  localparam MAX_LINE = 3;
  assign column_from_left = sx[9:6]; // 64 bit per column, 640 / 64 = 10 columns (MAX column) 4'b1010
  assign line_from_top = sy[9:7];  // 480 / 128 = 3 lines (MAX line) 4'b0011

  wire [7:0] ascii;
  // wire []
  wire [6:0] column_location;
  assign column_location = column_from_left << 3;
  assign ascii = (line_from_top == 0) ? line_0_ascii[79-column_location -: 8] :
               (line_from_top == 1) ? line_1_ascii[79-column_location -: 8] :
               //(line_from_top == 2) ? line_2_ascii[79-column_location -: 8] :
              8'b0;

  wire [7:0] ascii_rom_line;

  wire [2:0] ascii_column;
  wire [3:0] ascii_line;
  assign ascii_column = sx[5:3];
  assign ascii_line = sy[6:3];

  ascii_rom_async ascii_rom_inst (
      .addr({ascii[6:0], ascii_line}),
      .data(ascii_rom_line)
  );

  wire draw_ascii;
  assign draw_ascii = ascii_rom_line[7-ascii_column];

  // paint colour: yellow lines, blue background
  logic [3:0] paint_r, paint_g, paint_b;
  always_comb begin
    paint_r = (draw_ascii) ? 4'hF : 4'h1;
    paint_g = (draw_ascii) ? 4'hC : 4'h3;
    paint_b = (draw_ascii) ? 4'h0 : 4'h7;
  end

  // display colour: paint colour but black in blanking interval
  logic [3:0] display_r, display_g, display_b;
  always_comb begin
    display_r = (de) ? paint_r : 4'h0;
    display_g = (de) ? paint_g : 4'h0;
    display_b = (de) ? paint_b : 4'h0;
  end

  reg vga_hsync, vga_vsync;
  reg [3:0] vga_r, vga_g, vga_b;
  // VGA Pmod output
  always_ff @(posedge clk) begin
    vga_hsync <= hsync;
    vga_vsync <= vsync;
    vga_r <= display_r;
    vga_g <= display_g;
    vga_b <= display_b;
  end

  assign video_clk   = clk;
  assign video_hsync = hsync;
  assign video_vsync = vsync;
  assign AR=display_r[3:0];
  assign BR=display_r[3:1];
  assign BG=display_g[3:0];
  assign AG=display_g[3:1];
  assign AY=display_b[3:0];
  assign BY=display_b[3:1];
  assign video_de    = de;

endmodule


module simple_480p (
    input  wire logic clk_pix,  // pixel clock
    input  wire logic rst_pix,  // reset in pixel clock domain   
    output      logic [9:0] sx, // horizontal screen position
    output      logic [9:0] sy, // vertical screen position
    output      logic hsync,    // horizontal sync
    output      logic vsync,    // vertical sync
    output      logic de        // data enable (low in blanking interval)
);
    // horizontal timings
    parameter HA_END = 639;          // end of active pixels
    parameter HS_STA = HA_END + 16; // sync starts after front porch 655
    parameter HS_END = HS_STA + 96; // SYNC ENDS 
    parameter LINE   = 799;         // last pixel on line (after back porch)

    // vertical timings
    parameter VA_END = 479;         // end of active pixels
    parameter VS_STA = VA_END + 10; // sync starts after front porch
    parameter VS_END = VS_STA + 2;  // sync ends
    parameter SCREEN = 524;         // last line on screen (after back porch)

    always_comb begin
        hsync = ~(sx >= HS_STA && sx < HS_END); // invert: negative polarity
        vsync = ~(sy >= VS_STA && sy < VS_END); // invert: negative polarity
        de = (sx <= HA_END && sy <= VA_END);
    end

    // CALCULATE HORIZONTAL AND VERTICAL SCREEN POSTITION
    always_ff @(posedge clk_pix) begin
        if (sx == LINE) begin // last pixel on line ?
            sx <= 0;
            sy <= (sy == SCREEN) ? 0 : sy + 1; // last line on screen ?
        end else begin
            sx <= sx + 1;
        end

        if (rst_pix) begin
            sx <= 0;
            sy <= 0;
        end
    end

endmodule

//module test_bin2bcd;

//    reg [4:0] bin;
//    wire [7:0] bcd;

//    // Instantiate the module
//    bin2bcd u_bin2bcd (
//        .bin(bin),
//        .bcd(bcd)
//    );

//    initial begin
//        // Test case 1: binary 0
//        bin = 5'b00000;
//        #10;
//        $display("bin: %b, bcd: %b", bin, bcd);

//        // Test case 2: binary 10
//        bin = 5'b01010;
//        #10;
//        $display("bin: %b, bcd: %b", bin, bcd);

//        // Test case 3: binary 31
//        bin = 5'b11111;
//        #10;
//        $display("bin: %b, bcd: %b", bin, bcd);

//        // Add more test cases as needed
//    end

//endmodule

对应引脚直接参考我专栏里那篇写引脚的文章,不需要改动

  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值