module mojo_top(
    // 50MHz clock input
    input clk,
    // Input from reset button (active low)
    input rst_n,
    // Outputs to the 8 onboard LEDs
    output[7:0]led,
	 output[3:0] hdmi1_tmds,
    output[3:0] hdmi1_tmdsb,
	 input zclk,
	 input zioreq,
	 input zwr,
	 input zm1,
	 input zrd,
	 input[7:0] zdata,
	 input[3:0] zaddr
);

wire rst = ~rst_n; // make reset active high
reg [7:0] red, green, blue;
wire [11:0] x;
wire [10:0] y;
wire [5:0] scroll;
reg[3:0] charx;
reg[3:0] chary;
wire hclk;
wire mclk;
wire [15:0] xy;
wire [7:0] screen_x;
wire [7:0] screen_y;
reg [12:0] waddr;
wire [15:0] write_data;
wire write_enable;

reg [12:0] raddr;
wire [15:0] read_data;
wire [255:0] char;

reg [1:0] control_in;
// 0 Correct address
// 1 Write

wire[23:0] foreground;
wire[23:0] background;

assign led[5:0] = scroll[5:0];
assign led[7:6] = 0;

assign screen_x[7:0] = xy[7:0];
assign screen_y[7:0] = xy[15:8];

hdmi_clk hdmi_clk(.CLK_IN1(clk), .CLK_OUT1(hclk), .CLK_OUT2(mclk));

localparam HEIGHT = 720;
localparam WIDTH = 1280;
hdmi_encoder #(.Y_RES(HEIGHT), .X_RES(WIDTH), .Y_FRAME(HEIGHT+2*16), .X_FRAME(WIDTH+24*16)) hdmi(
    .clk(hclk), 
    .rst(rst), 
    .tmds(hdmi1_tmds), 
    .tmdsb(hdmi1_tmdsb), 
    .x(x), 
    .y(y), 
    .red(red), 
    .green(green), 
    .blue(blue)
);
	 
microblaze_mcs mcs_0 (
  .Clk(mclk), // input Clk
  .Reset(rst), // input Reset
  .GPO1(write_data), // output [15 : 0] GPO1
  .GPO2(xy), // output [15 : 0] GPO2
  .GPO3(write_enable), // output [0 : 0] GPO3
  .GPO4(scroll), // output [5 : 0] GPO4
  .GPI1(zdata), // input [7 : 0] GPI1
  .GPI1_Interrupt(), // output GPI1_Interrupt
  .GPI2(zclk), // input [0 : 0] GPI2
  .GPI2_Interrupt(), // output GPI2_Interrupt
  .GPI3(control_in), // input [1 : 0] GPI3
  .GPI3_Interrupt(), // output GPI3_Interrupt
  .INTC_IRQ() // output INTC_IRQ
);

simple_dual_ram #(.SIZE(16), .DEPTH((80+24)*(45+2))) sram (
    .wclk(mclk), 
    .waddr(waddr), 
    .write_data(write_data), 
    .write_en(write_enable), 
    .rclk(hclk), 
    .raddr(raddr), 
    .read_data(read_data)
);

char_map char_map (
    .clk(hclk), 
    .index(read_data[7:0]), 
    .char(char)
);

color_map foreground_map (
	.clk(hclk),
	.colorcode(read_data[11:8]),
	.color(foreground)
);
	
color_map backgroundground_map (
	.clk(hclk),
	.colorcode(read_data[15:12]),
	.color(background)
);
	 
always @(*) begin
	charx = (x >> 0) % 16;
	chary = (y >> 0) % 16;
	
	waddr = (screen_x % (80+24)) + (80+24)*((screen_y + scroll) % (45+2));
	raddr = (((x+2) >> 4) % (80+24)) + (80+24)*((( (x > WIDTH) ? ((y+1) >> 4) : (y >> 4) ) + scroll) % (45+2));
	
	if (zaddr == 4'h02) begin
		control_in[0] = 1;
	end else begin
		control_in[0] = 0;
	end
	
	if (zioreq == 0 && zm1 == 1 && zwr == 0) begin
		control_in[1] = 1;
	end else begin
		control_in[1] = 0;
	end
	
	// @todo Instead of doing + 17 we safe space in the char rom
	if (char[255 - charx - 16*chary] == 1) begin
		red = foreground[23:16];
		green = foreground[15:8];
		blue = foreground[7:0];
	end else begin
		red = background[23:16];
		green = background[15:8];
		blue = background[7:0];
	end
end

endmodule