Newer
Older
/**
* gl_avalon_intf
*
* Avalon-MM interface for GL modules
*
* Slave 1: GL MM Registers
* * gl[0]: Status flags (readonly)
* * gl[1]: Draw time (readonly)
* * gl[2]: Draw command
* * gl[4-7]: Unused
* * gl[8-15]: Args
*
* Before issuing any new commands, please first make sure no command is in
* progress by waiting for GL_DONE flag going low. You should also check the
* GL_TIMEOUT flag.
* To issue a drawing command, first set the args registers. Then set gl[2]
* to the desired drawing command. This will instantly starts drawing and set
* draw enable to high. You could then wait for GL_DONE flag to go low, but
* postponing this waiting till the beginning of the next command is
* recommended so that software could utilize the meantime. To issue the next
* command, set the command register again, even if the command is the same
* because painting execution is initiated on each write request. In the same
* way, the command register should be set exactly once per execution, otherwse
* the same operation may be repeated and cause undefined behavior.
*
* Slave 2: SRAM
input logic AVL_GL_READ,
input logic AVL_GL_WRITE,
input logic AVL_GL_CS,
input logic [3:0] AVL_GL_BYTE_EN,
input logic [3:0] AVL_GL_ADDR,
input logic [31:0] AVL_GL_WRITEDATA,
output logic [31:0] AVL_GL_READDATA,
// SRAM Slave
input logic AVL_SRAM_READ,
input logic AVL_SRAM_WRITE,
input logic AVL_SRAM_CS,
input logic [3:0] AVL_SRAM_BYTE_EN,
input logic [19:0] AVL_SRAM_ADDR,
input logic [31:0] AVL_SRAM_WRITEDATA,
output logic [31:0] AVL_SRAM_READDATA,
output logic AVL_SRAM_WAITREQ,
// Palette Slave
input logic AVL_PLT_READ,
input logic AVL_PLT_WRITE,
input logic AVL_PLT_CS,
input logic [3:0] AVL_PLT_BYTE_EN,
input logic [7:0] AVL_PLT_ADDR,
input logic [31:0] AVL_PLT_WRITEDATA,
output logic [31:0] AVL_PLT_READDATA,
// SRAM Conduit
output logic [19:0] SRAM_ADDR,
inout wire [15:0] SRAM_DQ,
output logic SRAM_UB_N, SRAM_LB_N, SRAM_CE_N, SRAM_OE_N, SRAM_WE_N,
// VGA Conduit
output logic VGA_CLK,
output logic [7:0] VGA_R, VGA_G, VGA_B,
output logic VGA_SYNC_N, VGA_BLANK_N, VGA_VS, VGA_HS
);
// GL
logic gl_frame_finished, gl_done, gl_timeout;
logic [9:0] gl_drawtime;
logic [3:0] gl_cmd, gl_cmd_in;
logic [31:0] gl_args[8], gl_args_in[8];
logic gl_exec, gl_exec_next;
logic avl_sram_ready;
gl_mgr gl_inst(
.CLOCK (CLOCK),
.RESET (RESET),
.GL_FRAME_FINISHED(gl_frame_finished),
.GL_TIMEOUT (gl_timeout),
.GL_DRAWTIME (gl_drawtime),
.GL_CMD (gl_cmd),
.GL_ARG1 (gl_args[0]),
.GL_ARG2 (gl_args[1]),
.GL_ARG3 (gl_args[2]),
.GL_ARG4 (gl_args[3]),
.GL_ARG5 (gl_args[4]),
.GL_ARG6 (gl_args[5]),
.GL_ARG7 (gl_args[6]),
.GL_ARG8 (gl_args[7]),
.GL_EXEC (gl_exec),
.GL_DONE (gl_done),
.AVL_REQ (avl_sram_writereq),
.AVL_ADDR (avl_sram_addr),
.AVL_DATA (avl_sram_data),
.AVL_READY (avl_sram_ready),
.AVL_PLT_RD (AVL_PLT_CS & AVL_PLT_READ),
.AVL_PLT_WR (AVL_PLT_CS & AVL_PLT_WRITE),
.AVL_PLT_INDEX (AVL_PLT_ADDR),
.AVL_PLT_RD_COLOR (AVL_PLT_READDATA[23:0]),
.AVL_PLT_WR_COLOR ({8'h0,AVL_PLT_WRITEDATA}),
.*);
assign AVL_SRAM_READDATA = 32'hCCCCCCCC; // SRAM is write-only
assign AVL_PLT_READDATA[31:24] = 8'h0;
// Avalon SRAM write pipeline
logic avl_sram_waitreq, avl_sram_wait_next, avl_sram_writereq, avl_sram_writereq_next;
logic [19:0] avl_sram_addr, avl_sram_addr_next;
logic [16:0] avl_sram_data, avl_sram_data_next;
always_ff @(posedge CLOCK) begin
if(RESET) begin
avl_sram_writereq <= avl_sram_writereq_next;
end
avl_sram_addr <= avl_sram_addr_next;
avl_sram_data <= avl_sram_data_next;
end
always_comb begin
AVL_SRAM_WAITREQ = 1'b0;
avl_sram_wait_next = avl_sram_waitreq;
avl_sram_writereq_next = avl_sram_writereq;
avl_sram_addr_next = avl_sram_addr;
avl_sram_data_next = avl_sram_data;
avl_sram_wait_next = 1'b0;
avl_sram_writereq_next = 1'b0;
end
end else begin
// IO available, listen for incoming write request
if (AVL_SRAM_CS & AVL_SRAM_WRITE & (AVL_SRAM_BYTE_EN[1:0] == 2'b11)) begin
avl_sram_wait_next = 1'b1;
avl_sram_writereq_next = 1'b1;
avl_sram_addr_next = AVL_SRAM_ADDR;
avl_sram_data_next = AVL_SRAM_WRITEDATA[16:0];
end
end
end
// GL controller
always_ff @(posedge CLOCK) begin
if(RESET) begin
gl_cmd <= 4'h0;
gl_exec <= 1'b0;
for (int i = 0; i < 8; i++) begin
gl_args[i] <= 0;
end
end else begin
gl_cmd <= gl_cmd_in;
gl_exec <= gl_exec_next;
for (int i = 0; i < 8; i++) begin
gl_args[i] <= gl_args_in[i];
end
end
end
always_comb begin
gl_cmd_in = gl_cmd;
gl_exec_next = gl_exec;
for (int i = 0; i < 8; i++) begin
gl_args_in[i] = gl_args[i];
end
AVL_GL_READDATA = 32'hCCCCCCCC;
if(AVL_GL_CS & AVL_GL_READ) begin
case (AVL_GL_ADDR)
4'd0: AVL_GL_READDATA = {29'b0, gl_timeout, gl_frame_finished, gl_done};
4'd1: AVL_GL_READDATA = {21'b0, gl_drawtime};
4'd2: AVL_GL_READDATA = {28'b0, gl_cmd};
endcase
if (AVL_GL_ADDR[3]) begin
AVL_GL_READDATA = gl_args[AVL_GL_ADDR[2:0]];
end
end
if (AVL_GL_CS & AVL_GL_WRITE) begin
if (AVL_GL_ADDR[3]) begin
if (AVL_GL_BYTE_EN == 4'hf)
gl_args_in[AVL_GL_ADDR[2:0]] = AVL_GL_WRITEDATA;
end else if (AVL_GL_ADDR == 4'd2) begin
if (AVL_GL_BYTE_EN[0]) begin
// Initiate new command
gl_cmd_in = AVL_GL_WRITEDATA[3:0];
gl_exec_next = 1'b1;
end
end else if (AVL_GL_ADDR == 4'd3) begin
if (AVL_GL_BYTE_EN[0]) begin
// Background dimming
gl_bg_dim_in = AVL_GL_WRITEDATA[7:0];
end