module lcd_pdf( clk,lcd_data, lcd_rw,lcd_rs, lcd_en,rst_n ); input clk; input rst_n; output reg [7:0] lcd_data; output reg lcd_rw; // wirte L output reg lcd_en; output reg lcd_rs; //clock 分频 reg [24:0] cnt; reg clk_10; always @(posedge clk or negedge rst_n) if(!rst_n)begin cnt <= 25'd0; clk_10 <= 1'b0; end else begin if(cnt == 5)begin clk_10 =~ clk_10; cnt <= cnt + 1'b1; end end //shixu always @(posedge clk_10 or negedge rst_n) if(!rst_n)begin lcd_rw <= 1'b0; lcd_en <= 1'b0; end else begin case(cnt) 100000:begin lcd_en <= 1'b0; lcd_data <= 8'h30; lcd_rw <= 1'b0; lcd_rs <= 1'b0; end 100001:begin lcd_en <= 1'b1; end 100010:begin lcd_en <= 1'b0; lcd_data <= 8'h0c; lcd_rw <= 1'b0; lcd_rs <= 1'b0; end 100011:begin lcd_en <= 1'b1; end 100020:begin lcd_en <= 1'b0; lcd_data <= 8'h01; lcd_rw <= 1'b0; lcd_rs <= 1'b0; end 100021:begin lcd_en <= 1'b1; end 100030:begin lcd_en <= 1'b0; lcd_data <= 8'h80; lcd_rw <= 1'b0; lcd_rs <= 1'b0; end 100031:begin lcd_en <= 1'b1; end 100040:begin lcd_en <= 1'b0; lcd_data <= 8'h30;//字符0 lcd_rw <= 1'b0; lcd_rs <= 1'b1; end 100041:begin lcd_en <= 1'b1; end default:lcd_en <= 1'b0; endcase end endmodule
主要还是按照时序图的时间顺序一步步的写,没有上机验证 而且tb在处理很大的数的时候不知道具体咋弄,留下以后解决
//-----------------------------------2-10号修改------------------------------------------//
module fsm_lcd( rs,rw,en,data, clk,rst_n ); input wire clk; input wire rst_n; output reg rs; //write_cmd -L or write_data -H output wire rw; //write - L output reg en; //写数据或者写指令 高脉冲 output reg [7:0] data; //上电20ms稳定电源 parameter TIME_20MS = 20'd1_0-1;//为了仿真将时间缩短 reg [19:0] cnt_init; always @(posedge clk or negedge rst_n) if(!rst_n) cnt_init <= 'd0; else if(cnt_init == TIME_20MS) cnt_init <= TIME_20MS; else cnt_init <= cnt_init + 1'b1; //分频 1602为慢速器件,要降低clk频率 parameter DIV_CNT = 20'd5 - 1;//加快仿真速度; reg [19:0] cnt_div; reg clk_500hz; always @(posedge clk or negedge rst_n) if(!rst_n)begin cnt_div <= 'd0; clk_500hz <= 'd0; end else if(cnt_div == DIV_CNT)begin cnt_div <= 'd0; clk_500hz =~ clk_500hz; end else cnt_div <= cnt_div + 1'b1; //fsm reg [4:0] state; reg [2:0] cnt_ms; always @(posedge clk_500hz or negedge rst_n) if(!rst_n)begin data <= 8'd0; en <= 1'd0; rs <= 1'd0; state <= 'd0; cnt_ms <= 'd0; end else if(cnt_init == TIME_20MS) case(state) 5'd0:begin data <= 8'd0; en <= 1'd0; rs <= 1'd0; state <= 5'd1; end 5'd1:begin data <= 8'h38; //显示模式 en <= 1'd0; rs <= 1'd0; state <= 5'd2; end 5'd2: if(cnt_ms == 3'd2)begin cnt_ms <= 'd0; en <= 1'd1; rs <= 1'd0; state <= 5'd3; end else cnt_ms <= cnt_ms + 1'b1; 5'd3:begin //0x0c 开显示不显示光标 data <= 8'h0c; en <= 1'd0; rs <= 1'd0; state <= 5'd4; end 5'd4:begin en <= 1'd1; state <= 5'd5; end 5'd5: if(cnt_ms == 3'd2)begin cnt_ms <= 'd0; en <= 1'd0; state <= 5'd6; end else cnt_ms <= cnt_ms + 1'b1; 5'd6:begin //0x80 首地址 en <= 1'd0; data <= 8'h80; state <= 5'd7; end 5'd7:begin en <= 1'd1; state <= 5'd8; end 5'd8:if(cnt_ms == 3'd2)begin //write_data cnt_ms <= 'd0; en <= 1'd0; rs <= 1'd1; data <= 8'h1; state <= 5'd9; end else cnt_ms <= cnt_ms + 1'b1; 5'd9:begin en <= 1'd1; state <= 5'd10; end 5'd10: if(cnt_ms == 3'd2)begin cnt_ms <= 'd0; en <= 1'd0; state <= 5'd0; end else cnt_ms <= cnt_ms + 1'b1; default:state <= 5'd0; endcase assign rw = 1'b0; endmodule