正在学习verilog,真是不踩坑不知道深浅。一个LCD的显示最开始想起来非常简单,后来写起来不是这里编不过,就是仿不过,完全不能用之前单片机的想法做。现在正在考虑不采用状态机的实现方法,好像还是比较麻烦。
先写了一个指令和data的控制的module。
module writecommand(
input cmd_start,
input cmd_sel,
input clk_1ms,
input rst_n,
output reg lcdrw,
output reg lcdrs,
output reg lcden,
input [7:0] datain,
output reg [7:0] dataout
);
reg [2:0] dy_cnt;
//reg lcdrs,lcdrw,lcden;
always @(posedge clk_1ms or negedge rst_n)
begin
if (!cmd_start)
dy_cnt =3'd0;
else
if(rst_n==1'b0)
begin
dy_cnt <=3'd0;
end
else
if(dy_cnt>=3'd7)
begin
dy_cnt <=dy_cnt;
end
else
dy_cnt <=dy_cnt+3'd1;
end
always @(posedge clk_1ms or negedge rst_n)
begin
if(rst_n==1'b0)
begin
lcdrs = 1'b0;
lcdrw = 1'b0;
lcden = 1'b0;
end
else
case(dy_cnt)
3'd00:
begin
lcdrs = 1'b0;
lcdrw = 1'b0;
lcden = 1'b0;
end
3'd01:
begin
dataout<=datain;
lcdrs = cmd_sel;
end
3'd02,3'd03:
begin
lcden <= 1'b1;
end
3'd04,3'd05:
lcden <= 1'b0;
3'd06:
begin
lcdrs = 1'b0;
lcdrw = 1'b0;
lcden = 1'b0;
end
default:;
endcase
end
endmodule
仿真代码如下
`timescale 100us / 1us
module led_tb;
reg clk;
reg [7:0] datain;
reg rstn;
reg cmd_start,cmd_sel;
always #1 clk = ~clk;
wire [7:0] dataout;
writecommand writecommand(
.cmd_start(cmd_start),
.cmd_sel(cmd_sel),
.clk_1ms(clk),
//.led(led),
.rst_n(rstn),
//.led(),
.lcdrs(lcdrs),
.lcdrw(lcdrw),
.lcden(lcden),
.datain(datain),
.dataout(dataout)
);
initial begin
clk=0;rstn=0;cmd_sel=0;cmd_start=0;
#100 rstn=1;
#10 cmd_sel=0;
#10 datain=8'h38;
#50 cmd_start=1;
#50 cmd_start=0;
#100 cmd_sel=1;
#10 datain=8'h82;
#50 cmd_start=1;
#50 cmd_start=0;
#1800 $stop;
end
endmodule
仿真结果如下: