Skip to content
Snippets Groups Projects
gl_avalon_intf.sv 5.68 KiB
Newer Older
  • Learn to ignore specific revisions
  • Fang Lu's avatar
    Fang Lu committed
    /**
     *	gl_avalon_intf
     *
     *	Avalon-MM interface for GL modules
     *
    
    Fang Lu's avatar
    Fang Lu committed
     *	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
    
    Fang Lu's avatar
    Fang Lu committed
     */
    
    module gl_avalon_intf (
    	// Avalon Clock Input
    
    Fang Lu's avatar
    Fang Lu committed
    	input logic CLOCK, RESET,
    
    Fang Lu's avatar
    Fang Lu committed
    
    	// GL Controller Slave
    
    Fang Lu's avatar
    Fang Lu committed
    	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,
    
    Fang Lu's avatar
    Fang Lu committed
    
    	// 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
    );
    
    
    Fang Lu's avatar
    Fang Lu committed
    // 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_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_WAITREQ <= 1'b0;
    		avl_sram_writereq <= 1'b0;
    	end else begin
    		AVL_SRAM_WAITREQ <= avl_sram_wait_next;
    		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_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;
    	if(AVL_SRAM_WAITREQ) begin
    		// IO inhibited, wait for ready signal
    		if (avl_sram_ready) begin
    			// Done!
    			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
    	end
    
    Fang Lu's avatar
    Fang Lu committed
    
    
    Fang Lu's avatar
    Fang Lu committed
    end
    
    Fang Lu's avatar
    Fang Lu committed
    
    
    Fang Lu's avatar
    Fang Lu committed
    endmodule // gl_avalon_intf