我想设计一个用于连接16 * 2 LCD的Verilog代码。如在LCD中给出“命令”或“数据”,我们必须给LCD的使能引脚一个“高到低脉冲”脉冲,这意味着
**E=1;
Delay();//Must be 450ns wide delay
E=0;**
这是我混淆的地方我在Verilog中意味着合成#是不允许的,所以我怎么能在这里给出延迟我附上下面的代码。 必须注意的是,我尝试延迟我的代码,但我认为延迟不起作用所以请帮助我摆脱这个延迟问题......
///////////////////////////////////////////////////////////////////////////////////
////////////////////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
答案 0 :(得分:5)
你似乎陷入了基于代码的软件编程思维模式,如果你想用HDL实际描述一个控制器,你将不得不改变一些事情。
不幸的是,对于你来说,没有办法像你在那里写的那样只在一个'例程'中插入任意延迟。
编写软件程序时,编写像
这样的程序是完全合理的doA();
doB();
doC();
每行以顺序方式一次执行一行。 HDL不能以这种方式工作。你不需要考虑任务,而是开始考虑时钟和状态机。
请记住,当您有一个始终阻止时,整个块在每个时钟周期并行执行。当你在一个始终的块中有这样的语句时:
lcd_cmd(8'b00111000);
lcd_cmd(8'b00000001);
lcd_cmd(8'b00000110);
lcd_cmd(8'b00001100);
这对你没有好处,因为所有这四个都在时钟的上升沿同时执行,而不是以顺序方式执行。您需要做的是创建一个状态机,以便它在一个时钟周期内前进并执行一个操作。
如果我尝试以顺序方式复制这四个lcd_cmd,它可能看起来像这样。
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
现在使用此代码,您可以在四个时钟周期内前进四个状态,因此您可以开始了解如何处理在每个时钟周期内编写一系列事件。
这个答案并没有让你一路走来,因为你想要的并没有“延迟”。但你可以想象有一个状态机,在设置数据后你进入DELAY状态,在那里你可以设置一个计数器来计算足够的时钟周期,你需要在进入下一个状态之前满足你的时序要求。
答案 1 :(得分:2)
引入延迟的最佳方法是使用Tim提到的计数器。 了解在时钟周期内需要等待多少个时钟周期才能获得所需的延迟(此处为450ns)。
让我们计算的时钟周期数是计数。在这种情况下,下面的代码可以为您提供所需的延迟。但是,您可能需要为您的目的修改逻辑。
always @ (posedge clk) begin
if (N == count) begin
N <= 0;
E = ~E;
end else begin
N <= N +1;
end
end
务必将N和E初始化为零。