Spartan 3E LCD verilog code problem

Status
Not open for further replies.

arishsu

Member level 3
Joined
Sep 10, 2013
Messages
66
Helped
6
Reputation
12
Reaction score
6
Trophy points
8
Location
India
Activity points
422
I tried to run this code on the fpga, but it is showing some garbage characters.
I got this code from the web. Please help me to correct the code.
Code:
module test_lcd(clk,sf_e,rs,rw,a,b,c,d,e);

input clk;//50Mhz onboard clk
output reg sf_e;//1 lcd access (0 strataFlash access)
output reg e;//enable(1)
output reg rs;//Register select(1 data bits for R/W)
output reg rw;//Read/Write, 1/0
output reg a;//1st data bits (to form a nibble)
output reg b;//2nd data bits (to form a nibble)
output reg c;//3rd data bits (to form a nibble)
output reg d;//4th data bits (to form a nibble)

reg[26:0] count=0;//27-bit count. 0 to 128M-1, over 2 secs
reg[5:0] code;//6-bit different signals to give out
reg refresh;//refresh lcd rate @ about 25Hz

always@(posedge clk)
begin
  count <= count+1;
  case (count[26:21]) //as top 6 bits change
 //power on init can be carried out before this loop to avoid the flickers
  0: code <= 6'h03;//power on init sequence
  1: code <= 6'h03;//this is needed atleast once
  2: code <= 6'h03;//when LCD is powered on
  3: code <= 6'h03;//it flickers existing char display
//table 5-3 function set
//send 00 and upper nibble 0010, then 00 and lower nibble 10xx
  4: code <= 6'h02;//function set, upper nibble 0010
  5: code <= 6'h08;//lower nibble 1000(10xx)
  
//table 5-3, entry mode
//send 00 and upper nibble 0000, then 00 and lower nibble 01 I/D S
//last 2 bit of the lower nibble I/D bit(increment 1 decrement 0)
  6: code <= 6'h00;//see table, upper nibble 0000, then lower nibble
  7: code <= 6'h06;//0110 incr, shift disabled

//table 5-3,display on/off
//send 00 and upper nibble 0000, then 00 and lower nibble 1DCB
//D:1, show char represented by code in DDR, 0, don't but code remains
//B:1, show cursor, 0, don't
//C:1, cursor blinks (if shown), 0, dont blink (if shown)
  8: code <= 6'h00;//display on/off, upper nibble 0000
  9: code <= 6'h0C;//lower nibble 1100(1 D C B)
  
//table 5-3 clear display, 00 and upper nibble 0000, then 00 and lower nibble 0001
  10: code <= 6'h00;//clear display, 00 and upper nibble 0000
  11: code <= 6'h01;//then 00 and lower nibble 0001
  
//charecters are then given out. cursor will advance to the right
//table 5-3, write data to DD RAM (or CG RAM)
//fig 5-4, 'H,' send 10 and upper nibble 0100, then 10 and lower nibble 1000
  12: code <= 6'h24;//'H' higher nibble
  13: code <= 6'h28;//'H'lower nibble
  14: code <= 6'h26;//e
  15: code <= 6'h25;
  16: code <= 6'h26;//l
  17: code <= 6'h2C;
  18: code <= 6'h26;//l
  19: code <= 6'h2C;
  20: code <= 6'h26;//o
  21: code <= 6'h2F;
  22: code <= 6'h22;//,
  23: code <= 6'h2C;
  
//table 5-3, set DDR address
//position the cursor on to the start of the 2nd line
//send 00 and upper nibble 1???, ??? is the highest 3 bit of the DDR
//address to move the cursor to, then 00 and lower 4 bits of the address
//so ??? is 100 and then 0000 for h40
  24: code <= 6'b001100;//position cursor to 2nd line upper nibble
  25: code <= 6'b000000;//lower nibble: h0

//charecters are then given out. cursor will advance to the right
  26: code <= 6'h25;//W
  27: code <= 6'h27;
  28: code <= 6'h26;//o
  29: code <= 6'h2F;
  30: code <= 6'h27;//r
  31: code <= 6'h22;
  32: code <= 6'h26;//l
  33: code <= 6'h2C;
  34: code <= 6'h26;//d
  35: code <= 6'h24;
  36: code <= 6'h22;//!
  37: code <= 6'h21;
  
//Table 5-3, Read Busy Flag and address
//send 01 BF (Busy Flag) xxx, then, 01xxxx
//idling
  default: code <=6'h10;//the rest unused time
  endcase
  
//refresh (enable) LCD when bit 20 of the count is 1
//it flips when counted up to 2M, and flips again after another 2M
  refresh <=count[20];//flip rate about 25(50MHz/2^21=2M)
  sf_e <= 1;
  {e,rs,rw,a,b,c,d} <= {refresh, code};
  
end //always
endmodule

And this is the ucf file.

Code:
NET "clk" LOC = "C9" | IOSTANDARD = LVCMOS33 ;
NET "sf_e" LOC = "D16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
NET "e" LOC = "M18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
NET "rs" LOC = "L18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
NET "rw" LOC = "L17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
# The LCD four-bit data interface is shared with the StrataFlash.
NET "a" LOC = "R15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
NET "b" LOC = "R16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
NET "c" LOC = "P17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
NET "d" LOC = "M15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
 

hi, if you can tell me what to be displayed ,then i can help you.
 
Last edited by a moderator:

Anything. A simple hello world program for example.
 

module lcd(clk,sf_ce0, lcd_rs, lcd_rw,
lcd_e, lcd_4, lcd_5, lcd_6, lcd_7);
parameter k = 18;
input clk; // synthesis attribute PERIOD clk "50 MHz"
// synthesis attribute PERIOD clk "50 MHz"
reg [k+8:0] count=0;
output reg sf_ce0; // high for full LCD access
reg lcd_busy=1;
reg lcd_stb;
reg [5:0] lcd_code;
reg [6:0] lcd_stuff;
output reg lcd_rs;
output reg lcd_rw;
output reg lcd_7;
output reg lcd_6;
output reg lcd_5;
output reg lcd_4;
output reg lcd_e;
reg [127:0] input1,input2;
initial
begin
input1 = " hello ";
input2 = " everyone ";
end
always @ (posedge clk) begin
count <= count + 1;
sf_ce0 <= 1;
case (count[k+8:k+2])
0: lcd_code = 6'h03; // power-on initialization
1: lcd_code = 6'h03;
2: lcd_code = 6'h03;
3: lcd_code = 6'h02;
4: lcd_code = 6'h02; // function set
5: lcd_code = 6'h08;
6: lcd_code = 6'h00; // entry mode set
7: lcd_code = 6'h06;
8: lcd_code = 6'h00; // display on/off control
9: lcd_code = 6'h0C;
10: lcd_code = 6'h00; // display clear
11: lcd_code = 6'h01;



12: lcd_code = {2'b10,input1[127:124]};
13: lcd_code = {2'b10,input1[123:120]};

14: lcd_code = {2'b10,input1[119:116]};
15: lcd_code = {2'b10,input1[115:112]};

16: lcd_code = {2'b10,input1[111:108]};
17: lcd_code = {2'b10,input1[107:104]};

18: lcd_code = {2'b10,input1[103:100]};
19: lcd_code = {2'b10,input1[99:96]};

20: lcd_code = {2'b10,input1[95:92]};
21: lcd_code = {2'b10,input1[91:88]};

22: lcd_code = {2'b10,input1[87:84]};
23: lcd_code = {2'b10,input1[83:80]};

24: lcd_code = {2'b10,input1[79:76]};
25: lcd_code = {2'b10,input1[75:72]};

26: lcd_code = {2'b10,input1[71:68]};
27: lcd_code = {2'b10,input1[67:64]};

28: lcd_code = {2'b10,input1[63:60]};
29: lcd_code = {2'b10,input1[59:56]};

30: lcd_code ={2'b10,input1[55:52]};
31: lcd_code = {2'b10,input1[51:48]};

32: lcd_code = {2'b10,input1[47:44]};
33: lcd_code = {2'b10,input1[43:40]};

34: lcd_code = {2'b10,input1[39:36]};
35: lcd_code = {2'b10,input1[35:32]};

36: lcd_code = {2'b10,input1[31:28]};
37: lcd_code = {2'b10,input1[27:24]};

38: lcd_code = {2'b10,input1[23:20]};
39: lcd_code = {2'b10,input1[19:16]};

40: lcd_code = {2'b10,input1[15:12]};
41: lcd_code = {2'b10,input1[11:08]};

42: lcd_code = {2'b10,input1[07:04]};
43: lcd_code = {2'b10,input1[03:00]};

44: lcd_code = 6'h0c;
45: lcd_code = 6'h00;

46: lcd_code = {2'b10,input2[127:124]};
47: lcd_code = {2'b10,input2[123:120]};

48: lcd_code = {2'b10,input2[119:116]};
49: lcd_code = {2'b10,input2[115:112]};

50: lcd_code = {2'b10,input2[111:108]};
51: lcd_code = {2'b10,input2[107:104]};

52: lcd_code = {2'b10,input2[103:100]};
53: lcd_code = {2'b10,input2[99:96]};

54: lcd_code = {2'b10,input2[95:92]};
55: lcd_code = {2'b10,input2[91:88]};

56: lcd_code = {2'b10,input2[87:84]};
57: lcd_code = {2'b10,input2[83:80]};

58: lcd_code = {2'b10,input2[79:76]};
59: lcd_code = {2'b10,input2[75:72]};

60: lcd_code = {2'b10,input2[71:68]};
61: lcd_code = {2'b10,input2[67:64]};

62: lcd_code = {2'b10,input2[63:60]};
63: lcd_code = {2'b10,input2[59:56]};

64: lcd_code ={2'b10,input2[55:52]};
65: lcd_code = {2'b10,input2[51:48]};

66: lcd_code = {2'b10,input2[47:44]};
67: lcd_code = {2'b10,input2[43:40]};

68: lcd_code = {2'b10,input2[39:36]};
69: lcd_code = {2'b10,input2[35:32]};

70: lcd_code = {2'b10,input2[31:28]};
71: lcd_code = {2'b10,input2[27:24]};

72: lcd_code = {2'b10,input2[23:20]};
73: lcd_code = {2'b10,input2[19:16]};

74: lcd_code = {2'b10,input2[15:12]};
75: lcd_code = {2'b10,input2[11:08]};

76: lcd_code = {2'b10,input2[07:04]};
77: lcd_code = {2'b10,input2[03:00]};
default: lcd_code = 6'h10;
endcase
//if (lcd_rw) // comment-out for repeating display
// lcd_busy <= 0; // comment-out for repeating display
lcd_stb <= ^count[k+1:k+0] & ~lcd_rw & lcd_busy; // clkrate / 2^(k+2)
lcd_stuff <= {lcd_stb,lcd_code};
{lcd_e,lcd_rs,lcd_rw,lcd_7,lcd_6,lcd_5,lcd_4} <= lcd_stuff;
end
endmodule

- - - Updated - - -

//ucf file
NET "lcd_e" LOC = "M18" ;
NET "lcd_rs" LOC = "L18" ;
NET "lcd_rw" LOC = "L17" ;

NET "lcd_4" LOC = "R15";
NET "lcd_5" LOC = "R16" ;
NET "lcd_6" LOC = "P17";
NET "lcd_7" LOC = "M15" ;

NET "clk" LOC = "C9";
NET "sf_ce0" LOC = "D16";

- - - Updated - - -

@arishu
try this code.
 
hi Gs65,

Have you implemented your code in fpga ?

I doubt it will work.
 

I have modified the code which was working and displayed here.
Right now I don't have the kit. ..it will work
 

hi Gs65,

Have you implemented your code in fpga ?

I doubt it will work.
This is a case of the blind (Gs65) leading the blind (arishsu).

Store the bytes to send in a array and use a simple sequencer to address the array and output a value to the LCD. That gets rid of the huge ugly ridiculous case statement.

This is also a glitch generator: ^count[k+1:k+0] This combinational output relies on the adjacent bits of the output count being routed with exactly the same amount of delay to avoid a low going pulse during the 01-10 transition.
 

Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…