Skip to content
Snippets Groups Projects
gl_avalon_intf.sv 6.13 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[3]:	Background dimming
    
    Fang Lu's avatar
    Fang Lu committed
     *	* 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 [7:0] gl_bg_dim, gl_bg_dim_in;
    
    Fang Lu's avatar
    Fang Lu committed
    
    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),
    
    	.BG_DIM           (gl_bg_dim),
    
    Fang Lu's avatar
    Fang Lu committed
    	.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
    
    Fang Lu's avatar
    Fang Lu committed
    logic avl_sram_waitreq, avl_sram_wait_next, avl_sram_writereq, avl_sram_writereq_next;
    
    Fang Lu's avatar
    Fang Lu committed
    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
    
    Fang Lu's avatar
    Fang Lu committed
    		avl_sram_waitreq <= 1'b0;
    
    Fang Lu's avatar
    Fang Lu committed
    		avl_sram_writereq <= 1'b0;
    	end else begin
    
    Fang Lu's avatar
    Fang Lu committed
    		avl_sram_waitreq <= avl_sram_wait_next;
    
    Fang Lu's avatar
    Fang Lu committed
    		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
    
    Fang Lu's avatar
    Fang Lu committed
    	AVL_SRAM_WAITREQ = 1'b0;
    	avl_sram_wait_next = avl_sram_waitreq;
    
    Fang Lu's avatar
    Fang Lu committed
    	avl_sram_writereq_next = avl_sram_writereq;
    	avl_sram_addr_next = avl_sram_addr;
    	avl_sram_data_next = avl_sram_data;
    
    Fang Lu's avatar
    Fang Lu committed
    	if(avl_sram_waitreq) begin
    
    Fang Lu's avatar
    Fang Lu committed
    		// IO inhibited, wait for ready signal
    
    Fang Lu's avatar
    Fang Lu committed
    		AVL_SRAM_WAITREQ = 1'b1;
    
    Fang Lu's avatar
    Fang Lu committed
    		if (avl_sram_ready) begin
    			// Done!
    
    Fang Lu's avatar
    Fang Lu committed
    			AVL_SRAM_WAITREQ = 1'b0;
    
    Fang Lu's avatar
    Fang Lu committed
    			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;
    
    Fang Lu's avatar
    Fang Lu committed
    			AVL_SRAM_WAITREQ = 1'b1;
    
    Fang Lu's avatar
    Fang Lu committed
    			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
    
    Fang Lu's avatar
    Fang Lu committed
    		gl_bg_dim <= 8'b10000000;
    
    Fang Lu's avatar
    Fang Lu committed
    	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
    
    Fang Lu's avatar
    Fang Lu committed
    		gl_bg_dim <= gl_bg_dim_in;
    
    Fang Lu's avatar
    Fang Lu committed
    	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
    
    	gl_bg_dim_in = gl_bg_dim;
    
    Fang Lu's avatar
    Fang Lu committed
    
    	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
    
    Fang Lu's avatar
    Fang Lu committed
    		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