首页 热点资讯 义务教育 高等教育 出国留学 考研考公
您的当前位置:首页正文

FPGA实验三-液晶屏的显示设计

2022-03-04 来源:华拓网
 . 专业:__电子信息工程__姓名:_____陈华杰_____ 实验报告 学号:______ 日期:___4月4日___ 地点:应电楼303桌号2组

课程名称:_____FPGA实验______指导老师:__竺红卫/陈宏__成绩:__________________ 实验名称:____液晶屏的显示设计______实验类型:_FPGA实验_同组学生姓名:__

一、实验目的

1. 熟悉实验板上液晶屏的工作原理; 2. 熟悉驱动电路的源代码。

二、实验装置 1. 电脑一台; 2. 实验板一块; 3. 实验板电源一只;

4. 实验板连接电脑的下载线一根。

三、实验原理

实验板显著的特征是2 线16 字符液晶显示器LCD。尽管LCD 支持8 位的数据接口,为了与其它的XILINX 的开发板保持兼容并且尽可能减少针脚数, FPGA 仅通过4 位的数据接口线控制LCD, LCD 通过使用ASCII 标准和自定义字符可以有效地显示多种信息。但是,这些显示速度并不是很快。每半秒扫描一次以测试实际清晰度的界限。与50MHz 时钟频率相比,这样的显示速度是慢的。 PicoBlaze 处理器可以有效地控制显示时间和显示内容。

.

字符 LCD 的供电电压是+5V。 FPGA 的I/O 口信号的电压是3.3V。但是, FPGA 的输出电平是通过LCD 来识别是有效的低电平还是高电平。 LCD 控制器接收5V TTL 信号电平, FPGA输出3.3V 的LCMOS 以满足5V TTL 电压要求。数据线上的390 欧串联电阻,当LCD 驱动一个逻辑高电平时,其用来防止了FPGA 和SrtataFlsah I/O 管脚的超负载。当LCD_RW 为高时, LCD驱动数据线。在绝大多数应用中, LCD作为只读外围设备,几乎没有从显示器读数据。

四、操作方法和实验步骤

对于程序的各个步骤,如新建项目、新建Verilog HDL、新建.ucf文件、Synthesize、Implement Design、Generate Programming File、Configure Target Device等等,在实验一中已经展示过,每一次实验的基本操作步骤都是差不多的,故这里不再重复阐述。

本次实验总共需要做三份程序并观察现象: 1)例程

.

2)设计按键拨动时显示小时、分钟和秒,中间分别空一格。

3)按键拨动开始显示,10秒钟显示结束,结束时LCD上显示ABCDEF,同时八只LED灯亮。

五、实验源代码和现象 1)例程

UCF文件如下:

NET \"CLK_50MHZ\" LOC=\"C9\"; NET \"LCD_D<0>\" LOC=\"R15\"; NET \"LCD_D<1>\" LOC=\"R16\"; NET \"LCD_D<2>\" LOC=\"P17\"; NET \"LCD_D<3>\" LOC=\"M15\"; NET \"LCD_E\" LOC=\"M18\"; NET \"LCD_RS\" LOC=\"L18\"; NET \"LCD_RW\" LOC=\"L17\";

源代码如下:

module lcd_write_number_test (

input CLK_50MHZ, output LCD_E, output LCD_RS, output LCD_RW, output [3:0] LCD_D

.

);

wire if_ready; reg if_write; reg [31:0] if_data; reg [1:0] state; reg [31:0] cntr;

parameter IDLE = 2'b00, IF_WRITE_1 = 2'b01, SET_IF_WRITE_0 = 2'b10, WAIT = 2'b11;

// Instantiate the Unit Under Test (UUT) lcd_write_number uut (

.CLK_50MHZ(CLK_50MHZ), .LCD_E(LCD_E), .LCD_RS(LCD_RS), .LCD_RW(LCD_RW), .LCD_D(LCD_D), .if_data(if_data), .if_write(if_write), .if_ready(if_ready) );

.

initial begin

if_data <= 32'habba0123; state <= IDLE; if_write <= 1'b0; cntr <= 32'b0; end

always@ (posedge CLK_50MHZ) begin case (state) IDLE:

if (if_ready) begin if_data <= if_data + 1'b1; if_write <= 1'b1; state <= IF_WRITE_1; cntr <= 32'b0; end

IF_WRITE_1: // this state to keep if_write up for 2 cycles state <= SET_IF_WRITE_0;

SET_IF_WRITE_0: // set if_write 0 and start the counter begin

if_write <= 1'b0; state <= WAIT; cntr <= 32'b0;

.

end WAIT:

if (cntr < 25000000) // wait for 0.5 seconds cntr <= cntr + 32'b1; else

state <= IDLE; endcase end endmodule

`timescale 1ns / 1ps module lcd_write_number (

input CLK_50MHZ, output LCD_E, output LCD_RS, output LCD_RW, output [3:0] LCD_D, input [31:0] if_data, input if_write, output if_ready );

.

reg [7:0] disp_data; reg disp_rs;

reg [31:0] disp_delay; reg disp_write; wire disp_ready; reg disp_b8; reg [7:0] char; reg [1:0] state; reg [31:0] number; reg init_done; reg running; reg [4:0] shift_cntr; reg if_ready_r;

assign if_ready = if_ready_r; lcd_display display (.clk(CLK_50MHZ), .rst(1'b0), .lcd_e(LCD_E), .lcd_rw(LCD_RW), .lcd_rs(LCD_RS), .lcd_d(LCD_D), .if_data(disp_data),

.

.if_rs(disp_rs), .if_delay(disp_delay), .if_write(disp_write), .if_ready(disp_ready), .if_8bit(disp_b8) );

parameter NB_CHARS = 8'd12; parameter START = 2'b00, WAIT_WRITE_0 = 2'b01, WRITE_1 = 2'b10, WAIT_WRITE_1 = 2'b11; initial begin state <= 2'b00; char <= 8'b0; init_done <= 1'b0; if_ready_r <= 1'b0; shift_cntr <= 5'b0; end

always@ (posedge CLK_50MHZ) begin if (init_done && char > 8'd16) begin if (disp_ready) if_ready_r <= 1'b1;

.

if (if_write) begin

char <= 4'd8; // reset the display end

end else if (char <= 8'd16) begin if_ready_r <= 1'b0; case (state) START:

if (disp_ready) begin disp_write <= 1'b1; state <= WAIT_WRITE_0; end

WAIT_WRITE_0: state <= WRITE_1; WRITE_1: begin

disp_write <= 1'b0; state <= 2'b11; end

WAIT_WRITE_1: begin

state <=START; char <= char + 8'b1;

.

end

endcase // case (state) end // else: !if(!running)

end // always@ (posedge CLK_50MHZ) always@ (negedge CLK_50MHZ) begin // these next steps initialize the LCD display: case (char) 0: begin

disp_b8 <= 1'b0; disp_data <= 8'h30;

disp_delay <= 32'd10000000; disp_rs <= 1'b0; end

1: disp_data <= 8'h30; 2: begin

disp_data <= 8'h30; disp_delay <= 32'd1000000; end 3: begin

.

disp_data <= 8'h20; disp_delay <= 32'd20000; end 4: begin

disp_b8 <= 1'b1; disp_data <= 8'h28; end

5: disp_data <= 8'h06; 6: disp_data <= 8'h0C; 7: begin

disp_data <= 8'h01; disp_delay <= 32'd1000000; init_done <= 1'b1; shift_cntr <= 5'd9; end

8: // this state provides an entry point to reset the display and then // go on to the default state that writes the number begin

disp_rs <= 1'b0; disp_data <= 8'h01;

.

disp_delay <= 32'd1000000; shift_cntr <= 5'b0; number <= if_data; end default:

// state machine to print a 32-bit number out if (disp_ready && state == START) begin if (shift_cntr < 5'd8) begin disp_rs <= 1'b1;

disp_delay <= 32'd20000; if (number[31:28] < 4'b1010)

disp_data <= number[31:28] + 8'h30; else

disp_data <= number[31:28] + 8'h37; number <= number << 4; shift_cntr <= shift_cntr + 5'b1; end end

endcase // case (char)

end // always@ (negedge CLK_50MHZ) endmodule

.

`timescale 1ns / 1ps module lcd_display (input clk, input rst, output lcd_e, output lcd_rw, output lcd_rs, output [3:0] lcd_d, input [7:0] if_data, input if_rs,

input [31:0] if_delay, input if_write, output if_ready, input if_8bit); reg [2:0] state; reg lcdr_e; reg [3:0] lcdr_d; reg [31:0] wait_cntr; reg ready; reg init_done;

parameter IDLE = 3'b000, WAIT_PULSE_E_0 = 3'b001,

.

LOAD_LOWER_NIBBLE = 3'b010, WAIT_PULSE_E_1 = 3'b011, WAIT_COMMAND = 3'b100; parameter PULSE_E_DLY = 32'd12; parameter INIT_TIME = 32'd20000000; assign lcd_d = lcdr_d; assign lcd_rs = if_rs; assign lcd_rw = 1'b0; assign lcd_e = lcdr_e; assign if_ready = ready; initial begin state <= IDLE; ready <= 1'b0; lcdr_e <= 1'b0; init_done <= 1'b0; end

always@ (posedge clk) begin if (rst) begin state <= IDLE;

end else if (!init_done) begin if (wait_cntr < INIT_TIME) wait_cntr <= wait_cntr + 1;

.

else begin init_done <= 1'b1; ready <= 1'b1; end

end else begin case (state) IDLE: begin

if (if_write) begin lcdr_e <= 1'b1;

lcdr_d <= if_data[7:4]; // upper nibble first ready <= 1'b0; wait_cntr <= 32'b0; state <= WAIT_PULSE_E_0; end end

WAIT_PULSE_E_0:

if (wait_cntr < PULSE_E_DLY) begin wait_cntr <= wait_cntr + 1; end else begin lcdr_e <= 1'b0; wait_cntr <= 0;

.

if (if_8bit)

state <= LOAD_LOWER_NIBBLE; else

state <= WAIT_COMMAND; end

LOAD_LOWER_NIBBLE:

if (wait_cntr < PULSE_E_DLY) begin wait_cntr <= wait_cntr + 1; end else begin wait_cntr <= 0; lcdr_e <= 1'b1;

lcdr_d <= if_data[3:0]; // lower nibble state <= WAIT_PULSE_E_1; end

WAIT_PULSE_E_1:

if (wait_cntr < PULSE_E_DLY) begin wait_cntr <= wait_cntr + 1; end else begin lcdr_e <= 1'b0; wait_cntr <= 0;

state <= WAIT_COMMAND; end

.

WAIT_COMMAND:

if (wait_cntr < if_delay) begin wait_cntr <= wait_cntr + 32'b1; end else begin wait_cntr <= 0; if (!if_write) begin state <= IDLE; ready <= 1'b1; end end

endcase // case (state) end end endmodule

共有三个module,它们的包含关系为lcd_write_number_test包含lcd_write_number,lcd_write_number包含lcd_display,下同。

实验现象:

如下图,刚烧录程序完时,LCD前8位依次显示十六进制数“ABBA0123”,然后每过0.5秒,该数值增一,满十六进位。

.

.

2)设计按键拨动时显示小时、分钟和秒,中间分别空一格。

UCF文件如下:

NET \"CLK_50MHZ\" LOC=\"C9\"; NET \"LCD_D<0>\" LOC=\"R15\"; NET \"LCD_D<1>\" LOC=\"R16\"; NET \"LCD_D<2>\" LOC=\"P17\"; NET \"LCD_D<3>\" LOC=\"M15\"; NET \"LCD_E\" LOC=\"M18\"; NET \"LCD_RS\" LOC=\"L18\"; NET \"LCD_RW\" LOC=\"L17\"; NET \"SW1\" LOC=\"L14\";

源代码如下:

module lcd_write_number_test (

input SW1, input CLK_50MHZ, output LCD_E, output LCD_RS, output LCD_RW, output [3:0] LCD_D );

wire if_ready;

.

reg if_write; reg [31:0] if_data; reg [1:0] state; reg [31:0] cntr;

parameter IDLE = 2'b00, IF_WRITE_1 = 2'b01, SET_IF_WRITE_0 = 2'b10, WAIT = 2'b11;

// Instantiate the Unit Under Test (UUT)

lcd_write_number uut (

.SW1(SW1),

.CLK_50MHZ(CLK_50MHZ), .LCD_E(LCD_E), .LCD_RS(LCD_RS), .LCD_RW(LCD_RW), .LCD_D(LCD_D), .if_data(if_data), .if_write(if_write), .if_ready(if_ready) );

.

initial begin

if_data <= 32'h19044012; state <= IDLE; if_write <= 1'b0; cntr <= 32'b0; end

always@ (posedge CLK_50MHZ) begin case (state) IDLE: if (if_ready) begin

if(if_data[31:0]==32'h23059059)if_data <= 32'h0;

else if(if_data[27:0]==28'h9059059)if_data <= if_data + 32'h6fa6fa7; else if(if_data[19:0]==20'h59059)if_data <= if_data + 32'hfa6fa7; else if(if_data[15:0]==16'h9059)if_data <= if_data + 32'h6fa7; else if(if_data[7:0]==8'h59)if_data <= if_data + 32'hfa7; else if(if_data[3:0]==4'h9)if_data <= if_data + 32'h7; else if_data <= if_data + 1'b1;

.

if_write <= 1'b1; state <= IF_WRITE_1; cntr <= 32'b0; end

IF_WRITE_1: // this state to keep if_write up for 2 cycles state <= SET_IF_WRITE_0;

SET_IF_WRITE_0: // set if_write 0 and start the counter begin

if_write <= 1'b0; state <= WAIT; cntr <= 32'b0; end WAIT:

if (cntr < 50000000) // wait for 1 seconds cntr <= cntr + 32'b1; else

state <= IDLE; endcase

.

end endmodule

`timescale 1ns / 1ps module lcd_display (input clk, input rst, output lcd_e, output lcd_rw, output lcd_rs, output [3:0] lcd_d, input [7:0] if_data, input if_rs,

input [31:0] if_delay, input if_write, output if_ready, input if_8bit); reg [2:0] state; reg lcdr_e; reg [3:0] lcdr_d; reg [31:0] wait_cntr; reg ready;

.

reg init_done;

parameter IDLE = 3'b000, WAIT_PULSE_E_0 = 3'b001, LOAD_LOWER_NIBBLE = 3'b010, WAIT_PULSE_E_1 = 3'b011, WAIT_COMMAND = 3'b100;

parameter PULSE_E_DLY = 32'd12; parameter INIT_TIME = 32'd20000000; assign lcd_d = lcdr_d; assign lcd_rs = if_rs; assign lcd_rw = 1'b0; assign lcd_e = lcdr_e; assign if_ready = ready;

initial begin state <= IDLE; ready <= 1'b0; lcdr_e <= 1'b0; init_done <= 1'b0; end

.

always@ (posedge clk) begin if (rst) begin state <= IDLE;

end else if (!init_done) begin if (wait_cntr < INIT_TIME) wait_cntr <= wait_cntr + 1; else begin init_done <= 1'b1; ready <= 1'b1; end

end else begin case (state) IDLE: begin

if (if_write) begin lcdr_e <= 1'b1;

lcdr_d <= if_data[7:4]; // upper nibble first ready <= 1'b0; wait_cntr <= 32'b0; state <= WAIT_PULSE_E_0; end end

.

WAIT_PULSE_E_0:

if (wait_cntr < PULSE_E_DLY) begin wait_cntr <= wait_cntr + 1; end else begin lcdr_e <= 1'b0; wait_cntr <= 0; if (if_8bit)

state <= LOAD_LOWER_NIBBLE; else

state <= WAIT_COMMAND; end

LOAD_LOWER_NIBBLE:

if (wait_cntr < PULSE_E_DLY) begin wait_cntr <= wait_cntr + 1; end else begin wait_cntr <= 0; lcdr_e <= 1'b1;

lcdr_d <= if_data[3:0]; // lower nibble state <= WAIT_PULSE_E_1; end

WAIT_PULSE_E_1:

if (wait_cntr < PULSE_E_DLY) begin

.

wait_cntr <= wait_cntr + 1; end else begin lcdr_e <= 1'b0; wait_cntr <= 0;

state <= WAIT_COMMAND; end

WAIT_COMMAND:

if (wait_cntr < if_delay) begin wait_cntr <= wait_cntr + 32'b1; end else begin wait_cntr <= 0; if (!if_write) begin state <= IDLE; ready <= 1'b1; end end

endcase // case (state) end end endmodule

`timescale 1ns / 1ps

.

module lcd_write_number (

input CLK_50MHZ, input SW1, output LCD_E, output LCD_RS, output LCD_RW, output [3:0] LCD_D, input [31:0] if_data, input if_write, output if_ready );

reg [7:0] disp_data; reg disp_rs;

reg [31:0] disp_delay; reg disp_write; wire disp_ready; reg disp_b8; reg [7:0] char; reg [1:0] state; reg [31:0] number; reg init_done;

.

reg running; reg [4:0] shift_cntr; reg if_ready_r;

assign if_ready = if_ready_r; lcd_display display (.clk(CLK_50MHZ), .rst(1'b0), .lcd_e(LCD_E), .lcd_rw(LCD_RW), .lcd_rs(LCD_RS), .lcd_d(LCD_D), .if_data(disp_data), .if_rs(disp_rs), .if_delay(disp_delay), .if_write(disp_write), .if_ready(disp_ready), .if_8bit(disp_b8) );

parameter NB_CHARS = 8'd12; parameter START = 2'b00,

.

WAIT_WRITE_0 = 2'b01, WRITE_1 = 2'b10, WAIT_WRITE_1 = 2'b11;

initial begin

state <= 2'b00; char <= 8'b0; init_done <= 1'b0; if_ready_r <= 1'b0; shift_cntr <= 5'b0; end

always@ (posedge CLK_50MHZ) begin

if (init_done && char > 8'd16) begin

if (disp_ready) if_ready_r <= 1'b1; if (if_write) begin

char <= 4'd8; // reset the display

.

end end

else if (char <= 8'd16) begin if_ready_r <= 1'b0; case (state)

START:

if (disp_ready) begin disp_write <= 1'b1; state <= WAIT_WRITE_0; end

WAIT_WRITE_0: state <= WRITE_1;

WRITE_1: begin

disp_write <= 1'b0; state <= 2'b11; end

WAIT_WRITE_1:

.

begin

state <= START; char <= char + 8'b1; end

endcase // case (state) end // else: !if(!running)

end // always@ (posedge CLK_50MHZ)

always@ (negedge CLK_50MHZ) begin // these next steps initialize the LCD display: case (char) 0: begin

disp_b8 <= 1'b0; disp_data <= 8'h30;

disp_delay <= 32'd10000000; disp_rs <= 1'b0; end

1: disp_data <= 8'h30;

.

2: begin

disp_data <= 8'h30; disp_delay <= 32'd1000000; end 3: begin

disp_data <= 8'h20; disp_delay <= 32'd20000; end 4: begin

disp_b8 <= 1'b1; disp_data <= 8'h28; end

5: disp_data <= 8'h06;

6: disp_data <= 8'h0C;

.

7: begin

disp_data <= 8'h01; disp_delay <= 32'd1000000; init_done <= 1'b1; shift_cntr <= 5'd9; end

8: // this state provides an entry point to reset the display and then // go on to the default state that writes the number begin

disp_rs <= 1'b0; disp_data <= 8'h01; disp_delay <= 32'd1000000; shift_cntr <= 5'b0; number <= if_data; end default:

// state machine to print a 32-bit number out if (SW1) begin

.

if (disp_ready && state == START) begin if (shift_cntr < 5'd8) begin disp_rs <= 1'b1;

disp_delay <= 32'd20000;

if((shift_cntr == 5'd2) || (shift_cntr == 5'd5))

begin

disp_data <= 8'h20; end else

begin

if (number[31:28] < 4'b1010)

disp_data <= number[31:28] + 8'h30; else

disp_data <= number[31:28] + 8'h37;

end

number <= number << 4;

shift_cntr <= shift_cntr + 5'b1; end end end

endcase // case (char)

.

end // always@ (negedge CLK_50MHZ) endmodule

实验现象:

当SW1为低电平时,LCD无显示。SW1向上拨后,如下图,LCD显示小时、分钟和秒,中间分别空一格,且该输出显示会按照时钟的样式计时、刷新,每过一秒钟秒位进一,秒的个位满10进位,秒数满60则分数增一……当SW1再次向下拨,LCD显示关闭,但始终仍然在计时。

程序刚烧进板子时,时钟的初始时间是人为设定的19时44分12秒。

.

3)按键拨动开始显示,10秒钟显示结束,结束时LCD上显示ABCDEF,同时八只LED灯亮。

UCF文件如下:

NET \"CLK_50MHZ\" LOC=\"C9\"; NET \"LCD_D<0>\" LOC=R15; NET \"LCD_D<1>\" LOC=R16; NET \"LCD_D<2>\" LOC=P17; NET \"LCD_D<3>\" LOC=M15; NET \"LCD_E\" LOC=M18; NET \"LCD_RS\" LOC=L18; NET \"LCD_RW\" LOC=L17; NET \"SW1\" LOC=L14; NET \"LED0\" LOC=F12; NET \"LED1\" LOC=E12; NET \"LED2\" LOC=E11; NET \"LED3\" LOC=F11; NET \"LED4\" LOC=C11; NET \"LED5\" LOC=D11; NET \"LED6\" LOC=E9; NET \"LED7\" LOC=F9;

源代码如下:

module lcd_write_number_test (

.

input CLK_50MHZ, input SW1, output LCD_E, output LCD_RS, output LCD_RW, output [3:0] LCD_D, output LED0, output LED1, output LED2, output LED3, output LED4, output LED5, output LED6, output LED7 );

wire if_ready; reg if_write; reg [31:0] if_data; reg [1:0] state; reg [31:0] cntr;

parameter IDLE = 2'b00, IF_WRITE_1 = 2'b01,

.

SET_IF_WRITE_0 = 2'b10, WAIT = 2'b11;

// Instantiate the Unit Under Test (UUT)

lcd_write_number uut (

.SW1(SW1),

.CLK_50MHZ(CLK_50MHZ), .LCD_E(LCD_E), .LCD_RS(LCD_RS), .LCD_RW(LCD_RW), .LCD_D(LCD_D), .if_data(if_data), .if_write(if_write), .if_ready(if_ready), .LED0(LED0), .LED1(LED1), .LED2(LED2), .LED3(LED3), .LED4(LED4), .LED5(LED5), .LED6(LED6),

.

.LED7(LED7) ); initial begin

if_data <= 32'h19044012; state <= IDLE; if_write <= 1'b0; cntr <= 32'b0; end

always@ (posedge CLK_50MHZ) begin case (state) IDLE: if (if_ready) begin

if(if_data[31:0]==32'h23059059)if_data <= 32'h0;

else if(if_data[27:0]==28'h9059059)if_data <= if_data + 32'h6fa6fa7; else if(if_data[19:0]==20'h59059)if_data <= if_data + 32'hfa6fa7; else if(if_data[15:0]==16'h9059)if_data <= if_data + 32'h6fa7; else if(if_data[7:0]==8'h59)if_data <= if_data + 32'hfa7;

.

else if(if_data[3:0]==4'h9)if_data <= if_data + 32'h7; else if_data <= if_data + 1'b1; if_write <= 1'b1; state <= IF_WRITE_1; cntr <= 32'b0; end

IF_WRITE_1: // this state to keep if_write up for 2 cycles state <= SET_IF_WRITE_0;

SET_IF_WRITE_0: // set if_write 0 and start the counter begin

if_write <= 1'b0; state <= WAIT; cntr <= 32'b0; end WAIT:

if (cntr < 50000000) // wait for 1 seconds cntr <= cntr + 32'b1; else

state <= IDLE;

.

endcase end endmodule

`timescale 1ns / 1ps module lcd_write_number (

input CLK_50MHZ, input SW1, output LCD_E, output LCD_RS, output LCD_RW, output [3:0] LCD_D, output LED0, output LED1, output LED2, output LED3, output LED4, output LED5, output LED6, output LED7,

.

input [31:0] if_data, input if_write, output if_ready );

reg [7:0] disp_data; reg disp_rs;

reg [31:0] disp_delay; reg disp_write; wire disp_ready; reg disp_b8; reg [7:0] char; reg [1:0] state; reg [31:0] number; reg init_done; reg running; reg [4:0] shift_cntr; reg if_ready_r; reg [28:0] cnt; reg cnt_state; reg light;

assign if_ready = if_ready_r;

.

lcd_display display (.clk(CLK_50MHZ), .rst(1'b0), .lcd_e(LCD_E), .lcd_rw(LCD_RW), .lcd_rs(LCD_RS), .lcd_d(LCD_D), .if_data(disp_data), .if_rs(disp_rs), .if_delay(disp_delay), .if_write(disp_write), .if_ready(disp_ready), .if_8bit(disp_b8) );

parameter NB_CHARS = 8'd12; parameter START = 2'b00, WAIT_WRITE_0 = 2'b01, WRITE_1 = 2'b10, WAIT_WRITE_1 = 2'b11;

initial

.

begin

state <= 2'b00; char <= 8'b0; init_done <= 1'b0; if_ready_r <= 1'b0; shift_cntr <= 5'b0; cnt_state <= 1'b0; cnt <= 29'b0; light <= 1'b0; end

always@ (posedge CLK_50MHZ) begin

if (init_done && char > 8'd16) begin

if (disp_ready) if_ready_r <= 1'b1; if (if_write) begin

char <= 4'd8; // reset the display end end

.

else if (char <= 8'd16) begin if_ready_r <= 1'b0; case (state)

START:

if (disp_ready) begin disp_write <= 1'b1; state <= WAIT_WRITE_0; end

WAIT_WRITE_0: state <= WRITE_1;

WRITE_1: begin

disp_write <= 1'b0; state <= 2'b11; end

WAIT_WRITE_1: begin

state <= START;

.

char <= char + 8'b1; end

endcase // case (state) end // else: !if(!running)

end // always@ (posedge CLK_50MHZ)

always@ (posedge CLK_50MHZ) if (!SW1) begin cnt <= 29'b0; cnt_state<=1'b0; end

else if (cnt==29'h1dcd6500) cnt_state<=1'b1; else cnt <= cnt+1'b1;

always@ (negedge CLK_50MHZ) begin // these next steps initialize the LCD display: case (char) 0: begin

disp_b8 <= 1'b0;

.

disp_data <= 8'h30;

disp_delay <= 32'd10000000; disp_rs <= 1'b0; end

1: disp_data <= 8'h30; 2: begin

disp_data <= 8'h30; disp_delay <= 32'd1000000; end 3: begin

disp_data <= 8'h20; disp_delay <= 32'd20000; end 4: begin

disp_b8 <= 1'b1;

.

disp_data <= 8'h28; end

5: disp_data <= 8'h06;

6: disp_data <= 8'h0C; 7: begin

disp_data <= 8'h01; disp_delay <= 32'd1000000; init_done <= 1'b1; shift_cntr <= 5'd9; end

8: // this state provides an entry point to reset the display and then // go on to the default state that writes the number begin

disp_rs <= 1'b0; disp_data <= 8'h01; disp_delay <= 32'd1000000; shift_cntr <= 5'b0;

.

number <= if_data; end default:

// state machine to print a 32-bit number out if (SW1 && (!cnt_state))

begin

if (disp_ready && state == START)

begin

if (shift_cntr < 5'd8)

begin

disp_rs <= 1'b1;

disp_delay <= 32'd20000;

if((shift_cntr == 5'd2) || (shift_cntr == 5'd5))

disp_data <= 8'h20; else

begin

if (number[31:28] < 4'b1010)

disp_data <= number[31:28] + 8'h30; else

.

disp_data <= number[31:28] + 8'h37;

end

number <= number << 4;

shift_cntr <= shift_cntr + 5'b1;

end end

light <= 1'b0; end

else if (SW1 && cnt_state)

begin

if (disp_ready && state == START)

if (shift_cntr < 5'd8)

begin begin

disp_rs <= 1'b1;

disp_delay <= 32'd20000;

if((shift_cntr == 5'd2) || (shift_cntr == 5'd5)) disp_data <= 8'h20; else if(shift_cntr == 5'd0)

disp_data <= 8'h41;

.

else if(shift_cntr == 5'd1)

disp_data <= 8'h42;

else if(shift_cntr == 5'd3)

disp_data <= 8'h43;

else if(shift_cntr == 5'd4)

disp_data <= 8'h44;

else if(shift_cntr == 5'd6)

disp_data <= 8'h45;

else if(shift_cntr == 5'd7)

disp_data <= 8'h46;

end

shift_cntr <= shift_cntr + 5'b1;

light <= 1'b1;

end end

else

light <= 1'b0;

endcase // case (char)

.

end // always@ (negedge CLK_50MHZ) assign LED0 = light; assign LED1 = light; assign LED2 = light; assign LED3 = light; assign LED4 = light; assign LED5 = light; assign LED6 = light; assign LED7 = light; endmodule

`timescale 1ns / 1ps module lcd_display (input clk, input rst, output lcd_e, output lcd_rw, output lcd_rs, output [3:0] lcd_d, input [7:0] if_data, input if_rs,

input [31:0] if_delay,

.

input if_write, output if_ready, input if_8bit); reg [2:0] state; reg lcdr_e; reg [3:0] lcdr_d; reg [31:0] wait_cntr; reg ready; reg init_done;

parameter IDLE = 3'b000, WAIT_PULSE_E_0 = 3'b001, LOAD_LOWER_NIBBLE = 3'b010, WAIT_PULSE_E_1 = 3'b011, WAIT_COMMAND = 3'b100;

parameter PULSE_E_DLY = 32'd12; parameter INIT_TIME = 32'd20000000; assign lcd_d = lcdr_d; assign lcd_rs = if_rs; assign lcd_rw = 1'b0; assign lcd_e = lcdr_e; assign if_ready = ready;

.

initial begin state <= IDLE; ready <= 1'b0; lcdr_e <= 1'b0; init_done <= 1'b0; end

always@ (posedge clk) begin if (rst) begin state <= IDLE;

end else if (!init_done) begin if (wait_cntr < INIT_TIME) wait_cntr <= wait_cntr + 1; else begin init_done <= 1'b1; ready <= 1'b1; end

end else begin case (state) IDLE: begin

.

if (if_write) begin lcdr_e <= 1'b1;

lcdr_d <= if_data[7:4]; // upper nibble first ready <= 1'b0; wait_cntr <= 32'b0; state <= WAIT_PULSE_E_0; end end

WAIT_PULSE_E_0:

if (wait_cntr < PULSE_E_DLY) begin wait_cntr <= wait_cntr + 1; end else begin lcdr_e <= 1'b0; wait_cntr <= 0; if (if_8bit)

state <= LOAD_LOWER_NIBBLE; else

state <= WAIT_COMMAND; end

LOAD_LOWER_NIBBLE:

if (wait_cntr < PULSE_E_DLY) begin wait_cntr <= wait_cntr + 1;

.

end else begin wait_cntr <= 0; lcdr_e <= 1'b1;

lcdr_d <= if_data[3:0]; // lower nibble state <= WAIT_PULSE_E_1; end

WAIT_PULSE_E_1:

if (wait_cntr < PULSE_E_DLY) begin wait_cntr <= wait_cntr + 1; end else begin lcdr_e <= 1'b0; wait_cntr <= 0;

state <= WAIT_COMMAND; end

WAIT_COMMAND:

if (wait_cntr < if_delay) begin wait_cntr <= wait_cntr + 32'b1; end else begin wait_cntr <= 0; if (!if_write) begin state <= IDLE; ready <= 1'b1;

.

end end

endcase // case (state) end end endmodule

实验现象:

当SW1为低电平时,LCD无显示,LED都不亮。将SW1向上拨,LCD立即显示小时(空格)分钟(空格)秒数,且该时钟会走动;LCD显示10秒钟后,LCD上变成显示AB(空格)CD(空格)EF,同时八只LED灯亮;此时再将SW1向下拨,则LCD变为无显示,LED全灭。再将SW1向上拨,又将重复上述过程。

将SW1向上拨,LCD显示持续10秒钟的时钟,如图:

10秒钟后,LCD改为显示AB CD EF,且8个LED全亮,如图:

.

因篇幅问题不能全部显示,请点此查看更多更全内容