我正在尝试使用缓冲区使当前项目中的动画更加平滑。 我能够在没有缓冲的情况下正确实现它,并且玩家角色可以平稳移动。但是由于某种原因,玩家角色只能在5到10秒内移动一次。
我尝试模拟并查看海浪,但到目前为止,海浪似乎已经发现,并且无法解释屏幕刷新缓慢的原因。刷新速度很慢,但是绘制得很完美,没有任何闪烁。
这是可能导致问题的缓冲区代码,
module m_engine
(
input wire CLK100MHZ,
input wire [4:0] BTN,
input wire [15:0] SW,
output wire [6:0] SG,
output wire [7:0] AN,
output wire [15:0] LED,
output wire VGA_HS,
output wire VGA_VS,
output reg [3:0] VGA_R,
output reg [3:0] VGA_G,
output reg [3:0] VGA_B
);
/****************************************************************************/
// Simulation
/****************************************************************************/
// reg CLK100MHZ = 0, r_display_clock = 0;
// initial forever #1 CLK100MHZ = ~CLK100MHZ;
// initial forever #2 r_display_clock = ~r_display_clock;
//
// assign w_display_clock = r_display_clock;
/****************************************************************************/
/****************************************************************************/
// Display
/****************************************************************************/
wire w_display_clock;
wire [10:0] w_display_x;
wire [10:0] w_display_y;
wire w_display_active;
wire w_display_reset;
wire w_display_frame;
reg [11:0] r_display_out;
CLK40MHZ display_clock (w_display_clock, CLK100MHZ);
assign w_display_reset = SW[15];
always @ (posedge CLK100MHZ)
begin
if (w_display_active)
begin
VGA_R <= r_display_out[11:8];
VGA_G <= r_display_out[7:4];
VGA_B <= r_display_out[3:0];
end
else
begin
VGA_R <= 0;
VGA_G <= 0;
VGA_B <= 0;
end
end
m_vga display
(
.iw_clock (w_display_clock),
.iw_rst (w_display_reset),
.ow_hs (VGA_HS),
.ow_vs (VGA_VS),
.ow_x (w_display_x),
.ow_y (w_display_y),
.ow_active (w_display_active),
.ow_frame (w_display_frame)
);
/****************************************************************************/
/****************************************************************************/
// VRAM
/****************************************************************************/
localparam DISPLAY_WIDTH = 800;
localparam DISPLAY_HEIGHT = 600;
localparam VRAM_DEPTH = DISPLAY_WIDTH * DISPLAY_HEIGHT;
localparam VRAM_ADDR_WIDTH = 19;
localparam VRAM_DATA_WIDTH = 4;
reg [VRAM_ADDR_WIDTH - 1:0] r_vram_address;
wire [VRAM_DATA_WIDTH - 1:0] w_vram0_dataout, w_vram1_dataout;
reg [VRAM_DATA_WIDTH - 1:0] r_vram_datain;
reg r_vram_write = 0;
always @(posedge CLK100MHZ)
begin
r_vram_address <= w_display_y * DISPLAY_WIDTH + w_display_x;
// Display content of active VRAM
r_display_out = (r_vram_write) ? w_vram1_dataout : w_vram0_dataout;
end
// At the end of every frame switch buffers.
always @(posedge w_display_frame)
r_vram_write = ~r_vram_write;
m_sram
#(
.ADDR_WIDTH (VRAM_ADDR_WIDTH),
.DATA_WIDTH (VRAM_DATA_WIDTH),
.DEPTH (VRAM_DEPTH)
)
vram0
(
.iw_addr (r_vram_address),
.iw_clock (CLK100MHZ),
.iw_write (r_vram_write),
.or_data (w_vram0_dataout),
.iw_data (r_vram_datain)
);
m_sram
#(
.ADDR_WIDTH (VRAM_ADDR_WIDTH),
.DATA_WIDTH (VRAM_DATA_WIDTH),
.DEPTH (VRAM_DEPTH)
)
vram1
(
.iw_addr (r_vram_address),
.iw_clock (CLK100MHZ),
.iw_write (!r_vram_write),
.or_data (w_vram1_dataout),
.iw_data (r_vram_datain)
);
/****************************************************************************/
/****************************************************************************/
// Game Logic
/****************************************************************************/
reg [10:0] r_player_x = 400, r_player_y = 300;
wire w_player_draw;
wire [VRAM_DATA_WIDTH - 1:0] w_player_dataout;
m_entity
#(
.ADDR_WIDTH (VRAM_ADDR_WIDTH),
.DATA_WIDTH (VRAM_DATA_WIDTH),
.ENTITY_SIZE (32),
.MEMFILE("fighter.mem")
)
player
(
.iw_clock (CLK100MHZ),
.iw_draw_x (w_display_x),
.iw_draw_y (w_display_y),
.iw_pos_x (r_player_x),
.iw_pos_y (r_player_y),
.ow_draw (w_player_draw),
.or_data (w_player_dataout)
);
reg [11:0] r_player_palette [0:255];
initial
begin
$display("Loading sprite r_player_palette.");
$readmemh("fighter_palette.mem", r_player_palette);
end
reg [20:0] r_i = 0;
always @(posedge CLK100MHZ)
begin
// Player control
r_i <= r_i + 1;
if(r_i == 0)
begin
if (BTN[3] && r_player_x < DISPLAY_WIDTH - 32)
r_player_x <= r_player_x + 1;
if (BTN[2] && r_player_x > 0)
r_player_x <= r_player_x - 1;
if (BTN[4] && r_player_y < DISPLAY_HEIGHT - 32)
r_player_y <= r_player_y + 1;
if (BTN[1] && r_player_y > 0)
r_player_y <= r_player_y - 1;
end
// Player draw
if (w_player_draw) r_vram_datain <= w_player_dataout;
else r_vram_datain <= 12'b111111111;
/****************************************************************************/
endmodule
还有一件事,背景应该是白色的,因为当我不绘制播放器但由于某种原因屏幕是蓝色时,我将111111111111输入到VGA中。我也不知道是什么原因造成的。
答案 0 :(得分:0)
好的。我又以某种方式自己解决了。事实证明,VRAM的时钟频率必须与显示器匹配才能正常工作。不是它的运行如此平稳以至于令人难以置信!
还找出了背景为何变成蓝色的原因。我忘了我减少了VRAM的数据宽度,因为我用完了MUX。因此,基本上,VRAM仅输出4位,这就是蓝色背景的原因。