Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate delay in verilog for synthesis?

Tags:

verilog

I Want to Design a Verilog code for Interfacing 16*2 LCD. As in LCD's to give "command" or "data" we have to give LCD's Enable pin a "High to low Pulse " pulse that means

**E=1;
Delay();//Must be 450ns wide delay
E=0;**

This the place where I confuse I means in Verilog for synthesis # are not allowed so how can I give delay here I attached my code below. It must be noted that I try give delay in my code but I think delay not work so please help me to get rid of this delay problem......

             ///////////////////////////////////////////////////////////////////////////////////
             ////////////////////LCD Interfacing with Xilinx FPGA///////////////////////////////
             ////////////////////Important code for 16*2/1 LCDs///////////////////////////////// 
             //////////////////Coder-Shrikant Vaishnav(M.Tech VLSI)/////////////////////////////
             ///////////////////////////////////////////////////////////////////////////////////

 module lcd_fpgashri(output reg [7:0]data,output reg enb,output reg rs,output reg rw ,input CLK);
        reg [15:0]hold;
        reg [13:0]count=0;
        //Code Starts from here like C's Main......
        always@(posedge CLK)
        begin
        count=count+1; //For Delay

       //For LCD Initialization   
        lcd_cmd(8'b00111000);
        lcd_cmd(8'b00000001);
        lcd_cmd(8'b00000110);
        lcd_cmd(8'b00001100);

       //This is a String "SHRI" that I want to display
        lcd_data(8'b01010011);//S
        lcd_data(8'b01001000);//H
        lcd_data(8'b01010010);//R
        lcd_data(8'b01001001);//I
        end


        //Task For Command

       task lcd_cmd(input reg [7:0]value); 
          begin
         data=value;
         rs=1'b0;
         rw=1'b0;
         enb=1'b1;        //sending high to low pulse
         hold=count[13]; //This is the place where I try to design delay
         enb=1'b0;
        end
        endtask


   //Task for Data      

    task lcd_data(input reg [7:0]value1);
        begin
         data=value1;
         rs=1'b1;
         rw=1'b0;
         enb=1'b1;        //sending high to low pulse  
         hold=count[13]; //This is the place where I try to design delay
         enb=1'b0;
        end 
        endtask


        endmodule
like image 470
Shrikant Vaishnav Avatar asked Oct 07 '13 19:10

Shrikant Vaishnav


2 Answers

You seem to be stuck in a software programming mindset based on your code, you're going to have to change things around quite a bit if you want to actually describe a controller in HDL.

Unfortunately for you there is no way to just insert an arbitrary delay into a 'routine' like you have written there.

When you write a software program, it is perfectly reasonable to write a program like

doA();
doB();
doC();

Where each line executes one at a time in a sequential fashion. HDL does not work in this way. You need to not think in terms of tasks, and start thinking in terms of clocks and state machines.

Remember that when you have an always block, the entire block executes in parallel on every clock cycle. When you have a statement like this in an always block:

    lcd_cmd(8'b00111000);
    lcd_cmd(8'b00000001);
    lcd_cmd(8'b00000110);
    lcd_cmd(8'b00001100);

This does you no good, because all four of these execute simultaneously on positive edge of the clock, and not in a sequential fashion. What you need to do is to create a state machine, such that it advances and performs one action during a clock period.

If I were to try to replicate those four lcd_cmd's in a sequential manner, it might look something like this.

always @(posedge clk)
    case(state_f)
       `RESET: begin
           state_f <= `INIT_STEP_1;
           data = 8'b00111000;
       end
       `INIT_STEP_1: begin
           state_f <= `INIT_STEP_2;
           data = 8'b00000001;
       end
       `INIT_STEP_2: begin
           state_f <= `INIT_STEP_3;
           data = 8'b00000110;
       end
       `INIT_STEP_3: begin
           state_f <= `INIT_STEP_4;
           data =8'b00111000;
       end
       `INIT_STEP_4: begin
           state_f <= ???; //go to some new state
           data = 8'b00000110;
       end
    endcase
end

Now with this code you are advancing through four states in four clock cycles, so you can start to see how you might handle writing a sequence of events that advances on each clock cycle.

This answer doesn't get you all of the way, as there is no 'delay' in between these as you wanted. But you could imagine having a state machine where after setting the data you move into a DELAY state, where you could set a counter which counts down enough clock cycles you need to meet your timing requirements before moving into the next state.

like image 115
Tim Avatar answered Oct 29 '22 11:10

Tim


The best way to introduce delay is to use a counter as Tim has mentioned. Find out how many clock cycles you need to wait to obtain the required delay (here 450ns) w.r.t your clock period.

Lets take the number of clock cycles calculated is count. In that case the following piece of code can get you the required delay. You may however need to modify the logic for your purpose.

always @ (posedge clk) begin
  if (N == count) begin
    N <= 0;
    E = ~E;
  end else begin
    N <= N +1;    
  end 
end

Be sure to initialize N and E to zero.

like image 40
Vineeth VS Avatar answered Oct 29 '22 10:10

Vineeth VS