Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Verilog help with LCD controlled from through CPLD from PIC- bidirectional port help.

Status
Not open for further replies.

JAMR

Newbie level 3
Joined
Jun 5, 2015
Messages
4
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
45
Hello all.

I've been working on a project of controlling an LCD from a PIC through a Lattice CPLD. The PIC code is fine but I keep getting garbled info when outputting through the CPLD. It appears that the issue is not being able to send data back to the PIC. I am unable to get my bidirectional ports to work correctly.

Any help is appreciated.

Thanks - Not a homework project


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
module U3_CPLD_GPIO( 
 
//Port List 
CPLD_CLK    ,  
CPLD_RESET    ,  
PMAD        ,  
PMCS0       ,  
PMRD        ,      
PMWR        ,  
LCD_BL      ,  
LCD_E       ,  
LCD_RS      ,      
LCD_RW      ,  
LCD_D       ,  
PMD         , 
INT1        , 
INT2        , 
IO_DIR      , 
LED             
); 
 
//Input declaration  
 input CPLD_CLK;          
 input CPLD_RESET;  
 input PMAD;  
 input PMCS0; 
 input PMRD;  
 input PMWR; 
  
//LCD 
 output LCD_BL;  
 output wire LCD_E;  
 output reg LCD_RS;  
 output reg LCD_RW; 
  
//LCD IO Config 
 //reg pcu_rnw; direction (read=1 or 0= write); 
 reg [7:0] WriteData;  
 inout wire[7:0] PMD;                //LCD data to/from PIC
 //input IO_DIR;        // Direction of io, 1 = set output, 0 = read input 
 //assign PMD = (pcu_rnw)? 8'bz : WriteData; 
  
 //reg pcu_rnw2; direction (read=1 or 0=write) 
 inout wire[7:0] LCD_D;             //Data to/from LCD
 //assign LCD_D = (pcu_rnw2)? 8'bz; 
   
//INT 
 output INT1; 
 output INT2; 
 
 input [3:0]IO_DIR; 
  
//LED 
 output reg LED; 
 
//Port Master Signals 
 reg [7:0] PMD_Regd; 
 reg [7:0] PMD_Out; 
 reg PMWR_Regd; 
 reg PMRD_Regd; 
 reg PMCS0_Regd; 
 reg PMAD_Regd; 
 
 assign LCD_BL = 1'b1;     
 
//LED Blink  
  reg [25:0] counter; 
 
  always @(posedge CPLD_CLK) 
    if (counter == 4000000)        //4MHz 
      begin 
        counter <= 0; 
        LED <= ~LED; 
      end 
    else 
      begin 
        counter <= counter + 1; 
        LED <= LED; 
      end
 
//LCD Process 
 
   always @(posedge CPLD_CLK) 
         if (PMWR == 1'b0) 
             begin         
                 PMD_Regd [7:0] <= PMD [7:0]; 
                 PMWR_Regd <= PMWR; 
                 PMRD_Regd <= PMRD;                  
                 PMCS0_Regd <= PMCS0; 
                 PMAD_Regd <= PMAD;             //LCD_E 
                 LCD_RS <= PMRD_Regd;                      
                 LCD_RW <= PMWR_Regd;                                  
                 LCD_E <= PMAD_Regd; 
                 #20; 
                 LCD_D [7:0] <= PMD_Regd [7:0];          
            end 
        else 
            begin 
                 //pcu_rnw2 <= 1'b1;                //set to input from LCD 
                 //WriteData <= LCD_D;          //read from LCD to WriteData
                 //pcu_rnw <= 1'b0;                 //output to PIC 
                 //PMD = WriteData; 
                  
                 //PMWR_Regd <= PMWR; 
                 //PMRD_Regd <= PMRD; 
                 PMD_Regd [7:0] <= LCD_D [7:0]; 
                 PMD [7:0] <= PMD_Regd [7:0]; 
            end  
                   
 
         
 
 
endmodule

 

Well you've removed all the bidirectional code to drive the output bidirectionally so of course it doesn't work.

Instead of showing us broken code that has what appears to be random changes to try and get it to "work/compile" how about showing us a drawing of what you want to implement and then we can compare it to the code and tell you exactly where you went wrong.
 

I've cleaned up the code and removed the commented out sections. I was trying to show what I've tried. For the bidirectional ports I'm using inout wire[7:0] PMD; and inout wire[7:0] LCD_D;

I cannot figure out how to control these (assign a direction) within the if else statement in my LCD process. The compiler always gives errors and I can only assign as input or output. Is this possible in real world hardware situations or only simulation ? The PCBA I'm working with at my company unfortunately has an outdated Lattice chip and I cannot find much support.

I've spent the last month and a half watching tutorials, reading books, and reading forums. I really need some guidance.

Thank you

Code:
module U3_CPLD_GPIO( 

//Port List 
CPLD_CLK    ,  
CPLD_RESET    ,  
PMAD        ,  
PMCS0       ,  
PMRD        ,      
PMWR        ,  
LCD_BL      ,  
LCD_E       ,  
LCD_RS      ,      
LCD_RW      ,  
LCD_D       ,  
PMD         , 
INT1        , 
INT2        , 
IO_DIR      , 
LED             
); 

//Input declaration  
 input CPLD_CLK;          
 input CPLD_RESET;  
 input PMAD;  
 input PMCS0; 
 input PMRD;  
 input PMWR; 
  
//LCD 
 output LCD_BL;  
 output LCD_E;  
 output LCD_RS;  
 output LCD_RW; 
  
//LCD IO Config 
 reg [7:0] WriteData;  
 inout wire[7:0] PMD;                //LCD data to/from PIC
 inout wire[7:0] LCD_D;              //Data to/from LCD
   
//INT 
 output INT1; 
 output INT2; 

 input [3:0]IO_DIR; 
  
//LED 
 output reg LED; 

//Port Master Signals 
 reg [7:0] PMD_Regd; 
 reg [7:0] PMD_Out; 
 reg PMWR_Regd; 
 reg PMRD_Regd; 
 reg PMCS0_Regd; 
 reg PMAD_Regd; 

 assign LCD_BL = 1'b1;     

//LED Blink  
  reg [25:0] counter; 

  always @(posedge CPLD_CLK) 
    if (counter == 4000000)        //4MHz 
      begin 
        counter <= 0; 
        LED <= ~LED; 
      end 
    else 
      begin 
        counter <= counter + 1; 
        LED <= LED; 
      end
 
//LCD Process 

   always @(posedge CPLD_CLK) 
         if (PMWR == 1'b0) 
             begin         
                 PMD_Regd [7:0] <= PMD [7:0];	//Read LCD data from PIC and save it to PMD_Regd 
                 PMWR_Regd <= PMWR; 
                 PMRD_Regd <= PMRD;                  
                 PMCS0_Regd <= PMCS0; 
                 PMAD_Regd <= PMAD;				//LCD_E 
                 LCD_RS <= PMRD_Regd;                      
                 LCD_RW <= PMWR_Regd;                                  
                 LCD_E <= PMAD_Regd; 
                 LCD_D [7:0] <= PMD_Regd [7:0];	//Send LCD data from PMD_Regd to LCD          
            end 
        else 
            begin 
                 PMWR_Regd <= PMWR; 
                 PMRD_Regd <= PMRD; 
                 PMD_Regd [7:0] <= LCD_D [7:0];	//Read data from LCD and save it to PMD_Regd
                 PMD [7:0] <= PMD_Regd [7:0];	//Send LCD data from PMD_Regd to PIC
            end  
                 

         


endmodule
 

Bi-direction signals are used as follows (this is well documented in books and online)


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
inout  bidi_port;
 
reg bidi_output;
reg bidi_dir; // 1 output, 0 input
reg capture_bidi_input;
 
assign bidi_port = bidi_dir ? bidi_output : 1'bz;
 
always @ (posedge clk) begin
 
  // using bidi_port on RHS (reading the port)
  capture_bidi_input <= bidi_port;
 
end

 

Thank you for your help. I've tried something similar and I'm not sure if I'm following correctly but I'm getting the same error as before. Is there anyway to change the port direction inside of my if else statement or another way you recommend of doing this ? When I assign direction I get stuck as an input or output.

Thanks again.

Error.JPG

Code:
//LCD 
 output reg LCD_BL;  
 output reg LCD_E;  
 output reg LCD_RS;  
 output reg LCD_RW; 
  
//LCD IO Config   
 inout [7:0] PMD;                //LCD data to/from PIC
 inout [7:0] LCD_D;              //Data to/from LCD
 
 reg PMD_output;
 reg PMD_dir; // 1 output, 0 input
 reg capture_PMD_input;
 
 reg LCD_output;
 reg LCD_dir; // 1 output, 0 input
 reg capture_LCD_input;
   
//LED 
 output reg LED;

 assign LCD_BL = 1'b1;
 
 assign PMD = PMD_dir ? PMD_output : 1'bz;
 assign LCD_D = LCD_dir ? LCD_output : 1'bz;

//LCD Process 

   always @(posedge CPLD_CLK) 
         if (PMWR == 1'b0) 
             begin         
                 capture_PMD_input <= PMD [7:0];	//Read LCD data from PIC and save it to PMD_Regd 
                 LCD_RS <= PMRD;                      
                 LCD_RW <= PMWR;                                  
                 LCD_E <= PMAD;
                 LCD_D <= capture_PMD_input;	//Send LCD data from PMD_Regd to LCD          
            end 
        else 
            begin
            	 capture_LCD_input <= LCD_D [7:0]; 
                 LCD_RS <= PMRD;                      
                 LCD_RW <= PMWR;                                  
                 LCD_E <= PMAD;
                 PMD <= capture_LCD_input;	//Send LCD data from PMD_Regd to PIC
            end  
                 
//LED Blink  
  reg [25:0] counter; 

  always @(posedge CPLD_CLK) 
    if (counter == 4000000)        //4MHz 
      begin 
        counter <= 0; 
        LED <= ~LED; 
      end 
    else 
      begin 
        counter <= counter + 1; 
        LED <= LED; 
      end
 
         


endmodule
 

Code:
//LCD
 output reg LCD_BL;
 output reg LCD_E;
 output reg LCD_RS;
 output reg LCD_RW;

//LCD IO Config
 inout [7:0] PMD;                //LCD data to/from PIC
 inout [7:0] LCD_D;              //Data to/from LCD

 reg PMD_output;
 reg PMD_dir; // 1 output, 0 input
 reg capture_PMD_input;

 reg LCD_output;
 reg LCD_dir; // 1 output, 0 input
 reg capture_LCD_input;

//LED
 output reg LED;

 assign LCD_BL = 1'b1;
[COLOR="#FF0000"]// *************************************
// this is the correct way to assign the inout OUTPUTS.
// *************************************
[/COLOR] assign PMD = PMD_dir ? PMD_output : 1'bz;
 assign LCD_D = LCD_dir ? LCD_output : 1'bz;

//LCD Process

   always @(posedge CPLD_CLK)
         if (PMWR == 1'b0)
             begin
                 capture_PMD_input <= PMD [7:0];	//Read LCD data from PIC and save it to PMD_Regd
                 LCD_RS <= PMRD;
                 LCD_RW <= PMWR;
                 LCD_E <= PMAD;
[COLOR="#FF0000"]// *******************************************
// WHY ARE YOU ASSIGNING LCD_D HERE!? you already
// have the assign statement above, which is the
// correct way to define a bi-directional signal.
// *******************************************
[/COLOR]                 LCD_D <= capture_PMD_input;	//Send LCD data from PMD_Regd to LCD
[COLOR="#FF0000"]// *******************************************
// This is what you should be assigning here.
//               LCD_output <=capture_PMD_input;
// *******************************************
[/COLOR]            end
        else
            begin
            	 capture_LCD_input <= LCD_D [7:0];
                 LCD_RS <= PMRD;
                 LCD_RW <= PMWR;
                 LCD_E <= PMAD;
[COLOR="#FF0000"]// *******************************************
// same problem as above.
// *******************************************
[/COLOR]                 PMD <= capture_LCD_input;	//Send LCD data from PMD_Regd to PIC
            end

//LED Blink
  reg [25:0] counter;

  always @(posedge CPLD_CLK)

[COLOR="#FF0000"]// *******************************************
// learn how to count from 0!
// starting at 0 ending at 4000000 is [b]4000001[/b] counts not 4000000.
// *******************************************
 [/COLOR]   if (counter == 4000000)        //4MHz
      begin
        counter <= 0;
        LED <= ~LED;
      end
    else
      begin
        counter <= counter + 1;
        LED <= LED;
      end

Once again....


Code Verilog - [expand]
1
2
3
4
5
6
7
// an inout....
// generate the output of the inout
assign bidi_pin <= bidi_dir ? bidi_output : 1'bz;
 
// using the input of an inout
my_signal <= bidi_pin;
if (bidi_pin == 1'b1)

 

Thank you for your help. Makes much more sense than the way I was reading it.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top