Implemented scrolling when text reaches bottom of screen
This commit is contained in:
parent
c1f88398e1
commit
bd9a0f03d8
3
HDMI.alp
3
HDMI.alp
|
@ -17,7 +17,8 @@
|
||||||
<component>cclk_detector.luc</component>
|
<component>cclk_detector.luc</component>
|
||||||
<component>tmds_encoder.luc</component>
|
<component>tmds_encoder.luc</component>
|
||||||
<constraint lib="true">mojo.ucf</constraint>
|
<constraint lib="true">mojo.ucf</constraint>
|
||||||
<constraint lib="true">hdmi.ucf</constraint>
|
<constraint>hdmi2.ucf</constraint>
|
||||||
|
<constraint>z80.ucf</constraint>
|
||||||
<core name="clk_wiz_v3_6">
|
<core name="clk_wiz_v3_6">
|
||||||
<src>..\clk_wiz_v3_6.v</src>
|
<src>..\clk_wiz_v3_6.v</src>
|
||||||
</core>
|
</core>
|
||||||
|
|
8
constraint/hdmi2.ucf
Normal file
8
constraint/hdmi2.ucf
Normal file
|
@ -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 ;
|
20
constraint/z80.ucf
Normal file
20
constraint/z80.ucf
Normal file
|
@ -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;
|
|
@ -19,8 +19,14 @@ module mojo_top(
|
||||||
output avr_rx, // AVR Rx => FPGA Tx
|
output avr_rx, // AVR Rx => FPGA Tx
|
||||||
input avr_rx_busy, // AVR Rx buffer full
|
input avr_rx_busy, // AVR Rx buffer full
|
||||||
output[3:0] hdmi1_tmds,
|
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
|
wire rst = ~rst_n; // make reset active high
|
||||||
|
|
||||||
|
@ -47,7 +53,7 @@ module mojo_top(
|
||||||
|
|
||||||
// @todo 1080p30 does not work for some reason (already extended number of bits)
|
// @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+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),
|
.clk(hdmi_clk),
|
||||||
.rst(rst),
|
.rst(rst),
|
||||||
.tmds(hdmi1_tmds),
|
.tmds(hdmi1_tmds),
|
||||||
|
@ -167,74 +173,82 @@ module mojo_top(
|
||||||
wire tx_busy;
|
wire tx_busy;
|
||||||
wire[7:0] rx_data;
|
wire[7:0] rx_data;
|
||||||
wire new_rx_data;
|
wire new_rx_data;
|
||||||
|
reg[5:0] char_color;
|
||||||
|
reg char_attribute;
|
||||||
|
|
||||||
assign led[7:0] = rx_data;
|
assign led[7:0] = rx_data;
|
||||||
|
|
||||||
avr_interface #(.CLK_FREQ(75000000)) vr_interface (
|
avr_interface #(.CLK_FREQ(75000000)) vr_interface (
|
||||||
.clk(hdmi_clk),
|
.clk(hdmi_clk),
|
||||||
.rst(rst),
|
.rst(rst),
|
||||||
.cclk(cclk),
|
.cclk(cclk),
|
||||||
.spi_miso(spi_miso),
|
.spi_miso(spi_miso),
|
||||||
.spi_mosi(spi_mose),
|
.spi_mosi(spi_mose),
|
||||||
.spi_sck(spi_sck),
|
.spi_sck(spi_sck),
|
||||||
.spi_ss(spi_ss),
|
.spi_ss(spi_ss),
|
||||||
.spi_channel(spi_channel),
|
.spi_channel(spi_channel),
|
||||||
.tx(avr_rx),
|
.tx(avr_rx),
|
||||||
.rx(avr_tx),
|
.rx(avr_tx),
|
||||||
.channel(4'd15),
|
.channel(4'd15),
|
||||||
.new_sample(),
|
.new_sample(),
|
||||||
.sample(),
|
.sample(),
|
||||||
.sample_channel(),
|
.sample_channel(),
|
||||||
.tx_data(tx_data),
|
.tx_data(tx_data),
|
||||||
.new_tx_data(new_tx_data),
|
.new_tx_data(new_tx_data),
|
||||||
.tx_busy(tx_busy),
|
.tx_busy(tx_busy),
|
||||||
.tx_block(avr_rx_busy),
|
.tx_block(avr_rx_busy),
|
||||||
.rx_data(rx_data),
|
.rx_data(rx_data),
|
||||||
.new_rx_data(new_rx_data)
|
.new_rx_data(new_rx_data)
|
||||||
);
|
);
|
||||||
|
|
||||||
reg [13:0] addr_q, addr_d;
|
reg [13:0] addr_q, addr_d;
|
||||||
|
reg [6:0] scroll_q, scroll_d;
|
||||||
reg[7:0] write_data;
|
reg[7:0] write_data;
|
||||||
reg write_enable;
|
reg write_enable;
|
||||||
wire[7:0] sram_read_data;
|
wire[7:0] sram_read_data;
|
||||||
sram #(.SIZE(8), .DEPTH(CHAR_HMAX*CHAR_VMAX)) sram(
|
sram #(.SIZE(8), .DEPTH(CHAR_HMAX*CHAR_VMAX)) sram(
|
||||||
.clk(hdmi_clk),
|
.clk(hdmi_clk),
|
||||||
.read_address(char_index_q),
|
.read_address(char_index_q),
|
||||||
.write_address(addr_q),
|
.write_address(addr_q),
|
||||||
.read_data(sram_read_data),
|
.read_data(sram_read_data),
|
||||||
.write_data(write_data),
|
.write_data(write_data),
|
||||||
.write_en(write_enable)
|
.write_en(write_enable)
|
||||||
);
|
);
|
||||||
|
|
||||||
always @(*) begin
|
always @(*) begin
|
||||||
// @todo For some reason we need a -1 here, otherwise it looks weird with
|
// @todo For some reason we need a -1 here, otherwise it looks weird with
|
||||||
// SCALE = 1
|
// SCALE = 1
|
||||||
// Need to figure that out, something to do with wrap around
|
// Need to figure that out, something to do with wrap around
|
||||||
charx = (hdmix >> (SCALE-1)) % 8;
|
charx = (hdmix >> (SCALE-1)) % 8;
|
||||||
chary = (hdmiy >> (SCALE-1)) % 8;
|
chary = (hdmiy >> (SCALE-1)) % 8;
|
||||||
|
|
||||||
char_index_d = ((hdmix >> (SCALE+2)) + CHAR_HMAX*(hdmiy >> (SCALE+2)));
|
char_index_d = ((hdmix >> (SCALE+2)) + CHAR_HMAX*(hdmiy >> (SCALE+2)) + CHAR_HMAX*scroll_q) % (CHAR_HMAX*CHAR_VMAX);
|
||||||
|
|
||||||
if (char_index_d[6] == 1) begin
|
//char_color = char_index_d[5:0];
|
||||||
hdmired = 8'h55 * char_index_d[1:0];
|
char_color = 6'b111111;
|
||||||
hdmigreen = 8'h55 * char_index_d[3:2];
|
//char_attribute = char_index_d[6];
|
||||||
hdmiblue = 8'h55 * char_index_d[5:4];
|
char_attribute = 1'b0;
|
||||||
end else begin
|
|
||||||
hdmired = 1'b0;
|
if (char_attribute == 1) begin
|
||||||
hdmigreen = 1'b0;
|
hdmired = 8'h55 * char_color[1:0];
|
||||||
hdmiblue = 1'b0;
|
hdmigreen = 8'h55 * char_color[3:2];
|
||||||
end
|
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 (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
|
if (char_attribute == 1) begin
|
||||||
hdmired = 1'b0;
|
hdmired = 1'b0;
|
||||||
hdmigreen = 1'b0;
|
hdmigreen = 1'b0;
|
||||||
hdmiblue = 1'b0;
|
hdmiblue = 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
hdmired = 8'h55 * char_index_d[1:0];
|
hdmired = 8'h55 * char_color[1:0];
|
||||||
hdmigreen = 8'h55 * char_index_d[3:2];
|
hdmigreen = 8'h55 * char_color[3:2];
|
||||||
hdmiblue = 8'h55 * char_index_d[5:4];
|
hdmiblue = 8'h55 * char_color[5:4];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
frame_d = frame_q;
|
frame_d = frame_q;
|
||||||
|
@ -243,34 +257,73 @@ module mojo_top(
|
||||||
frame_d = frame_q + 1'b1;
|
frame_d = frame_q + 1'b1;
|
||||||
end
|
end
|
||||||
|
|
||||||
new_tx_data = 1'b0;
|
// new_tx_data = 1'b0;
|
||||||
write_enable = 1'b0;
|
// write_enable = 1'b0;
|
||||||
write_data = 1'b0;
|
// write_data = 1'b0;
|
||||||
addr_d = addr_q;
|
// addr_d = addr_q;
|
||||||
if (new_rx_data) begin
|
// if (new_rx_data) begin
|
||||||
new_tx_data = 1'b1;
|
// new_tx_data = 1'b1;
|
||||||
tx_data = rx_data;
|
// 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
|
||||||
|
|
||||||
if (rx_data == "\r") begin
|
reg bottom_of_screen_q, bottom_of_screen_d;
|
||||||
end else if (rx_data == "\n") begin
|
|
||||||
addr_d = addr_q - (addr_q % CHAR_HMAX) + CHAR_HMAX;
|
always @(posedge z80_clk) begin
|
||||||
end else if (rx_data == 8) begin
|
write_enable = 1'b0;
|
||||||
addr_d = addr_q - 1'b1;
|
write_data = 1'b0;
|
||||||
end else begin
|
addr_d = addr_q;
|
||||||
write_enable = 1'b1;
|
scroll_d = scroll_q;
|
||||||
write_data = rx_data - 32;
|
bottom_of_screen_d = bottom_of_screen_q;
|
||||||
addr_d = addr_q + 1'b1;
|
|
||||||
end
|
// if (z80_ioreq != 1 && z80_m1 != 0 && z80_address[7:0] == 8'h10) begin
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
always @(posedge hdmi_clk) begin
|
always @(posedge hdmi_clk) begin
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
frame_q <= 1'b0;
|
frame_q <= 1'b0;
|
||||||
char_index_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
|
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;
|
frame_q <= frame_d;
|
||||||
char_index_q <= char_index_d;
|
char_index_q <= char_index_d;
|
||||||
end
|
end
|
||||||
|
|
Reference in New Issue
Block a user