Verilog流水线
Verilog pipeline
我正在尝试使用 HD44780 LCD 制作一款简单的游戏。
我的想法是使用 BUSY 信号来推迟任何命令,直到执行前一个命令。我想对命令序列使用计数器和大小写,而另一个块由 BUSY 信号保持。
像这样:
case (counter)
0: CMD_REG = CLEAR_LCD;
1: CMD_REG = WRITE_PLR;
2: ME_BUSY = 0;
endcase
if(DRIVER_BUSY == 0 && counter < 2) begin
ENABLE_DRIVER <= 1;
counter <= counter + 1;
end
if (counter > 2) begin
counter <= 4'd0;
end
但感觉"wrong"。我对 Verilog 没有任何认真的经验,所以有人可以告诉我应该怎么做吗?
虽然您的想法似乎不错,但使用有限状态机 [FSM] ( http://en.wikipedia.org/wiki/Finite-state_machine ) 可能会更好。这几乎意味着您将拥有一个变量来保存一系列具有更易读名称的状态,而不是计数器。使用它,您只需要一个 case 语句来定义您的下一个状态和输出逻辑,具体取决于当前状态。
虽然这个 FSM 基本上是作为一个计数器来实现的,但它更容易阅读。我无法确切地说出如何使用您的代码来实现它,但它可能看起来像这样:
// State register
always @(posedge clk) begin
state <= next_state;
end
// Next state and output logic
always @(*) begin
// Default values
CMD_REG = CLEAR_LCD;
ME_BUSY = 1'b0;
ENABLE_DRIVER = 1'b0;
next_state = WAIT; // Im using enum style, but if you cant use enums, you can always use macros (`WAIT)
case (state)
WAIT: begin // counter == 0
if (DRIVER_BUSY == 0) begin
next_state = WAIT_MORE;
end
WAIT_MORE: begin // counter == 1
ENABLE_DRIVER = 1'b1;
CMD_REG = WRITE_PLR;
if (DRIVER_BUSY == 0) begin
next_state = NOT_BUSY_HOLD;
end
NOT_BUSY_HOLD: begin // counter == 2, here it looks like you get stuck due to your conditionals (at counter == 2, it doesnt increment nor reset)
...
但你很有希望得到这个想法。
我正在尝试使用 HD44780 LCD 制作一款简单的游戏。 我的想法是使用 BUSY 信号来推迟任何命令,直到执行前一个命令。我想对命令序列使用计数器和大小写,而另一个块由 BUSY 信号保持。
像这样:
case (counter)
0: CMD_REG = CLEAR_LCD;
1: CMD_REG = WRITE_PLR;
2: ME_BUSY = 0;
endcase
if(DRIVER_BUSY == 0 && counter < 2) begin
ENABLE_DRIVER <= 1;
counter <= counter + 1;
end
if (counter > 2) begin
counter <= 4'd0;
end
但感觉"wrong"。我对 Verilog 没有任何认真的经验,所以有人可以告诉我应该怎么做吗?
虽然您的想法似乎不错,但使用有限状态机 [FSM] ( http://en.wikipedia.org/wiki/Finite-state_machine ) 可能会更好。这几乎意味着您将拥有一个变量来保存一系列具有更易读名称的状态,而不是计数器。使用它,您只需要一个 case 语句来定义您的下一个状态和输出逻辑,具体取决于当前状态。
虽然这个 FSM 基本上是作为一个计数器来实现的,但它更容易阅读。我无法确切地说出如何使用您的代码来实现它,但它可能看起来像这样:
// State register
always @(posedge clk) begin
state <= next_state;
end
// Next state and output logic
always @(*) begin
// Default values
CMD_REG = CLEAR_LCD;
ME_BUSY = 1'b0;
ENABLE_DRIVER = 1'b0;
next_state = WAIT; // Im using enum style, but if you cant use enums, you can always use macros (`WAIT)
case (state)
WAIT: begin // counter == 0
if (DRIVER_BUSY == 0) begin
next_state = WAIT_MORE;
end
WAIT_MORE: begin // counter == 1
ENABLE_DRIVER = 1'b1;
CMD_REG = WRITE_PLR;
if (DRIVER_BUSY == 0) begin
next_state = NOT_BUSY_HOLD;
end
NOT_BUSY_HOLD: begin // counter == 2, here it looks like you get stuck due to your conditionals (at counter == 2, it doesnt increment nor reset)
...
但你很有希望得到这个想法。