This repository has been archived on 2021-01-21. You can view files and clone it, but cannot push or open issues or pull requests.
hdmi.old/source/mojo_top.v

310 lines
9.5 KiB
Verilog

module mojo_top(
// 50MHz clock input
input clk,
// Input from reset button (active low)
input rst_n,
// cclk input from AVR, high when AVR is ready
input cclk,
// Outputs to the 8 onboard LEDs
output[7:0]led,
// AVR SPI connections
output spi_miso,
input spi_ss,
input spi_mosi,
input spi_sck,
// AVR ADC channel select
output [3:0] spi_channel,
// Serial connections
input avr_tx, // AVR Tx => FPGA Rx
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,
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 hdmi_clk;
reg[7:0] hdmired, hdmigreen, hdmiblue;
wire[11:0] hdmix;
wire[10:0] hdmiy;
reg[7:0] frame_q, frame_d;
clk_wiz_v3_6 clk_wiz(
.CLK_IN1(clk),
.CLK_OUT1(hdmi_clk)
);
localparam SCALE = 2;
localparam WIDTH = 1280;
localparam HEIGHT = 720;
// localparam WIDTH = 1920;
// localparam HEIGHT = 1080;
localparam CHAR_HMAX = WIDTH / (SCALE*8);
localparam CHAR_VMAX = HEIGHT / (SCALE*8);
// @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(
.clk(hdmi_clk),
.rst(rst),
.tmds(hdmi1_tmds),
.tmdsb(hdmi1_tmdsb),
.x(hdmix),
.y(hdmiy),
.red(hdmired),
.green(hdmigreen),
.blue(hdmiblue)
);
wire [29:0] char_data [94:0];
assign char_data[0] = 30'h00000000; //
assign char_data[1] = 30'h1CE7380E; // !
assign char_data[2] = 30'h14A00000; // "
assign char_data[3] = 30'hAFABEA; // #
assign char_data[4] = 30'h8FA38BE; // $
assign char_data[5] = 30'h19D1173; // %
assign char_data[6] = 30'h1905324D; // &
assign char_data[7] = 30'h8400000; // '
assign char_data[8] = 30'hCC63186; // (
assign char_data[9] = 30'h186318CC; // )
assign char_data[10] = 30'h4ABAA4; // *
assign char_data[11] = 30'h427C84; // +
assign char_data[12] = 30'h0x8C; // ,
assign char_data[13] = 30'h3800; // -
assign char_data[14] = 30'hC; // .
assign char_data[15] = 30'hC663318; // /
assign char_data[16] = 30'h3FBDEF7F; // 0
assign char_data[17] = 30'h3C6318DF; // 1
assign char_data[18] = 30'h3E3FE31F; // 2
assign char_data[19] = 30'h3E378C7F; // 3
assign char_data[20] = 30'h37BF8C63; // 4
assign char_data[21] = 30'h3F8F8C7F; // 5
assign char_data[22] = 30'h3F8FEF7F; // 6
assign char_data[23] = 30'h3E33318C; // 7
assign char_data[24] = 30'h3FBFEF7F; // 8
assign char_data[25] = 30'h3FBF8C7F; // 9
assign char_data[26] = 30'hC00180; // :
assign char_data[27] = 30'hC00198; // ;
assign char_data[28] = 30'h666186; // <
assign char_data[29] = 30'h701C0; // =
assign char_data[30] = 30'hC30CCC; // >
assign char_data[31] = 30'h3C31B80C; // ?
assign char_data[32] = 30'h1D1BDE0F; // @
assign char_data[33] = 30'h1DBDFF7B; // A
assign char_data[34] = 30'h3DBF6F7E; // B
assign char_data[35] = 30'h1DBC636E; // C
assign char_data[36] = 30'h3DBDEF7E; // D
assign char_data[37] = 30'h1F8F630F; // E
assign char_data[38] = 30'h1F8F6318; // F
assign char_data[39] = 30'h1F8C6F6F; // G
assign char_data[40] = 30'h37BFEF7B; // H
assign char_data[41] = 30'h3CC6319E; // I
assign char_data[42] = 30'h3E6318DC; // J
assign char_data[43] = 30'h37BE6F7B; // K
assign char_data[44] = 30'h318C631F; // L
assign char_data[45] = 30'h37FFEF7B; // M
assign char_data[46] = 30'h3DBDEF7B; // N
assign char_data[47] = 30'h1DBDEF6E; // O
assign char_data[48] = 30'h3DBDFB18; // P
assign char_data[49] = 30'h1DBDEFCF; // Q
assign char_data[50] = 30'h3DBDF37B; // R
assign char_data[51] = 30'h1F870C7E; // S
assign char_data[52] = 30'h3EC6318C; // T
assign char_data[53] = 30'h37BDEF6E; // U
assign char_data[54] = 30'h37BDEDC4; // V
assign char_data[55] = 30'h37BDFFFB; // W
assign char_data[56] = 30'h37B26F7B; // X
assign char_data[57] = 30'h37BF8C7E; // Y
assign char_data[58] = 30'h3E33331F; // X
assign char_data[59] = 30'h1CC6318E; // [
assign char_data[60] = 30'h18C31863; // \
assign char_data[61] = 30'h1C6318CE; // ]
assign char_data[62] = 30'h8A00000; // ^
assign char_data[63] = 30'h1F; // _
assign char_data[64] = 30'h10400000; // `
assign char_data[65] = 30'h7EF7D; // a
assign char_data[66] = 30'h318F6F7F; // b
assign char_data[67] = 30'h7E30F; // c
assign char_data[68] = 30'h637EF6F; // d
assign char_data[69] = 30'h76F8F; // e
assign char_data[70] = 30'hEC67D8C; // f
assign char_data[71] = 30'h1FBDBC7E; // g
assign char_data[72] = 30'h318F6F7B; // h
assign char_data[73] = 30'h18063186; // i
assign char_data[74] = 30'hC6318DC; // j
assign char_data[75] = 30'h31BD735B; // k
assign char_data[76] = 30'h18C63186; // l
assign char_data[77] = 30'h57F7B; // m
assign char_data[78] = 30'hF6F7B; // n
assign char_data[79] = 30'h7EF7E; // o
assign char_data[80] = 30'h3DBDFB18; // p
assign char_data[81] = 30'h1FBDBC63; // q
assign char_data[82] = 30'h76F18; // r
assign char_data[83] = 30'h7F0FE; // s
assign char_data[84] = 30'h18CF3186; // t
assign char_data[85] = 30'hDEF6F; // u
assign char_data[86] = 30'hDED44; // v
assign char_data[87] = 30'hDEFEA; // w
assign char_data[88] = 30'hDBB7B; // x
assign char_data[89] = 30'h37BDBC6E; // y
assign char_data[90] = 30'hF999F; // z
assign char_data[91] = 30'h623086; // {
assign char_data[92] = 30'h421084; // |
assign char_data[93] = 30'h610C46; // }
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)
);
reg [13:0] addr_q, addr_d, addr_t, addr_n, addr_r;
reg[7:0] write_data_q, write_data_d;
reg write_enable, write_enable_c_q, write_enable_c_d;
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-1),
.read_data(sram_read_data),
.write_data(write_data_q),
.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));
//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_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;
if (hdmix == WIDTH-1 && hdmiy == HEIGHT-1) begin
frame_d = frame_q + 1'b1;
end
// Disable write during IO request
write_enable = z80_ioreq && write_enable_c_q;
end
always @(posedge z80_clk) begin
write_data_d = write_data_q;
write_enable_c_d = write_enable_c_q;
addr_d = addr_q;
// @todo Hook up address lines
// 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_r;
write_enable_c_d = 0;
end else if (z80_data == "\n") begin
addr_d = addr_n;
write_enable_c_d = 0;
end else begin
write_data_d = z80_data - 32;
addr_d = addr_t;
write_enable_c_d = 1;
end
end
end
// IO request starts
always @(negedge z80_ioreq) begin
addr_t = (addr_q + 1) % (CHAR_HMAX*CHAR_VMAX);
addr_n = (addr_q + CHAR_HMAX) % (CHAR_HMAX*CHAR_VMAX);
addr_r = (addr_q - (addr_q % CHAR_HMAX)) % (CHAR_HMAX*CHAR_VMAX);
end
always @(posedge hdmi_clk) begin
if (rst) begin
frame_q <= 1'b0;
char_index_q <= 1'b0;
addr_q <= 1'b0;
write_data_q <= 0;
write_enable_c_q <= 0;
end else begin
frame_q <= frame_d;
char_index_q <= char_index_d;
addr_q <= addr_d;
write_data_q <= write_data_d;
write_enable_c_q <= write_enable_c_d;
end
end
endmodule