diff --git a/HDMI.alp b/HDMI.alp
index 668f553..681dfbe 100644
--- a/HDMI.alp
+++ b/HDMI.alp
@@ -17,7 +17,8 @@
cclk_detector.luc
tmds_encoder.luc
mojo.ucf
- hdmi.ucf
+ hdmi2.ucf
+ z80.ucf
..\clk_wiz_v3_6.v
diff --git a/constraint/hdmi2.ucf b/constraint/hdmi2.ucf
new file mode 100644
index 0000000..2cdfb86
--- /dev/null
+++ b/constraint/hdmi2.ucf
@@ -0,0 +1,8 @@
+NET "hdmi1_tmds(3)" LOC = "P144" |IOSTANDARD = TMDS_33 | CLOCK_DEDICATED_ROUTE = FALSE ; # Clock
+NET "hdmi1_tmdsb(3)" LOC = "P143" |IOSTANDARD = TMDS_33 | CLOCK_DEDICATED_ROUTE = FALSE ;
+NET "hdmi1_tmds(2)" LOC = "P138" |IOSTANDARD = TMDS_33 ; # Red
+NET "hdmi1_tmdsb(2)" LOC = "P137" |IOSTANDARD = TMDS_33 ;
+NET "hdmi1_tmds(1)" LOC = "P140" |IOSTANDARD = TMDS_33 ; # Green
+NET "hdmi1_tmdsb(1)" LOC = "P139" |IOSTANDARD = TMDS_33 ;
+NET "hdmi1_tmds(0)" LOC = "P142" |IOSTANDARD = TMDS_33 ; # Blue
+NET "hdmi1_tmdsb(0)" LOC = "P141" |IOSTANDARD = TMDS_33 ;
\ No newline at end of file
diff --git a/constraint/z80.ucf b/constraint/z80.ucf
new file mode 100644
index 0000000..b2632e0
--- /dev/null
+++ b/constraint/z80.ucf
@@ -0,0 +1,20 @@
+NET "z80_clk" LOC = P23 | IOSTANDARD = LVTTL;
+NET "z80_data(2)" LOC = P114 | IOSTANDARD = LVTTL;
+NET "z80_data(3)" LOC = P115 | IOSTANDARD = LVTTL;
+NET "z80_data(1)" LOC = P116 | IOSTANDARD = LVTTL;
+NET "z80_data(0)" LOC = P117 | IOSTANDARD = LVTTL;
+NET "z80_data(4)" LOC = P118 | IOSTANDARD = LVTTL;
+NET "z80_data(5)" LOC = P119 | IOSTANDARD = LVTTL;
+NET "z80_data(6)" LOC = P120 | IOSTANDARD = LVTTL;
+NET "z80_data(7)" LOC = P121 | IOSTANDARD = LVTTL;
+// NET "z80_address(0)" LOC = P9 | IOSTANDARD = LVTTL;
+// NET "z80_address(1)" LOC = P10 | IOSTANDARD = LVTTL;
+// NET "z80_address(2)" LOC = P11 | IOSTANDARD = LVTTL;
+// NET "z80_address(3)" LOC = P12 | IOSTANDARD = LVTTL;
+// NET "z80_address(4)" LOC = P13 | IOSTANDARD = LVTTL;
+// NET "z80_address(5)" LOC = P14 | IOSTANDARD = LVTTL;
+// NET "z80_address(6)" LOC = P15 | IOSTANDARD = LVTTL;
+// NET "z80_address(7)" LOC = P16 | IOSTANDARD = LVTTL;
+NET "z80_ioreq" LOC = P24 | IOSTANDARD = LVTTL;
+NET "z80_wr" LOC = P21 | IOSTANDARD = LVTTL;
+NET "z80_m1" LOC = P22 | IOSTANDARD = LVTTL;
diff --git a/source/mojo_top.v b/source/mojo_top.v
index 72b22dc..c91e1df 100644
--- a/source/mojo_top.v
+++ b/source/mojo_top.v
@@ -19,8 +19,14 @@ module mojo_top(
output avr_rx, // AVR Rx => FPGA Tx
input avr_rx_busy, // AVR Rx buffer full
output[3:0] hdmi1_tmds,
- output[3:0] hdmi1_tmdsb
- );
+ output[3:0] hdmi1_tmdsb,
+ input z80_clk,
+ input[7:0] z80_data,
+ // input[7:0] z80_address,
+ input z80_ioreq,
+ input z80_wr,
+ input z80_m1
+ );
wire rst = ~rst_n; // make reset active high
@@ -36,7 +42,7 @@ module mojo_top(
.CLK_IN1(clk),
.CLK_OUT1(hdmi_clk)
);
-
+
localparam SCALE = 2;
localparam WIDTH = 1280;
localparam HEIGHT = 720;
@@ -47,7 +53,7 @@ module mojo_top(
// @todo 1080p30 does not work for some reason (already extended number of bits)
hdmi_encoder #(.Y_RES(HEIGHT), .X_RES(WIDTH), .Y_FRAME(HEIGHT+30), .X_FRAME(WIDTH+387)) hdmi(
- // hdmi_encoder #(.Y_RES(HEIGHT), .X_RES(WIDTH), .Y_FRAME(HEIGHT+45), .X_FRAME(WIDTH+303)) hdmi(
+ // hdmi_encoder #(.Y_RES(HEIGHT), .X_RES(WIDTH), .Y_FRAME(HEIGHT+45), .X_FRAME(WIDTH+303)) hdmi(
.clk(hdmi_clk),
.rst(rst),
.tmds(hdmi1_tmds),
@@ -61,7 +67,7 @@ module mojo_top(
wire [29:0] char_data [94:0];
- assign char_data[0] = 30'h00000000; //
+ assign char_data[0] = 30'h00000000; //
assign char_data[1] = 30'h1CE7380E; // !
assign char_data[2] = 30'h14A00000; // "
assign char_data[3] = 30'hAFABEA; // #
@@ -158,83 +164,91 @@ module mojo_top(
assign char_data[94] = 30'hAA0000; // ~
reg[13:0] char_index_q, char_index_d;
-
+
reg[10:0] charx;
reg[9:0] chary;
-
+
reg[7:0] tx_data;
reg new_tx_data;
wire tx_busy;
wire[7:0] rx_data;
wire new_rx_data;
-
+ reg[5:0] char_color;
+ reg char_attribute;
+
assign led[7:0] = rx_data;
-
+
avr_interface #(.CLK_FREQ(75000000)) vr_interface (
- .clk(hdmi_clk),
- .rst(rst),
- .cclk(cclk),
- .spi_miso(spi_miso),
- .spi_mosi(spi_mose),
- .spi_sck(spi_sck),
- .spi_ss(spi_ss),
- .spi_channel(spi_channel),
- .tx(avr_rx),
- .rx(avr_tx),
- .channel(4'd15),
- .new_sample(),
- .sample(),
- .sample_channel(),
- .tx_data(tx_data),
- .new_tx_data(new_tx_data),
- .tx_busy(tx_busy),
- .tx_block(avr_rx_busy),
- .rx_data(rx_data),
- .new_rx_data(new_rx_data)
+ .clk(hdmi_clk),
+ .rst(rst),
+ .cclk(cclk),
+ .spi_miso(spi_miso),
+ .spi_mosi(spi_mose),
+ .spi_sck(spi_sck),
+ .spi_ss(spi_ss),
+ .spi_channel(spi_channel),
+ .tx(avr_rx),
+ .rx(avr_tx),
+ .channel(4'd15),
+ .new_sample(),
+ .sample(),
+ .sample_channel(),
+ .tx_data(tx_data),
+ .new_tx_data(new_tx_data),
+ .tx_busy(tx_busy),
+ .tx_block(avr_rx_busy),
+ .rx_data(rx_data),
+ .new_rx_data(new_rx_data)
);
-
+
reg [13:0] addr_q, addr_d;
+ reg [6:0] scroll_q, scroll_d;
reg[7:0] write_data;
reg write_enable;
wire[7:0] sram_read_data;
sram #(.SIZE(8), .DEPTH(CHAR_HMAX*CHAR_VMAX)) sram(
- .clk(hdmi_clk),
- .read_address(char_index_q),
- .write_address(addr_q),
- .read_data(sram_read_data),
- .write_data(write_data),
- .write_en(write_enable)
+ .clk(hdmi_clk),
+ .read_address(char_index_q),
+ .write_address(addr_q),
+ .read_data(sram_read_data),
+ .write_data(write_data),
+ .write_en(write_enable)
);
-
+
always @(*) begin
- // @todo For some reason we need a -1 here, otherwise it looks weird with
- // SCALE = 1
- // Need to figure that out, something to do with wrap around
- charx = (hdmix >> (SCALE-1)) % 8;
- chary = (hdmiy >> (SCALE-1)) % 8;
-
- char_index_d = ((hdmix >> (SCALE+2)) + CHAR_HMAX*(hdmiy >> (SCALE+2)));
-
- if (char_index_d[6] == 1) begin
- hdmired = 8'h55 * char_index_d[1:0];
- hdmigreen = 8'h55 * char_index_d[3:2];
- hdmiblue = 8'h55 * char_index_d[5:4];
- end else begin
- hdmired = 1'b0;
- hdmigreen = 1'b0;
- hdmiblue = 1'b0;
- end
-
+ // @todo For some reason we need a -1 here, otherwise it looks weird with
+ // SCALE = 1
+ // Need to figure that out, something to do with wrap around
+ charx = (hdmix >> (SCALE-1)) % 8;
+ chary = (hdmiy >> (SCALE-1)) % 8;
+
+ char_index_d = ((hdmix >> (SCALE+2)) + CHAR_HMAX*(hdmiy >> (SCALE+2)) + CHAR_HMAX*scroll_q) % (CHAR_HMAX*CHAR_VMAX);
+
+ //char_color = char_index_d[5:0];
+ char_color = 6'b111111;
+ //char_attribute = char_index_d[6];
+ char_attribute = 1'b0;
+
+ if (char_attribute == 1) begin
+ hdmired = 8'h55 * char_color[1:0];
+ hdmigreen = 8'h55 * char_color[3:2];
+ hdmiblue = 8'h55 * char_color[5:4];
+ end else begin
+ hdmired = 1'b0;
+ hdmigreen = 1'b0;
+ hdmiblue = 1'b0;
+ end
+
if (charx > 0 && charx < 6 && chary > 0 && chary < 7 && char_data[sram_read_data][29 - (charx - 1) - 5*(chary - 1)] == 1) begin
- if (char_index_d[6] == 1) begin
- hdmired = 1'b0;
- hdmigreen = 1'b0;
- hdmiblue = 1'b0;
- end else begin
- hdmired = 8'h55 * char_index_d[1:0];
- hdmigreen = 8'h55 * char_index_d[3:2];
- hdmiblue = 8'h55 * char_index_d[5:4];
- end
+ if (char_attribute == 1) begin
+ hdmired = 1'b0;
+ hdmigreen = 1'b0;
+ hdmiblue = 1'b0;
+ end else begin
+ hdmired = 8'h55 * char_color[1:0];
+ hdmigreen = 8'h55 * char_color[3:2];
+ hdmiblue = 8'h55 * char_color[5:4];
+ end
end
frame_d = frame_q;
@@ -242,35 +256,74 @@ module mojo_top(
if (hdmix == WIDTH-1 && hdmiy == HEIGHT-1) begin
frame_d = frame_q + 1'b1;
end
-
- new_tx_data = 1'b0;
- write_enable = 1'b0;
- write_data = 1'b0;
- addr_d = addr_q;
- if (new_rx_data) begin
- new_tx_data = 1'b1;
- tx_data = rx_data;
-
- if (rx_data == "\r") begin
- end else if (rx_data == "\n") begin
- addr_d = addr_q - (addr_q % CHAR_HMAX) + CHAR_HMAX;
- end else if (rx_data == 8) begin
- addr_d = addr_q - 1'b1;
- end else begin
- write_enable = 1'b1;
- write_data = rx_data - 32;
- addr_d = addr_q + 1'b1;
- end
- end
+
+ // new_tx_data = 1'b0;
+ // write_enable = 1'b0;
+ // write_data = 1'b0;
+ // addr_d = addr_q;
+ // if (new_rx_data) begin
+ // new_tx_data = 1'b1;
+ // tx_data = rx_data;
+ //
+ // if (rx_data == "\r") begin
+ // end else if (rx_data == "\n") begin
+ // addr_d = addr_q - (addr_q % CHAR_HMAX) + CHAR_HMAX;
+ // end else if (rx_data == 8) begin
+ // addr_d = addr_q - 1'b1;
+ // end else begin
+ // write_enable = 1'b1;
+ // write_data = rx_data - 32;
+ // addr_d = addr_q + 1'b1;
+ // end
+ // end
end
+
+ reg bottom_of_screen_q, bottom_of_screen_d;
+ always @(posedge z80_clk) begin
+ write_enable = 1'b0;
+ write_data = 1'b0;
+ addr_d = addr_q;
+ scroll_d = scroll_q;
+ bottom_of_screen_d = bottom_of_screen_q;
+
+ // if (z80_ioreq != 1 && z80_m1 != 0 && z80_address[7:0] == 8'h10) begin
+ if (z80_ioreq != 1 && z80_m1 != 0 && z80_wr != 1) begin
+ if (z80_data == "\r") begin
+ addr_d = addr_q - (addr_q % CHAR_HMAX);
+ end else if (z80_data == "\n") begin
+ addr_d = addr_q + CHAR_HMAX;
+ end else begin
+ write_enable = 1'b1;
+ write_data = z80_data - 32;
+ addr_d = addr_q + 1'b1;
+ end
+
+ if (bottom_of_screen_d == 1 && addr_d >= CHAR_HMAX*scroll_q) begin
+ scroll_d = (scroll_q + 1'b1) % CHAR_VMAX;
+ end
+
+ if (addr_d >= CHAR_HMAX*CHAR_VMAX) begin
+ bottom_of_screen_d = 1'b1;
+ addr_d = addr_d - CHAR_HMAX*CHAR_VMAX;
+ end
+
+ end
+ end
+
always @(posedge hdmi_clk) begin
if (rst) begin
frame_q <= 1'b0;
char_index_q <= 1'b0;
- addr_q <= 1'b0;
+ addr_q <= 1'b0;
+ scroll_q <= 1'b0;
+ bottom_of_screen_q <= 1'b0;
end else begin
- addr_q <= addr_d;
+ if (z80_ioreq == 1) begin
+ addr_q <= addr_d;
+ scroll_q <= scroll_d;
+ bottom_of_screen_q <= bottom_of_screen_d;
+ end
frame_q <= frame_d;
char_index_q <= char_index_d;
end