Update sys.

This commit is contained in:
sorgelig
2021-01-19 02:24:11 +08:00
parent b596069c4a
commit 30b2edfbfb
8 changed files with 401 additions and 45 deletions

View File

@@ -52,6 +52,33 @@ module emu
output [1:0] VGA_SL,
output VGA_SCALER, // Force VGA scaler
`ifdef USE_FB
// Use framebuffer in DDRAM (USE_FB=1 in qsf)
// FB_FORMAT:
// [2:0] : 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp
// [3] : 0=16bits 565 1=16bits 1555
// [4] : 0=RGB 1=BGR (for 16/24/32 modes)
//
// FB_STRIDE either 0 (rounded to 256 bytes) or multiple of pixel size (in bytes)
output FB_EN,
output [4:0] FB_FORMAT,
output [11:0] FB_WIDTH,
output [11:0] FB_HEIGHT,
output [31:0] FB_BASE,
output [13:0] FB_STRIDE,
input FB_VBL,
input FB_LL,
output FB_FORCE_BLANK,
// Palette control for 8bit modes.
// Ignored for other video modes.
output FB_PAL_CLK,
output [7:0] FB_PAL_ADDR,
output [23:0] FB_PAL_DOUT,
input [23:0] FB_PAL_DIN,
output FB_PAL_WR,
`endif
output LED_USER, // 1 - ON, 0 - OFF.
// b[1]: 0 - LED status is system status OR'd with b[0]
@@ -81,6 +108,7 @@ module emu
output SD_CS,
input SD_CD,
`ifdef USE_DDRAM
//High latency DDR3 RAM interface
//Use for non-critical time purposes
output DDRAM_CLK,
@@ -93,7 +121,9 @@ module emu
output [63:0] DDRAM_DIN,
output [7:0] DDRAM_BE,
output DDRAM_WE,
`endif
`ifdef USE_SDRAM
//SDRAM interface with lower latency
output SDRAM_CLK,
output SDRAM_CKE,
@@ -106,6 +136,20 @@ module emu
output SDRAM_nCAS,
output SDRAM_nRAS,
output SDRAM_nWE,
`endif
`ifdef DUAL_SDRAM
//Secondary SDRAM
input SDRAM2_EN,
output SDRAM2_CLK,
output [12:0] SDRAM2_A,
output [1:0] SDRAM2_BA,
inout [15:0] SDRAM2_DQ,
output SDRAM2_nCS,
output SDRAM2_nCAS,
output SDRAM2_nRAS,
output SDRAM2_nWE,
`endif
input UART_CTS,
output UART_RTS,

View File

@@ -204,7 +204,7 @@ assign DDRAM_DIN = {ram_data,ram_data};
assign DDRAM_WE = ram_wr;
assign DDRAM_RD = 0;
assign FB_EN = ~no_rotate;
assign FB_EN = fb_en[2];
assign FB_FORMAT = 5'b00110;
assign FB_BASE = {MEM_BASE,o_fb,23'd0};
assign FB_WIDTH = vsz;
@@ -236,6 +236,11 @@ always @(posedge CLK_VIDEO) begin
end
end
initial begin
fb_en = 0;
end
reg [2:0] fb_en = 0;
reg [11:0] hsz = 320, vsz = 240;
reg [11:0] bwidth;
reg [22:0] bufsize;
@@ -257,6 +262,7 @@ always @(posedge CLK_VIDEO) begin
vsz <= vcnt;
bwidth <= vcnt + 2'd3;
vcnt <= 0;
fb_en <= {fb_en[1:0], ~no_rotate};
end
if(old_vs & ~VGA_VS) bufsize <= hsz * stride;
end

View File

@@ -111,32 +111,32 @@ wire [15:0] init_data[82] =
{8'h17, 8'b01100010}, // Aspect ratio 16:9 [1]=1, 4:3 [1]=0
{8'h18, ypbpr ? 8'h88 : limited[0] ? 8'h8D : limited[1] ? 8'h8E : 8'h00}, // CSC Scaling Factors and Coefficients for RGB Full->Limited.
{8'h19, ypbpr ? 8'h2E : limited[0] ? 8'hBC : 8'hFE}, // Taken from table in ADV7513 Programming Guide.
{8'h1A, ypbpr ? 8'h18 : 8'h00}, // CSC Channel A.
{8'h1B, ypbpr ? 8'h93 : 8'h00},
{8'h1C, ypbpr ? 8'h1F : 8'h00},
{8'h1D, ypbpr ? 8'h3F : 8'h00},
{8'h1E, ypbpr ? 8'h08 : 8'h01},
{8'h1F, 8'h00},
{8'h18, ypbpr ? 8'h86 : limited[0] ? 8'h8D : limited[1] ? 8'h8E : 8'h00}, // CSC Scaling Factors and Coefficients for RGB Full->Limited.
{8'h19, ypbpr ? 8'hDF : limited[0] ? 8'hBC : 8'hFE}, // Taken from table in ADV7513 Programming Guide.
{8'h1A, ypbpr ? 8'h1A : 8'h00}, // CSC Channel A.
{8'h1B, ypbpr ? 8'h3F : 8'h00},
{8'h1C, ypbpr ? 8'h1E : 8'h00},
{8'h1D, ypbpr ? 8'hE2 : 8'h00},
{8'h1E, ypbpr ? 8'h07 : 8'h01},
{8'h1F, ypbpr ? 8'hE7 : 8'h00},
{8'h20, ypbpr ? 8'h03 : 8'h00}, // CSC Channel B.
{8'h21, ypbpr ? 8'h67 : 8'h00},
{8'h22, ypbpr ? 8'h0B : limited[0] ? 8'h0D : 8'h0E},
{8'h23, ypbpr ? 8'h71 : limited[0] ? 8'hBC : 8'hFE},
{8'h20, ypbpr ? 8'h04 : 8'h00}, // CSC Channel B.
{8'h21, ypbpr ? 8'h1C : 8'h00},
{8'h22, ypbpr ? 8'h08 : limited[0] ? 8'h0D : 8'h0E},
{8'h23, ypbpr ? 8'h11 : limited[0] ? 8'hBC : 8'hFE},
{8'h24, ypbpr ? 8'h01 : 8'h00},
{8'h25, ypbpr ? 8'h28 : 8'h00},
{8'h26, ypbpr ? 8'h00 : 8'h01},
{8'h25, ypbpr ? 8'h91 : 8'h00},
{8'h26, ypbpr ? 8'h01 : 8'h01},
{8'h27, 8'h00},
{8'h28, ypbpr ? 8'h1E : 8'h00}, // CSC Channel C.
{8'h29, ypbpr ? 8'h21 : 8'h00},
{8'h2A, ypbpr ? 8'h19 : 8'h00},
{8'h2B, ypbpr ? 8'hB2 : 8'h00},
{8'h2C, ypbpr ? 8'h08 : limited[0] ? 8'h0D : 8'h0E},
{8'h2D, ypbpr ? 8'h2D : limited[0] ? 8'hBC : 8'hFE},
{8'h2E, ypbpr ? 8'h08 : 8'h01},
{8'h2F, 8'h00},
{8'h28, ypbpr ? 8'h1D : 8'h00}, // CSC Channel C.
{8'h29, ypbpr ? 8'hAE : 8'h00},
{8'h2A, ypbpr ? 8'h1B : 8'h00},
{8'h2B, ypbpr ? 8'h73 : 8'h00},
{8'h2C, ypbpr ? 8'h06 : limited[0] ? 8'h0D : 8'h0E},
{8'h2D, ypbpr ? 8'hDF : limited[0] ? 8'hBC : 8'hFE},
{8'h2E, ypbpr ? 8'h07 : 8'h01},
{8'h2F, ypbpr ? 8'hE7 : 8'h00},
{8'h3B, 8'b0000_0000}, // Pixel repetition [6:5] b00 AUTO. [4:3] b00 x1 mult of input clock. [2:1] b00 x1 pixel rep to send to HDMI Rx.

View File

@@ -126,7 +126,8 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0)
output reg [32:0] TIMESTAMP,
// UART flags
input [15:0] uart_mode,
output reg [7:0] uart_mode,
output reg [31:0] uart_speed,
// ps2 keyboard emulation
output ps2_kbd_clk_out,
@@ -248,6 +249,8 @@ always@(posedge clk_sys) begin : uio_block
reg old_status_set = 0;
reg old_info = 0;
reg [7:0] info_n = 0;
reg [15:0] tmp1;
reg [7:0] tmp2;
old_status_set <= status_set;
if(~old_status_set & status_set) begin
@@ -453,9 +456,6 @@ always@(posedge clk_sys) begin : uio_block
//RTC
'h24: TIMESTAMP[(byte_cnt-6'd1)<<4 +:16] <= io_din;
//UART flags
'h28: io_dout <= uart_mode;
//status set
'h29: if(!byte_cnt[MAX_W:3]) begin
case(byte_cnt[2:0])
@@ -479,6 +479,15 @@ always@(posedge clk_sys) begin : uio_block
{gamma_wr, gamma_value} <= {1'b1,io_din[7:0]};
if (byte_cnt[1:0] == 3) byte_cnt <= 1;
end
// UART
'h3b: if(!byte_cnt[MAX_W:2]) begin
case(byte_cnt[1:0])
1: tmp2 <= io_din[7:0];
2: tmp1 <= io_din;
3: {uart_speed, uart_mode} <= {io_din, tmp1, tmp2};
endcase
end
endcase
end
end

283
sys/mt32pi.sv Normal file
View File

@@ -0,0 +1,283 @@
//
// Communication module to MT32-pi (external MIDI emulator on RPi)
// (C) 2020 Sorgelig, Kitrinx
//
// https://github.com/dwhinham/mt32-pi
//
module mt32pi
(
input CLK_AUDIO,
input CLK_VIDEO,
input CE_PIXEL,
input VGA_VS,
input VGA_DE,
input [6:0] USER_IN,
output [6:0] USER_OUT,
input reset,
input midi_tx,
output midi_rx,
output reg [15:0] mt32_i2s_r,
output reg [15:0] mt32_i2s_l,
output reg mt32_available,
input mt32_mode_req,
input [1:0] mt32_rom_req,
input [7:0] mt32_sf_req,
output reg [7:0] mt32_mode,
output reg [7:0] mt32_rom,
output reg [7:0] mt32_sf,
output reg mt32_newmode,
output reg mt32_lcd_en,
output reg mt32_lcd_pix,
output reg mt32_lcd_update
);
//
// Pin | USB Name | Signal
// ----+----------+--------------
// 0 | D+ | I/O I2C_SDA / RX (midi in)
// 1 | D- | O TX (midi out)
// 2 | TX- | I I2S_WS (1 == right)
// 3 | GND_d | I I2C_SCL
// 4 | RX+ | I I2S_BCLK
// 5 | RX- | I I2S_DAT
// 6 | TX+ | - none
//
assign USER_OUT[0] = sda_out;
assign USER_OUT[1] = midi_tx;
assign USER_OUT[6:2] = '1;
//
// crossed/straight cable selection
//
generate
genvar i;
for(i = 0; i<2; i++) begin : clk_rate
wire clk_in = i ? USER_IN[6] : USER_IN[4];
reg [4:0] cnt;
always @(posedge CLK_AUDIO) begin : clkr
reg clk_sr, clk, old_clk;
reg [4:0] cnt_tmp;
clk_sr <= clk_in;
if (clk_sr == clk_in) clk <= clk_sr;
if(~&cnt_tmp) cnt_tmp <= cnt_tmp + 1'd1;
else cnt <= '1;
old_clk <= clk;
if(~old_clk & clk) begin
cnt <= cnt_tmp;
cnt_tmp <= 0;
end
end
end
reg crossed;
always @(posedge CLK_AUDIO) crossed <= (clk_rate[0].cnt <= clk_rate[1].cnt);
endgenerate
wire i2s_ws = crossed ? USER_IN[2] : USER_IN[5];
wire i2s_data = crossed ? USER_IN[5] : USER_IN[2];
wire i2s_bclk = crossed ? USER_IN[4] : USER_IN[6];
assign midi_rx = ~mt32_available ? USER_IN[0] : crossed ? USER_IN[6] : USER_IN[4];
//
// i2s receiver
//
always @(posedge CLK_AUDIO) begin : i2s_proc
reg [15:0] i2s_buf = 0;
reg [4:0] i2s_cnt = 0;
reg clk_sr;
reg i2s_clk = 0;
reg old_clk, old_ws;
reg i2s_next = 0;
// Debounce clock
clk_sr <= i2s_bclk;
if (clk_sr == i2s_bclk) i2s_clk <= clk_sr;
// Latch data and ws on rising edge
old_clk <= i2s_clk;
if (i2s_clk && ~old_clk) begin
if (~i2s_cnt[4]) begin
i2s_cnt <= i2s_cnt + 1'd1;
i2s_buf[~i2s_cnt[3:0]] <= i2s_data;
end
// Word Select will change 1 clock before the new word starts
old_ws <= i2s_ws;
if (old_ws != i2s_ws) i2s_next <= 1;
end
if (i2s_next) begin
i2s_next <= 0;
i2s_cnt <= 0;
i2s_buf <= 0;
if (i2s_ws) mt32_i2s_l <= i2s_buf;
else mt32_i2s_r <= i2s_buf;
end
if (reset) begin
i2s_buf <= 0;
mt32_i2s_l <= 0;
mt32_i2s_r <= 0;
end
end
//
// i2c slave
//
reg sda_out;
reg [7:0] lcd_data[1024];
reg lcd_sz;
reg reset_r = 0;
wire [7:0] mode_req = reset_r ? 8'hA0 : mt32_mode_req ? 8'hA2 : 8'hA1;
wire [7:0] rom_req = {6'd0, mt32_rom_req};
always @(posedge CLK_AUDIO) begin : i2c_slave
reg sda_sr, scl_sr;
reg old_sda, old_scl;
reg sda, scl;
reg [7:0] tmp;
reg [3:0] cnt = 0;
reg [10:0] bcnt = 0;
reg ack;
reg i2c_rw;
reg disp, dispdata;
reg [2:0] div;
reg old_reset;
old_reset <= reset;
if(old_reset & ~reset) sda_out <= 1;
div <= div + 1'd1;
if(!div) begin
sda_sr <= USER_IN[0];
if(sda_sr == USER_IN[0]) sda <= sda_sr;
old_sda <= sda;
scl_sr <= USER_IN[3];
if(scl_sr == USER_IN[3]) scl <= scl_sr;
old_scl <= scl;
//start
if(old_scl & scl & old_sda & ~sda) begin
cnt <= 9;
bcnt <= 0;
ack <= 0;
i2c_rw <= 0;
disp <= 0;
dispdata <= 0;
end
//stop
if(old_scl & scl & ~old_sda & sda) begin
cnt <= 0;
if(dispdata) begin
lcd_sz <= ~bcnt[9];
mt32_lcd_update <= ~mt32_lcd_update;
end
end
//data latch
if(~old_scl && scl && cnt) begin
tmp <= {tmp[6:0], sda};
cnt <= cnt - 1'd1;
end
if(!cnt) sda_out <= 1;
//data set
if(old_scl && ~scl) begin
sda_out <= 1;
if(cnt == 1) begin
if(!bcnt) begin
if(tmp[7:1] == 'h45 || tmp[7:1] == 'h3c) begin
disp <= (tmp[7:1] == 'h3c);
sda_out <= 0;
mt32_available <= 1;
ack <= 1;
i2c_rw <= tmp[0];
bcnt <= bcnt + 1'd1;
cnt <= 10;
end
else begin
// wrong address, stop
cnt <= 0;
end
end
else if(ack) begin
if(~i2c_rw) begin
if(disp) begin
if(bcnt == 1) dispdata <= (tmp[7:6] == 2'b01);
else if(dispdata) lcd_data[bcnt[9:0] - 2'd2] <= tmp;
end
else begin
if(bcnt == 1) mt32_mode <= tmp;
if(bcnt == 2) mt32_rom <= tmp;
if(bcnt == 3) mt32_sf <= tmp;
if(bcnt == 3) mt32_newmode <= ~mt32_newmode;
end
end
if(~&bcnt) bcnt <= bcnt + 1'd1;
sda_out <= 0;
cnt <= 10;
end
end
else if(i2c_rw && ack && cnt && ~disp) begin
if(bcnt == 1) sda_out <= mode_req[cnt[2:0] - 2'd2];
if(bcnt == 2) sda_out <= rom_req[cnt[2:0] - 2'd2];
if(bcnt == 3) sda_out <= mt32_sf_req[cnt[2:0] - 2'd2];
if(bcnt == 3) reset_r <= 0;
end
end
end
if(reset) begin
reset_r <= 1;
mt32_available <= 0;
end
end
always @(posedge CLK_VIDEO) begin
reg old_de, old_vs;
reg [7:0] hcnt;
reg [6:0] vcnt;
reg [7:0] sh;
if(CE_PIXEL) begin
old_de <= VGA_DE;
old_vs <= VGA_VS;
if(~&hcnt) hcnt <= hcnt + 1'd1;
sh <= (sh << 1) | (~old_de & VGA_DE);
if(sh[7]) hcnt <= 0;
if(old_de & ~VGA_DE & ~&vcnt) vcnt <= vcnt + 1'd1;
if(~old_vs & VGA_VS) vcnt <= 0;
mt32_lcd_en <= mt32_available & ~hcnt[7] && (lcd_sz ? !vcnt[6] : !vcnt[6:5]);
mt32_lcd_pix <= lcd_data[{vcnt[5:3],hcnt[6:0]}][vcnt[2:0]];
end
end
endmodule

View File

@@ -67,6 +67,8 @@ reg spdif_out_q;
reg [5:0] parity_count_q;
reg channel_status_bit;
//-----------------------------------------------------------------
// Subframe Counter
//-----------------------------------------------------------------
@@ -142,7 +144,7 @@ assign subframe_w[28] = 1'b0; // Valid
assign subframe_w[29] = 1'b0;
// Timeslots 30 = Channel status bit
assign subframe_w[30] = 1'b0;
assign subframe_w[30] = channel_status_bit ; //was constant 1'b0 enabling copy-bit;
// Timeslots 31 = Even Parity bit (31:4)
assign subframe_w[31] = 1'b0;
@@ -150,9 +152,9 @@ assign subframe_w[31] = 1'b0;
//-----------------------------------------------------------------
// Preamble
//-----------------------------------------------------------------
localparam PREAMBLE_Z = 8'b00010111;
localparam PREAMBLE_Y = 8'b00100111;
localparam PREAMBLE_X = 8'b01000111;
localparam PREAMBLE_Z = 8'b00010111; // "B" channel A data at start of block
localparam PREAMBLE_Y = 8'b00100111; // "W" channel B data
localparam PREAMBLE_X = 8'b01000111; // "M" channel A data not at start of block
reg [7:0] preamble_r;
@@ -168,6 +170,15 @@ begin
// Left Channel (but not start of block)?
else
preamble_r = PREAMBLE_X; // X(M)
if (subframe_count_q[8:1] == 8'd2) // frame 2 => subframes 4 and 5 => 0 = copy inhibited, 1 = copy permitted
channel_status_bit = 1'b1;
else if (subframe_count_q[8:1] == 8'd15) // frame 15 => 0 = no indication, 1 = original media
channel_status_bit = 1'b1;
else if (subframe_count_q[8:1] == 8'd25) // frame 24 to 27 => sample frequency, 0100 = 48kHz, 0000 = 44kHz (l2r)
channel_status_bit = 1'b1;
else
channel_status_bit = 1'b0; // everything else defaults to 0
end
always @ (posedge rst_i or posedge clk_i )

View File

@@ -20,6 +20,7 @@ set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) a
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) iir_filter.v ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ltc2308.sv ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sigma_delta_dac.v ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) mt32pi.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hdmi_config.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) mcp23009.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ddr_svc.sv ]

View File

@@ -21,29 +21,30 @@ set_clock_groups -exclusive \
set_false_path -from [get_ports {KEY*}]
set_false_path -from [get_ports {BTN_*}]
set_false_path -to [get_ports {LED_*}]
set_false_path -to [get_ports {VGA_*}]
set_false_path -to [get_ports {AUDIO_SPDIF}]
set_false_path -to [get_ports {AUDIO_L}]
set_false_path -to [get_ports {AUDIO_R}]
set_false_path -to {cfg[*]}
set_false_path -to [get_ports {LED_*}]
set_false_path -to [get_ports {VGA_*}]
set_false_path -to [get_ports {AUDIO_SPDIF}]
set_false_path -to [get_ports {AUDIO_L}]
set_false_path -to [get_ports {AUDIO_R}]
set_false_path -to {cfg[*]}
set_false_path -from {cfg[*]}
set_false_path -from {VSET[*]}
set_false_path -to {wcalc[*] hcalc[*]}
set_false_path -to {width[*] height[*]}
set_false_path -to {wcalc[*] hcalc[*]}
set_false_path -to {width[*] height[*]}
set_multicycle_path -to {*_osd|osd_vcnt*} -setup 2
set_multicycle_path -to {*_osd|osd_vcnt*} -hold 1
set_false_path -to {*_osd|v_cnt*}
set_false_path -to {*_osd|v_osd_start*}
set_false_path -to {*_osd|v_info_start*}
set_false_path -to {*_osd|h_osd_start*}
set_false_path -to {*_osd|v_cnt*}
set_false_path -to {*_osd|v_osd_start*}
set_false_path -to {*_osd|v_info_start*}
set_false_path -to {*_osd|h_osd_start*}
set_false_path -from {*_osd|v_osd_start*}
set_false_path -from {*_osd|v_info_start*}
set_false_path -from {*_osd|h_osd_start*}
set_false_path -from {*_osd|rot*}
set_false_path -from {*_osd|dsp_width*}
set_false_path -to {*_osd|half}
set_false_path -to {*_osd|half}
set_false_path -to {WIDTH[*] HFP[*] HS[*] HBP[*] HEIGHT[*] VFP[*] VS[*] VBP[*]}
set_false_path -from {WIDTH[*] HFP[*] HS[*] HBP[*] HEIGHT[*] VFP[*] VS[*] VBP[*]}
@@ -51,7 +52,8 @@ set_false_path -to {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*]
set_false_path -from {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*] LFB_HMAX[*] LFB_VMIN[*] LFB_VMAX[*]}
set_false_path -to {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]}
set_false_path -from {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]}
set_false_path -from {aflt_* acx* acy* areset*}
set_false_path -from {aflt_* acx* acy* areset* arc*}
set_false_path -from {vs_line*}
set_false_path -from {ascal|o_ihsize*}
set_false_path -from {ascal|o_ivsize*}