下面是综合代码:
`timescale 1ns/1ns
module LCD1602(
input clk,//100M
input rst_n,
//user interface
input wr_req_cmd,
input wr_req_data,
output reg wr_cmd_done,
output reg wr_data_done,
input row,
input [3:0] col,
input [7:0] data,
// output isout_sim,
//LCD1602 interface
output lcd_vo,
output reg lcd_rs,
output reg lcd_rw,
output reg lcd_e,
inout [7:0] lcd_db
);
parameter lcd_e_period =199;
parameter lcd_e_quarter =49;
parameter lcd_e_half =99;
reg [7:0] state;
reg [7:0] retu;
reg [7:0] jump;
reg [31:0] c1;
reg [7:0] busy;
reg isout;
reg [7:0] lcd_dbr;
reg [7:0] data_temp;
reg [7:0] send_data;
reg [3:0] pwm_cnt;
//assign isout_sim=isout;
assign lcd_db = isout ? lcd_dbr: 8'dz;
always@(posedge clk or negedge rst_n)
if(rst_n==1'b0)begin
data_temp=0;
end
else if(wr_req_data)begin
data_temp=data;
end
always@(posedge clk or negedge rst_n)
if(rst_n==1'b0)begin
state<= #4 0;
retu<= #4 8'd0;
jump<= #4 8'd0;
c1<= #4 0;
lcd_rs<= #4 1'b0;
lcd_rw<= #4 1'b0;
lcd_e<= #4 1'b0;
busy<= #4 8'd0;
isout=1'b1;
lcd_dbr<= #4 8'd0;
send_data<= #4 8'd0;
wr_cmd_done<= #4 1'b0;
wr_data_done<= #4 1'b0;
end
else begin
case(state)
0:begin
if(c1==1499999)begin
c1<= #4 0;
state<= #4 state+1'b1;
end
else begin
c1<= #4 c1+1'b1;
end
end
1:begin//写指令38H
state<= #4 16;
send_data<= #4 8'h38;
retu<= #4 state+1'b1;
end
2:begin
if(c1==499999)begin
c1<= #4 0;
state<= #4 state+1'b1;
end
else begin
c1<= #4 c1+1'b1;
end
end
3:begin//写指令38H
state<= #4 16;
send_data<= #4 8'h38;
retu<= #4 state+1'b1;
end
4:begin
if(c1==499999)begin
c1<= #4 0;
state<= #4 state+1'b1;
end
else begin
c1<= #4 c1+1'b1;
end
end
5:begin//写指令38H
state<= #4 16;
send_data<= #4 8'h38;
retu<= #4 state+1'b1;
end
6:begin//写指令38H
state<= #4 13;
send_data<= #4 8'h38;
retu<= #4 state+1'b1;
jump<= #4 16;
end
7:begin//写指令08H
state<= #4 13;
send_data<= #4 8'h08;
retu<= #4 state+1'b1;
jump<= #4 16;
end
8:begin//写指令01H
state<= #4 13;
send_data<= #4 8'h01;
retu<= #4 state+1'b1;
jump<= #4 16;
end
9:begin//写指令06H
state<= #4 13;
send_data<= #4 8'h06;
retu<= #4 state+1'b1;
jump<= #4 16;
end
10:begin//写指令0cH
state<= #4 13;
send_data<= #4 8'h0c;
retu<= #4 state+1'b1;
jump<= #4 16;
end
11:begin//IDLE
if(wr_req_cmd)begin//write cmd requst
state<= #4 13;
send_data<= #4 data;
retu<= #4 11;
jump<= #4 16;
end
else if(wr_req_data) begin//write data requst
send_data<= #4 row?(8'hC0|col):(8'h80|col);
state<= #4 13;
retu<= #4 state+1'b1;
jump<= #4 16;
end
else begin
state<= #4 11;
retu<= #4 8'd0;
jump<= #4 8'd0;
c1<= #4 0;
lcd_rs<= #4 1'b0;
lcd_rw<= #4 1'b0;
lcd_e<= #4 1'b0;
busy<= #4 8'd0;
isout=1'b1;
lcd_dbr<= #4 8'd0;
send_data<= #4 8'd0;
wr_cmd_done<= #4 1'b0;
wr_data_done<= #4 1'b0;
end
end
12:begin//write data
state<= #4 13;
send_data<= #4 data_temp;
retu<= #4 11;
jump<= #4 15;
end
//***************wait 1ms*************************
13:begin
if(c1==99999)begin
c1<= #4 0;
state<= #4 state+1'b1;
end
else begin
c1<= #4 c1+1'b1;
end
end
//***************jump*************************
14:begin
state<= #4 jump;
end
//***************write data******************************
15:begin
if(c1==0) begin
lcd_rs<= #4 1'b1;
lcd_rw<= #4 1'b0;
lcd_e<= #4 1'b0;
isout=1'b1;
lcd_dbr<= #4 send_data;
end
else if(c1==lcd_e_quarter)
lcd_e<= #4 1'b1;
else if(c1==lcd_e_half)
lcd_e<= #4 1'b0;
else if(c1==198)
wr_data_done<= #4 1'b1;
if(c1==lcd_e_period) begin
c1<= #4 0;
lcd_dbr<= #4 8'd0;
wr_data_done<= #4 1'b0;
state<= #4 retu;
end
else begin
c1<= #4 c1+1'b1;
end
end
//***************write cmd*******************************
16:begin
if(c1==0) begin
lcd_rs<= #4 1'b0;
lcd_rw<= #4 1'b0;
lcd_e<= #4 1'b0;
isout=1'b1;
lcd_dbr<= #4 send_data;
end
else if(c1==lcd_e_quarter)
lcd_e<= #4 1'b1;
else if(c1==lcd_e_half)
lcd_e<= #4 1'b0;
else if(c1==198)
wr_cmd_done<= #4 1'b1;
if(c1==lcd_e_period) begin
c1<= #4 0;
lcd_dbr<= #4 8'd0;
state<= #4 retu;
wr_cmd_done<= #4 1'b0;
end
else begin
c1<= #4 c1+1'b1;
end
end
endcase
end
always@(posedge clk or negedge rst_n)
if(!rst_n)
pwm_cnt <= #4 4'd0;
else
pwm_cnt <= #4 pwm_cnt + 1'b1;
assign lcd_vo = (pwm_cnt>9);
endmodule
仿真代码:
`timescale 1ns/1ns
`define clk_period 10
module LCD1602_sim;
reg clk;//100M
reg rst_n;
reg wr_req_data;
reg wr_req_cmd;
wire wr_cmd_done;
wire wr_data_done;
reg row;
reg [3:0] col;
reg [7:0] data;
//wire isout_sim;
wire lcd_vo;
wire lcd_rs;
wire lcd_rw;
wire lcd_e;
wor [7:0] lcd_db;
reg [7:0] lcd_db_r;
assign lcd_db=lcd_db_r;
LCD1602 LCD1602(
.clk(clk),//100M
.rst_n(rst_n),
.wr_req_cmd(wr_req_cmd),
.wr_req_data(wr_req_data),
.wr_cmd_done(wr_cmd_done),
.wr_data_done(wr_data_done),
.row(row),
.col(col),
.data(data),
// .isout_sim(isout_sim),
.lcd_vo(lcd_vo),
.lcd_rs(lcd_rs),
.lcd_rw(lcd_rw),
.lcd_e(lcd_e),
.lcd_db(lcd_db)
);
initial clk=1;
always#(`clk_period/2) clk=~clk;
initial begin
rst_n =0;
wr_req_cmd=0;
wr_req_data=0;
row=0;
col=0;
data=0;
lcd_db_r=0;
#(`clk_period*50+3);
rst_n =1;
#30_000_000;
wr_cmd(8'haa);
wr_data(1,5,8'h55);
wr_data(0,8,8'h66);
wr_data(1,3,8'h33);
wr_data(0,2,8'h77);
wr_cmd(8'hcc);
#30_000;
$stop;
end
task wr_cmd;
input [7:0] data_r;
begin
data=data_r;
wr_req_cmd=1;
#(`clk_period);
wr_req_cmd=0;
@(negedge wr_cmd_done);
end
endtask
task wr_data;
input row_r;
input [3:0] col_r;
input [7:0] data_r;
begin
data=data_r;
row=row_r;
col=col_r;
wr_req_data=1;
#(`clk_period);
wr_req_data=0;
@(negedge wr_data_done);
end
endtask
endmodule