DE2-115 LCD 上的两条线都无法正常工作。我知道我需要更改 DDRAM 地址以获得开始打印消息的起始位置,但是我不确定如何使两条线都工作。这是我当前得到的液晶驱动器,我的顶层是之后的。
module lcd_driver ( // Host Side
input clk,
dstream.in in_data, // data from controller
// LCD Side
output logic [7:0] LCD_DATA,
output logic LCD_RW,LCD_EN,LCD_RS,LCD_ON,LCD_BLON
);
assign LCD_ON = 1'b1; // Turn LCD on
assign LCD_BLON = 1'b0; // Display backlight (Not supported on DE2-115).
enum logic [2:0] {INIT, START, ENABLE, WAIT, NEXT} state, next_state;
logic [5:0] initialise_index = 0;
logic [9:0] init_data;
integer start_count = 0;
integer delay_count = 0;
integer enable_count = 0;
always_comb begin : next_state_logic
next_state = state;
case (state)
INIT: next_state = start_count > 3 ? ENABLE : INIT; // start_count: wait for 80ns
START: next_state = start_count > 3 ? ENABLE : START;
ENABLE: next_state = enable_count < 16 ? ENABLE : WAIT; // Wait 320ns
WAIT: next_state = delay_count < 262142 ? WAIT : NEXT; // Wait for 262142 cycles -> 5.24284 ms
NEXT: next_state = initialise_index < 4 ? INIT : START; // Stay in initialisation sequence
endcase
end
always_ff @(posedge clk) begin : fsm_ff
state <= next_state;
end
assign LCD_EN = state == ENABLE;
assign in_data.ready = state == START; // Only ready for new data in the start state
logic in_data_handshake; // Store if the handshake has taken place
always_ff @(posedge clk) begin : output_ff
case(state)
INIT: begin
LCD_DATA <= init_data[7:0]; // First 8 bits = DB* data bits
LCD_RW <= init_data[8]; // RS bit
LCD_RS <= init_data[9]; // RS bit
start_count <= start_count + 1;
end
START: begin
LCD_DATA <= in_data.data[7:0];
LCD_RW <= in_data.data[8];
LCD_RS <= in_data.data[9];
if (in_data_handshake) start_count <= start_count + 1; // If handshake already occured, start counting. Start_count: wait for 80ns
else in_data_handshake <= in_data.valid; // Handshake occured
end
ENABLE: begin
enable_count <= enable_count+1; // Wait 320ns
start_count <= 0;
in_data_handshake <= 0; // Reset handshake for next packet.
end
WAIT: begin
delay_count <= delay_count+1; // Wait for 262142 cycles -> 5.24284 ms
enable_count <= 0;
end
NEXT: begin
delay_count <= 0;
initialise_index <= initialise_index+1; // Move to next initialisation instruction.
end
endcase
end
/* Initialise Lookup Table : */
always_comb begin : init_lut
case(initialise_index)
// Initial
0: init_data = 10'h038; // Function set
1: init_data = 10'h00C; // Display on
2: init_data = 10'h001; // Clear Display
3: init_data = 10'h006; // Entry mode
4: init_data = 10'h080; // DDRAM Addr set to 0 10'b0010000000 //for lower screen 10'b0011000000
default: init_data = 10'h010; // Return Home
endcase
end
endmodule
module top_level (
input CLOCK_50, // 50 MHz
output LCD_BLON,
inout [7:0] LCD_DATA,
output LCD_EN,
output LCD_ON,
output LCD_RS,
output LCD_RW
);
dstream #(.N(10)) in_data (CLOCK_50);
lcd_driver u5 (.clk(CLOCK_50), .*);
logic [9:0] instructions [0:15] ='{10'h220, 10'h220, 10'h248, 10'h265, 10'h26C,
10'h26C, 10'h26F, 10'h220, 10'h220, 10'h257, 10'h26F, 10'h272, 10'h26C, 10'h264, 10'h220, 10'h220};
integer count=0;
always_ff @(posedge CLOCK_50) begin // Read instructions and pass them to the LCD driver module.
count <= count + 1;
in_data.valid <= 0;
if(count[23:0] == 24'hFFFFFF) begin // Write to the display every ~0.34 seconds (2^24 counts)
// Implementation note: we should really check for a handshake before moving to the next instruction!
in_data.out.data <= instructions[count[27:24]]; // Clever trick to count every ~0.67 seconds.
in_data.valid <= 1; // pulse valid.
end
if(count[28] == 1'b1) count <= count; // Pause count once it gets to 2^28.
end
endmodule
目前我只收到一条消息,即说明,但我想稍后再写一行。我相信第 2 行的 DDRAM 地址是 h'040。有人可以帮我吗?
我尝试实例化另一个 lcd_driver 但无法使其工作。另一种方法是获得一个大数组,但间距使其变得太复杂并且从未得到正确的结果。
尝试以下更改:
module lcd_driver (
input clk,
dstream.in in_data,
output logic [7:0] LCD_DATA,
output logic LCD_RW, LCD_EN, LCD_RS, LCD_ON, LCD_BLON
);
// ... (existing code)
// Additional state variables for second line printing
enum logic [2:0] {INIT, START, ENABLE, WAIT, NEXT, LINE2_INIT, LINE2_START} state, next_state;
logic [5:0] initialise_index = 0;
logic [9:0] init_data;
integer start_count = 0;
integer delay_count = 0;
integer enable_count = 0;
// ... (existing code)
always_ff @(posedge clk) begin : output_ff
state <= next_state;
end
// Add logic for printing the second line
always_ff @(posedge clk) begin : second_line_logic
if (state == LINE2_INIT) begin
// Initialize for printing the second line
initialise_index <= 0;
init_data <= 10'h0C0; // Set DDRAM address to 0x40 (second line)
end
else if (state == LINE2_START) begin
// Print the second line
LCD_DATA <= in_data.data[7:0];
LCD_RW <= in_data.data[8];
LCD_RS <= in_data.data[9];
end
end
// Modify the existing FSM logic to transition to the second line printing
always_ff @(posedge clk) begin : fsm_ff
if (state == NEXT && initialise_index == 3) begin
next_state <= LINE2_INIT; // Transition to initialize second line printing
end
else begin
next_state <= state;
end
end
// ... (existing code)
endmodule