OpenCores
URL https://opencores.org/ocsvn/wb_lcd/wb_lcd/trunk

Subversion Repositories wb_lcd

[/] [wb_lcd/] [trunk/] [verilog/] [wb_lcd/] [rtl/] [lcd_display.v] - Rev 2

Compare with Previous | Blame | View Log

//////////////////////////////////////////////////////////////////////
////                                                              ////
////  lcd_display.v                                               ////
////                                                              ////
////  This file is part of:                                       ////
////  WISHBONE/MEM MAPPED CONTROLLER FOR LCD CHARACTER DISPLAYS   ////
////  http://www.opencores.org/projects/wb_lcd/                   ////
////                                                              ////
////  Description                                                 ////
////   - Memory mapped main controller.                           ////
////                                                              ////
////  To Do:                                                      ////
////   - nothing really                                           ////
////                                                              ////
////  Author(s):                                                  ////
////   - José Ignacio Villar, jose@dte.us.es , jvillar@gmail.com  ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2009 José Ignacio Villar - jvillar@gmail.com   ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// either version 3 of the License, or (at your option) any     ////
//// later version.                                               ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// from http://www.gnu.org/licenses/lgpl.txt                    ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
 
`include "lcd_defines.v"
 
module lcd (
	input clk,
	input reset,
 
	input [`DAT_WIDTH-1:0] dat,
	input [`ADDR_WIDTH-1:0] addr,
	input we,
 
	input  repaint,
	output busy,
	output [3:0] SF_D,
	output LCD_E,
	output LCD_RS,
	output LCD_RW
	);
 
//
// TX sub FSM
//
parameter tx_state_high_setup	= 3'b000;
parameter tx_state_high_hold	= 3'b001;
parameter tx_state_oneus	= 3'b010;
parameter tx_state_low_setup	= 3'b011;
parameter tx_state_low_hold	= 3'b100;
parameter tx_state_fortyus	= 3'b101;	
parameter tx_state_done		= 3'b110;
 
reg	[2:0]	tx_state = tx_state_done; // Current tx fsm state
reg	[7:0]	tx_byte; // transmitting byte
wire		tx_init; // init transmission
reg  tx_done = 0;
 
 
//
// MAIN FSM
//
parameter display_state_init		= 5'b00000;
parameter init_state_fifteenms		= 5'b00001;
parameter init_state_one		= 5'b00010;
parameter init_state_two		= 5'b00011;
parameter init_state_three		= 5'b00100;
parameter init_state_four		= 5'b00101;
parameter init_state_five		= 5'b00110;
parameter init_state_six		= 5'b00111;
parameter init_state_seven		= 5'b01000;
parameter init_state_eight		= 5'b01001;
parameter display_state_function_set	= 5'b11000;
parameter display_state_entry_set	= 5'b11001;
parameter display_state_set_display	= 5'b11010;
parameter display_state_clr_display	= 5'b11011;
parameter display_state_pause_setup	= 5'b10000;
parameter display_state_pause		= 5'b10001;
parameter display_state_set_addr1	= 5'b11100;
parameter display_state_char_write1	= 5'b11101;
parameter display_state_set_addr2	= 5'b11110;
parameter display_state_char_write2	= 5'b11111;
parameter display_state_done		= 5'b10010;
 
reg [4:0] display_state = display_state_init; // current main fsm state
integer pos = `MEM_LOW1; // current drawing position
 
 
 
 
//
// RAM Interface
//
reg     [`DAT_WIDTH-1:0] ram [0:`MEM_LENGTH-1];    // memory contents
assign busy = (display_state != display_state_done);
 
always @(posedge clk) 
	if (we) 
		ram[addr] <= dat;
 
///
/// FSM and councurrent assignments definitions for LCD driving
/// 
reg [3:0] SF_D0 = 4'b0000;
reg [3:0] SF_D1 = 4'b0000;
reg       LCD_E0 = 1'b0;
reg       LCD_E1 = 1'b0;
wire      output_selector;
 
assign output_selector = display_state[4];
 
assign SF_D = (output_selector == 1'b1) ?	SF_D0 : //transmit
						SF_D1;  //initialize
 
assign LCD_E = (output_selector == 1'b1) ?	LCD_E0 ://transmit
						LCD_E1; //initialize
 
assign LCD_RW = 1'b0; // write only
 
//when to transmit a command/data and when not to
assign tx_init = !tx_done & display_state[4] & display_state[3];
 
// register select
assign LCD_RS =	(display_state == display_state_function_set) ? 1'b0 :
                (display_state == display_state_entry_set)    ? 1'b0 :
                (display_state == display_state_set_display)  ? 1'b0 :
                (display_state == display_state_clr_display)  ? 1'b0 :
                (display_state == display_state_set_addr1)    ? 1'b0 :
                (display_state == display_state_set_addr2)    ? 1'b0 :
                                                                1'b1;
 
 
reg  [`INIT_DELAY_COUNTER_WIDTH-1:0] main_delay_value = 0;
reg  [`INIT_DELAY_COUNTER_WIDTH-1:0] tx_delay_value = 0;
 
wire delay_done;
 
reg main_delay_load = 0;
reg tx_delay_load = 0;
 
 
 
delay_counter  #(
	.counter_width(`INIT_DELAY_COUNTER_WIDTH)
) delay_counter (
	.clk   ( clk ),
	.reset ( reset ),
	.count ( (main_delay_load) ? main_delay_value : tx_delay_value),
	.load  ( main_delay_load | tx_delay_load ),
	.done  ( delay_done )
);									  
 
 
 
 
// main (display) state machine
always @(posedge clk, posedge reset)
begin
	if(reset==1'b1) begin
		display_state <= display_state_init;
		main_delay_load <= 0;
		main_delay_value <= 0;
	end else begin
		main_delay_load <= 0;
		main_delay_value <= 0;
 
		case (display_state)
			//refer to intialize state machine below
			display_state_init:
			begin
				tx_byte <= 8'b00000000;
				display_state <= init_state_fifteenms;
				main_delay_load <= 1'b1;
				main_delay_value <= 750000;
			end
 
			init_state_fifteenms: 
			begin
				main_delay_load <= 1'b0;
				if(delay_done) begin
					display_state <= init_state_one;
					main_delay_load <= 1'b1;
					main_delay_value <= 11;
				end
			end	
 
			init_state_one: 
			begin
				main_delay_load <= 1'b0;
				SF_D1 <= 4'b0011;
				LCD_E1 <= 1'b1;
				if(delay_done) begin
					display_state <= init_state_two;
					main_delay_load <= 1'b1;
					main_delay_value <= 205000;
				end 
			end
 
			init_state_two: 
			begin
				main_delay_load <= 1'b0;
				LCD_E1 <= 1'b0;
				if(delay_done) begin
					display_state <= init_state_three;
					main_delay_load <= 1'b1;
					main_delay_value <= 11;
				end
			end
 
			init_state_three: 
			begin
				main_delay_load <= 1'b0;
				SF_D1 <= 4'b0011;
				LCD_E1 <= 1'b1;
				if(delay_done) begin
					display_state <= init_state_four;
					main_delay_load <= 1'b1;
					main_delay_value <= 5000;
				end
			end
 
			init_state_four: 
			begin
				main_delay_load <= 1'b0;
				LCD_E1 <= 1'b0;
				if(delay_done) begin
					display_state <= init_state_five;
					main_delay_load <= 1'b1;
					main_delay_value <= 11;
				end
			end
 
			init_state_five: 
			begin
				main_delay_load <= 1'b0;
				SF_D1 <= 4'b0011;
				LCD_E1 <= 1'b1;
				if(delay_done) begin
					display_state <= init_state_six;
					main_delay_load <= 1'b1;
					main_delay_value <= 2000;
				end
			end
 
			init_state_six: 
			begin
				main_delay_load <= 1'b0;
				LCD_E1 <= 1'b0;
				if(delay_done) begin
					display_state <= init_state_seven;
					main_delay_load <= 1'b1;
					main_delay_value <= 11;
				end
			end
 
			init_state_seven: 
			begin
				main_delay_load <= 1'b0;
				SF_D1 <= 4'b0010;
				LCD_E1 <= 1'b1;
				if(delay_done) begin
					display_state <= init_state_eight;
					main_delay_load <= 1'b1;
					main_delay_value <= 2000;
				end
			end
 
			init_state_eight: 
			begin
				main_delay_load <= 1'b0;
				LCD_E1 <= 1'b0;
				if(delay_done) begin
					display_state <= display_state_function_set;
				end
			end
 
			//every other state but pause uses the transmit state machine
			display_state_function_set:
			begin
				tx_byte <= 8'b00101000;
				if(tx_done)
					display_state <= display_state_entry_set;
			end
 
			display_state_entry_set:
			begin
				tx_byte <= 8'b00000110;
				if(tx_done)
					display_state <= display_state_set_display;
			end
 
			display_state_set_display:
			begin
				tx_byte <= 8'b00001100;
				if(tx_done)
					display_state <= display_state_clr_display;
			end
 
			display_state_clr_display:
			begin
				tx_byte <= 8'b00000001;
				if(tx_done) begin
					display_state <= display_state_pause_setup;
					main_delay_load <= 1;
					main_delay_value <= 82000;
				end
			end
 
			display_state_pause_setup:
			begin
				display_state <= display_state_pause;
			end
 
			display_state_pause:
			begin
				tx_byte <= 8'b00000000;
				if(delay_done) 
					display_state <= display_state_set_addr1;
			end
 
			display_state_set_addr1:
			begin
				tx_byte <= 8'b10000000;
				if(tx_done) begin
					display_state <= display_state_char_write1;
					pos <= `MEM_LOW1;
				end
			end
 
			display_state_char_write1:
			begin
				tx_byte <= ram[pos] & 8'b11111111;
				if(tx_done)
					if(pos == `MEM_HIGH1)
						display_state <= display_state_set_addr2;
					else 
						pos <= pos + 1;
			end
 
			display_state_set_addr2:
			begin
				tx_byte <= 8'b11000000;
				if(tx_done) begin
					display_state <= display_state_char_write2;
					pos <= `MEM_LOW2;
				end
			end
 
			display_state_char_write2:
			begin
				tx_byte <= ram[pos] & 8'b11111111;
				if(tx_done)
					if(pos == `MEM_HIGH2) begin
						display_state <= display_state_done;
					end else 
						pos <= pos + 1;
			end
 
			display_state_done:
			begin
				tx_byte <= 8'b00000000;
				if(repaint)
					display_state <= display_state_function_set;
				else
					display_state <= display_state_done;
			end
		endcase
	end
end
 
 
// transmit (tx) state machine, specified by datasheet
always @(posedge clk, posedge reset)
begin
	if(reset==1'b1)
		tx_state <= tx_state_done;
	else
	begin
		case (tx_state)
			tx_state_high_setup: // 40 ns
			begin
				LCD_E0 <= 1'b0;
				SF_D0 <= tx_byte[7 : 4];
				tx_delay_load <= 1'b0;
				if(delay_done) begin
					tx_state <= tx_state_high_hold;
					tx_delay_load <= 1'b1;
					tx_delay_value <= 12;
				end
			end
 
			tx_state_high_hold: // 230 ns
			begin
				LCD_E0 <= 1'b1;
				SF_D0 <= tx_byte[7 : 4];
				tx_delay_load <= 1'b0;
				if(delay_done) begin
					tx_state <= tx_state_oneus;
					tx_delay_load <= 1'b1;
					tx_delay_value <= 50;
				end
			end
 
			tx_state_oneus: 
			begin
				LCD_E0 <= 1'b0;
				tx_delay_load <= 1'b0;
				if(delay_done) begin
					tx_state <= tx_state_low_setup;
					tx_delay_load <= 1'b1;
					tx_delay_value <= 2;
				end
			end
 
			tx_state_low_setup: // 40 ns
			begin
				LCD_E0 <= 1'b0;
				SF_D0 <= tx_byte[3 : 0];
				tx_delay_load <= 1'b0;
				if(delay_done) begin
					tx_state <= tx_state_low_hold;
					tx_delay_load <= 1'b1;
					tx_delay_value <= 12;
				end
			end
 
			tx_state_low_hold: // 230 ns
			begin
				LCD_E0 <= 1'b1;
				SF_D0 <= tx_byte[3 : 0];
				tx_delay_load <= 1'b0;
				if(delay_done) begin
					tx_state <= tx_state_fortyus;
					tx_delay_load <= 1'b1;
					tx_delay_value <= 2000;
				end
			end
 
			tx_state_fortyus: 
			begin
				LCD_E0 <= 1'b0;
				tx_delay_load <= 1'b0;
				if(delay_done) begin
					tx_state <= tx_state_done;
					tx_done <= 1'b1;
				end
			end
 
			tx_state_done: 
			begin
				LCD_E0 <= 1'b0;
				tx_done <= 1'b0;
				tx_delay_load <= 1'b0;
				if(tx_init == 1'b1) begin
					tx_state <= tx_state_high_setup;
					tx_delay_load <= 1'b1;
					tx_delay_value <= 2;
				end
			end
		endcase
	end
end
endmodule
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.