mirror of
https://github.com/array-in-a-matrix/SAROO.git
synced 2025-04-02 10:31:43 -04:00
666 lines
17 KiB
Verilog
666 lines
17 KiB
Verilog
|
|
///////////////////////////////////////////////////////
|
|
// Module: SEGA Saturn Master Flash Card //
|
|
///////////////////////////////////////////////////////
|
|
|
|
// version 0.1: first step.
|
|
// 0.2: for HW1.2
|
|
|
|
module SSMaster(
|
|
// System
|
|
CLK_50M,
|
|
// SDRAM
|
|
SD_CKE, SD_CLK, SD_CS, SD_WE, SD_CAS, SD_RAS, SD_ADDR, SD_BA, SD_DQM, SD_DQ,
|
|
// PSRAM
|
|
PSRAM_CS,
|
|
|
|
// SS system
|
|
SS_MCLK, SS_RST,
|
|
// SS I2S output
|
|
SS_SCLK, SS_SSEL, SS_BCK, SS_LRCK, SS_SD,
|
|
// SS ABUS
|
|
SS_FC0, SS_FC1, SS_TIM0, SS_TIM1, SS_TIM2, SS_AAS,
|
|
SS_ADDR, SS_DATA, SS_CS0, SS_CS1, SS_CS2, SS_RD, SS_WR0, SS_WR1, SS_WAIT, SS_IRQ,
|
|
SS_DATA_OE, SS_DATA_DIR, SS_OUTEN,
|
|
|
|
// STM32 FSMC
|
|
ST_CLK, ST_AD, ST_ADDR, ST_CS, ST_RD, ST_WR, ST_BL0, ST_BL1, ST_ALE, ST_WAIT,
|
|
// STM32 GPIO
|
|
ST_GPIO0, ST_GPIO2, ST_GPIO3,
|
|
// STM32 I2S
|
|
ST_MCLK, ST_BCK, ST_LRCK, ST_SDO,
|
|
|
|
// DEBUG LED
|
|
LED0, LED1
|
|
);
|
|
|
|
///////////////////////////////////////////////////////
|
|
// Pins //
|
|
///////////////////////////////////////////////////////
|
|
|
|
// System
|
|
input CLK_50M;
|
|
|
|
// SDRAM
|
|
output SD_CKE;
|
|
output SD_CLK;
|
|
output SD_CS;
|
|
output SD_WE;
|
|
output SD_CAS;
|
|
output SD_RAS;
|
|
output[12:0] SD_ADDR;
|
|
output[ 1:0] SD_BA;
|
|
output[ 1:0] SD_DQM;
|
|
inout[15:0] SD_DQ;
|
|
|
|
// PSRAM
|
|
input PSRAM_CS;
|
|
|
|
// SS System
|
|
input SS_MCLK;
|
|
input SS_RST;
|
|
|
|
// SS I2S
|
|
input SS_SCLK;
|
|
output SS_SSEL;
|
|
output SS_BCK;
|
|
output SS_LRCK;
|
|
output SS_SD;
|
|
|
|
// SS ABUS
|
|
input SS_FC0;
|
|
input SS_FC1;
|
|
input SS_TIM0;
|
|
input SS_TIM1;
|
|
input SS_TIM2;
|
|
input SS_AAS;
|
|
input[23:0] SS_ADDR;
|
|
inout[15:0] SS_DATA;
|
|
input SS_CS0;
|
|
input SS_CS1;
|
|
input SS_CS2;
|
|
input SS_RD;
|
|
input SS_WR0;
|
|
input SS_WR1;
|
|
output SS_WAIT;
|
|
output SS_IRQ;
|
|
output SS_DATA_OE;
|
|
output SS_DATA_DIR;
|
|
output SS_OUTEN;
|
|
|
|
// STM32 FSMC
|
|
input ST_CLK;
|
|
inout[15:0] ST_AD;
|
|
input[ 7:0] ST_ADDR;
|
|
input ST_CS;
|
|
input ST_RD;
|
|
input ST_WR;
|
|
input ST_BL0;
|
|
input ST_BL1;
|
|
input ST_ALE;
|
|
output ST_WAIT;
|
|
|
|
// STM32 GPIO
|
|
input ST_GPIO0;
|
|
output ST_GPIO2;
|
|
input ST_GPIO3;
|
|
|
|
// STM32 I2S
|
|
input ST_MCLK;
|
|
input ST_BCK;
|
|
input ST_LRCK;
|
|
input ST_SDO;
|
|
|
|
// DEBUG LED
|
|
output LED0;
|
|
output LED1;
|
|
|
|
///////////////////////////////////////////////////////
|
|
// Debug LED //
|
|
///////////////////////////////////////////////////////
|
|
|
|
assign LED0 = 1'b0;
|
|
assign LED1 = ss_reg_ctrl[8];
|
|
|
|
wire NRESET = ST_GPIO0;
|
|
assign ST_GPIO2 = ST_IRQ;
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
// I2S //
|
|
///////////////////////////////////////////////////////
|
|
|
|
//assign ST_MCLK = SS_SCLK;
|
|
assign SS_BCK = ST_BCK;
|
|
assign SS_LRCK = ST_LRCK;
|
|
assign SS_SD = ST_SDO;
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
// PLL: 50M -> 100M //
|
|
///////////////////////////////////////////////////////
|
|
|
|
|
|
wire mclk;
|
|
wire sdclk;
|
|
wire pll_locked;
|
|
mainpll _mpll(CLK_50M, mclk, sdclk, pll_locked);
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
// STM32 FSMC //
|
|
///////////////////////////////////////////////////////
|
|
|
|
// fsmc address latch
|
|
reg[24:0] fsmc_addr;
|
|
reg fsmc_cs;
|
|
|
|
always @(posedge ST_ALE)
|
|
begin
|
|
fsmc_addr <= {ST_ADDR, ST_AD, 1'b0};
|
|
end
|
|
|
|
always @(posedge ST_CS or posedge ST_ALE)
|
|
begin
|
|
if(ST_CS==1)
|
|
fsmc_cs <= 1;
|
|
else
|
|
fsmc_cs <= 0;
|
|
end
|
|
|
|
// fsmc read/write sync
|
|
reg ale_set, ale_ack;
|
|
always @(posedge ale_ack or posedge ST_ALE)
|
|
begin
|
|
if(ale_ack==1)
|
|
ale_set <= 0;
|
|
else
|
|
ale_set <= 1;
|
|
end
|
|
|
|
reg st_wr_start;
|
|
always @(posedge mclk)
|
|
begin
|
|
ale_ack <= ale_set;
|
|
st_wr_start <= (ale_ack==1 && ST_WR==0);
|
|
end
|
|
wire st_rd_start = (ale_ack==1 && ST_WR==1);
|
|
//wire st_wr_start = (ale_ack==1 && ST_WR==0);
|
|
|
|
///////////////////////////////////////////////////////
|
|
// STM32 CS timeout debug //
|
|
///////////////////////////////////////////////////////
|
|
|
|
(* noprune *)reg[8:0] stcs_cnt;
|
|
always @(posedge mclk)
|
|
begin
|
|
if(ST_CS==1) begin
|
|
stcs_cnt <= 0;
|
|
end else begin
|
|
stcs_cnt <= stcs_cnt + 1'b1;
|
|
end
|
|
end
|
|
|
|
///////////////////////////////////////////////////////
|
|
// STM32 FPGA control register //
|
|
///////////////////////////////////////////////////////
|
|
|
|
reg[15:0] st_reg_ctrl;
|
|
reg[15:0] ss_resp1;
|
|
reg[15:0] ss_resp2;
|
|
reg[15:0] ss_resp3;
|
|
reg[15:0] ss_resp4;
|
|
|
|
wire st_fifo_reset = st_reg_ctrl[8];
|
|
wire st_fifo_write = (st_wr_start==1 && fsmc_addr[24]==0 && fsmc_addr[7:0]==8'h08);
|
|
|
|
always @(negedge NRESET or posedge mclk)
|
|
begin
|
|
if(NRESET==0) begin
|
|
st_reg_ctrl <= 0;
|
|
end else if(st_wr_start==1) begin
|
|
if(fsmc_addr[24]==0 && fsmc_addr[7:0]==8'h04) st_reg_ctrl <= ST_AD;
|
|
if(fsmc_addr[24]==0 && fsmc_addr[7:0]==8'h20) ss_resp1 <= ST_AD;
|
|
if(fsmc_addr[24]==0 && fsmc_addr[7:0]==8'h22) ss_resp2 <= ST_AD;
|
|
if(fsmc_addr[24]==0 && fsmc_addr[7:0]==8'h24) ss_resp3 <= ST_AD;
|
|
if(fsmc_addr[24]==0 && fsmc_addr[7:0]==8'h26) ss_resp4 <= ST_AD;
|
|
end
|
|
end
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
// Saturn to STM32: HIRQ register //
|
|
///////////////////////////////////////////////////////
|
|
|
|
reg[15:0] ss_hirq;
|
|
|
|
|
|
always @(negedge NRESET or posedge mclk)
|
|
begin
|
|
if(NRESET==0) begin
|
|
ss_hirq <= 0;
|
|
end else begin
|
|
if( st_wr_start==1 && fsmc_addr[24]==0 && fsmc_addr[7:0]==8'h28)
|
|
// STM32 set
|
|
ss_hirq <= ss_hirq|ST_AD;
|
|
else if(st_wr_start==1 && fsmc_addr[24]==0 && fsmc_addr[7:0]==8'h2c)
|
|
// STM32 reset
|
|
ss_hirq <= ss_hirq&(~ST_AD);
|
|
else if(ss_wr_start==1 && ss_cdc_cs==1 && SS_ADDR[5:2]==4'b00_10)
|
|
// Saturn reset
|
|
ss_hirq <= ss_hirq&SS_DATA;
|
|
// else if(ss_wr_start==1 && ss_cdc_cs==1 && SS_ADDR[5:2]==4'b10_01 && ss_cr1==0)
|
|
// // Saturn write CR4
|
|
// // Auto ack getStatus command
|
|
// ss_hirq <= ss_hirq|16'b1;
|
|
end
|
|
end
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
// Saturn to STM32: CDC request //
|
|
///////////////////////////////////////////////////////
|
|
|
|
reg st_irq_cdc;
|
|
|
|
always @(negedge NRESET or posedge mclk)
|
|
begin
|
|
if(NRESET==0) begin
|
|
st_irq_cdc <= 1'b0;
|
|
end else begin
|
|
if(ss_wr_start==1 && ss_cdc_cs==1 && SS_ADDR[5:2]==4'b10_01)// && ss_cr1!=0)
|
|
// SS write CR4 and not getStatus command
|
|
st_irq_cdc <= 1'b1;
|
|
else if(st_wr_start==1 && fsmc_addr[24]==0 && fsmc_addr[7:0]==8'h06)
|
|
st_irq_cdc <= st_irq_cdc&(~ST_AD[0]);
|
|
end
|
|
end
|
|
|
|
///////////////////////////////////////////////////////
|
|
// Saturn to STM32: CMD request //
|
|
///////////////////////////////////////////////////////
|
|
|
|
reg st_irq_cmd;
|
|
|
|
always @(negedge NRESET or posedge mclk)
|
|
begin
|
|
if(NRESET==0) begin
|
|
st_irq_cmd <= 1'b0;
|
|
end else begin
|
|
if(ss_wr_start==1 && ss_reg_cs==1 && SS_ADDR[5:2]==4'b01_00)
|
|
st_irq_cmd <= 1'b1;
|
|
else if(st_wr_start==1 && fsmc_addr[24]==0 && fsmc_addr[7:0]==8'h06)
|
|
st_irq_cmd <= st_irq_cmd&(~ST_AD[1]);
|
|
end
|
|
end
|
|
|
|
///////////////////////////////////////////////////////
|
|
// CDC FIFO dma end //
|
|
///////////////////////////////////////////////////////
|
|
|
|
reg st_irq_fifo;
|
|
reg[2:0] fifo_usedw_d;
|
|
reg fifo_empty_d;
|
|
|
|
always @(posedge mclk)
|
|
begin
|
|
fifo_usedw_d <= fifo_usedw[10:8];
|
|
fifo_empty_d <= fifo_empty;
|
|
end
|
|
|
|
always @(negedge NRESET or posedge mclk)
|
|
begin
|
|
if(NRESET==0) begin
|
|
st_irq_fifo <= 1'b0;
|
|
end else begin
|
|
if((fifo_usedw_d==3'b001 && fifo_usedw[10:8]==3'b000) || (fifo_empty_d==0 && fifo_empty==1))
|
|
// 256->255 or empty
|
|
st_irq_fifo <= 1'b1;
|
|
else if(st_wr_start==1 && fsmc_addr[24]==0 && fsmc_addr[7:0]==8'h06)
|
|
st_irq_fifo <= st_irq_fifo&(~ST_AD[2]);
|
|
end
|
|
end
|
|
|
|
///////////////////////////////////////////////////////
|
|
// Saturn ss_in_cmd //
|
|
///////////////////////////////////////////////////////
|
|
|
|
reg ss_in_cmd;
|
|
|
|
always @(negedge NRESET or posedge mclk)
|
|
begin
|
|
if(NRESET==0) begin
|
|
ss_in_cmd <= 1'b0;
|
|
end else begin
|
|
if(ss_rd_start==1 && ss_cdc_cs==1 && SS_ADDR[5:2]==4'b10_01)
|
|
// Read CR4
|
|
ss_in_cmd <= 1'b0;
|
|
else if(ss_wr_start==1 && ss_cdc_cs==1 && SS_ADDR[5:2]==4'b10_01)
|
|
// Write CR4
|
|
ss_in_cmd <= 1'b1;
|
|
end
|
|
end
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
// STM32 read data //
|
|
///////////////////////////////////////////////////////
|
|
|
|
reg[15:0] st_reg_data_out;
|
|
|
|
always @(posedge mclk)
|
|
begin
|
|
st_reg_data_out <=
|
|
(fsmc_addr[7:0]==8'h00)? 16'h5253 : // ID: "SR"
|
|
(fsmc_addr[7:0]==8'h02)? 16'h1102 : // ver: HW1.1 && SW0.2
|
|
(fsmc_addr[7:0]==8'h04)? st_reg_ctrl :
|
|
(fsmc_addr[7:0]==8'h06)? st_reg_stat :
|
|
(fsmc_addr[7:0]==8'h0c)? st_fifo_stat :
|
|
(fsmc_addr[7:0]==8'h10)? ss_reg_cmd :
|
|
(fsmc_addr[7:0]==8'h12)? ss_reg_data :
|
|
(fsmc_addr[7:0]==8'h14)? ss_reg_ctrl :
|
|
|
|
(fsmc_addr[7:0]==8'h18)? ss_resp1 :
|
|
(fsmc_addr[7:0]==8'h1a)? ss_resp2 :
|
|
(fsmc_addr[7:0]==8'h1c)? ss_resp3 :
|
|
(fsmc_addr[7:0]==8'h1e)? ss_resp4 :
|
|
|
|
(fsmc_addr[7:0]==8'h20)? ss_cr1 :
|
|
(fsmc_addr[7:0]==8'h22)? ss_cr2 :
|
|
(fsmc_addr[7:0]==8'h24)? ss_cr3 :
|
|
(fsmc_addr[7:0]==8'h26)? ss_cr4 :
|
|
(fsmc_addr[7:0]==8'h28)? ss_hirq :
|
|
(fsmc_addr[7:0]==8'h2a)? ss_hirq_mask :
|
|
|
|
16'hffff;
|
|
end
|
|
|
|
|
|
reg st_rd_delay;
|
|
|
|
always @(posedge mclk)
|
|
begin
|
|
st_rd_delay <= (ST_RD==0 && ST_CS==0) ? 1'b0: 1'b1;
|
|
end
|
|
|
|
assign ST_AD = (st_rd_delay==0)? (
|
|
(fsmc_addr[24]==0)? st_reg_data_out : st_ram_data_out
|
|
) : 16'hzzzz;
|
|
|
|
|
|
wire st_ram_cs = (fsmc_cs==0 && ST_ADDR[7]==1);
|
|
|
|
wire[15:0] st_reg_stat = {
|
|
pll_locked, ST_IRQ, 1'b0, ss_in_cmd, 4'b0,
|
|
5'b0, st_irq_fifo, st_irq_cmd, st_irq_cdc
|
|
};
|
|
|
|
wire[15:0] st_fifo_stat = {4'b0, fifo_full, fifo_usedw};
|
|
|
|
|
|
wire st_irq_fifoen = st_reg_ctrl[2];
|
|
wire st_irq_cmd_en = st_reg_ctrl[1];
|
|
wire st_irq_cdc_en = st_reg_ctrl[0];
|
|
|
|
wire ST_IRQ = ( (st_irq_cdc_en==1 && st_irq_cdc==1) ||
|
|
(st_irq_cmd_en==1 && st_irq_cmd==1) ||
|
|
(st_irq_fifoen==1 && st_irq_fifo==1) );
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
// SATURN ABUS //
|
|
///////////////////////////////////////////////////////
|
|
|
|
reg sscs_s0, sscs_s1, sscs_s2, sscs_s3, sscs_s4;
|
|
reg ssfc1_s0, ssfc1_s1, ssfc1_s2;
|
|
|
|
always @(posedge mclk)
|
|
begin
|
|
sscs_s0 <= (SS_CS0 & SS_CS1 & SS_CS2);
|
|
sscs_s1 <= sscs_s0;
|
|
sscs_s2 <= sscs_s1;
|
|
sscs_s3 <= sscs_s2;
|
|
sscs_s4 <= sscs_s3;
|
|
|
|
ssfc1_s0 <= SS_FC1;
|
|
ssfc1_s1 <= ssfc1_s0;
|
|
ssfc1_s2 <= ssfc1_s1;
|
|
end
|
|
|
|
wire ss_refresh = (ssfc1_s2==1 && ssfc1_s1==0);
|
|
|
|
wire ss_rd_start = (sscs_s2==1 && sscs_s1==0 && SS_RD==0);
|
|
wire ss_wr_start = (sscs_s4==1 && sscs_s3==0 && (SS_WR0==0 || SS_WR1==0));
|
|
|
|
assign SS_DATA =
|
|
(SS_RD==0 && SS_CS0==0)? ss_ram_data_out :
|
|
(SS_RD==0 && SS_CS1==0)? ss_cs1_data_out :
|
|
(SS_RD==0 && ss_reg_cs==1)? ss_bcr_data_out :
|
|
(SS_RD==0 && ss_cdc_cs==1)? ss_cdc_data_out :
|
|
16'hzzzz;
|
|
|
|
assign SS_DATA_OE = (SS_CS0==1 && SS_CS1==1 && (SS_CS2==1 || (ss_cdc_cs==1 && SS_RD==0 && ss_cdc_en==0)));
|
|
|
|
assign SS_DATA_DIR = (SS_WR0 & SS_WR1);
|
|
|
|
///////////////////////////////////////////////////////
|
|
// SATURN System Control //
|
|
///////////////////////////////////////////////////////
|
|
|
|
reg[15:0] ss_bcr_data_out;
|
|
reg[15:0] ss_reg_ctrl;
|
|
reg[15:0] ss_reg_cmd;
|
|
reg[15:0] ss_reg_data;
|
|
reg[31:0] ss_reg_timer;
|
|
|
|
// 00: Bootrom
|
|
// 01: Data Cart
|
|
// 10: RAM Cart: 1MBytes
|
|
// 11: RAM Cart: 4MBytes
|
|
wire[1:0] ss_cs0_type = ss_reg_ctrl[13:12];
|
|
wire[15:0] ss_cs1_data_out = (SS_ADDR[23:16]==8'hff && ss_cs0_type[1]==1)?
|
|
(
|
|
(ss_cs0_type[0]==0)? 16'hff5a : 16'hff5c
|
|
) : 16'hffff;
|
|
|
|
wire[15:0] ss_reg_stat = {4'b0, fifo_full, fifo_usedw};
|
|
|
|
|
|
// 0x25807000
|
|
wire ss_reg_cs = (SS_CS2==0 && SS_ADDR[14:12]==3'b111);
|
|
|
|
always @(posedge mclk)
|
|
begin
|
|
ss_bcr_data_out <=
|
|
(SS_ADDR[5:1]==5'b00_000)? 16'h5253 : // ID: "SR"
|
|
(SS_ADDR[5:1]==5'b00_001)? 16'h1102 : // ver: HW1.1 && SW0.2
|
|
(SS_ADDR[5:2]==4'b00_01 )? ss_reg_ctrl :
|
|
(SS_ADDR[5:2]==4'b00_10 )? ss_reg_stat :
|
|
(SS_ADDR[5:1]==5'b00_110)? ss_reg_timer[31:16] :
|
|
(SS_ADDR[5:1]==5'b00_111)? ss_reg_timer[15: 0] :
|
|
(SS_ADDR[5:2]==4'b01_00 )? ss_reg_cmd :
|
|
(SS_ADDR[5:2]==4'b01_01 )? ss_reg_data :
|
|
(SS_ADDR[5:2]==4'b01_10 )? ss_fifo_data_out :
|
|
16'h0000;
|
|
end
|
|
|
|
|
|
always @(negedge NRESET or posedge mclk)
|
|
begin
|
|
if(NRESET==0)
|
|
ss_reg_ctrl <= 16'h0100;
|
|
else if(ss_wr_start==1 && ss_reg_cs==1 && SS_ADDR[5:2]==4'b00_01)
|
|
ss_reg_ctrl <= SS_DATA;
|
|
end
|
|
|
|
// Saturn set and STM32 reset
|
|
always @(negedge NRESET or posedge mclk)
|
|
begin
|
|
if(NRESET==0)
|
|
ss_reg_cmd <= 4'b0000;
|
|
else if(st_wr_start==1 && fsmc_addr[24]==0 && fsmc_addr[7:0]==8'h10)
|
|
ss_reg_cmd <= 0;
|
|
else if(ss_wr_start==1 && ss_reg_cs==1 && SS_ADDR[5:2]==4'b01_00)
|
|
ss_reg_cmd <= SS_DATA;
|
|
end
|
|
|
|
// Saturn or STM32 set
|
|
always @(negedge NRESET or posedge mclk)
|
|
begin
|
|
if(NRESET==0) begin
|
|
ss_reg_data <= 1'b0;
|
|
end else begin
|
|
if(ss_wr_start==1 && ss_reg_cs==1 && SS_ADDR[5:2]==4'b01_01)
|
|
ss_reg_data <= SS_DATA;
|
|
else if(st_wr_start==1 && fsmc_addr[24]==0 && fsmc_addr[7:0]==8'h12)
|
|
ss_reg_data <= ST_AD;
|
|
end
|
|
end
|
|
|
|
|
|
|
|
reg[6:0] ss_timer_feed;
|
|
|
|
always @(posedge mclk)
|
|
begin
|
|
if(ss_timer_feed==7'd99)
|
|
ss_timer_feed <= 0;
|
|
else
|
|
ss_timer_feed <= ss_timer_feed+7'b1;
|
|
end
|
|
|
|
always @(posedge mclk)
|
|
begin
|
|
if(ss_wr_start==1 && ss_reg_cs==1 && SS_ADDR[5:2]==4'b00_11)
|
|
ss_reg_timer <= 0;
|
|
else if(ss_timer_feed==0) begin
|
|
ss_reg_timer <= ss_reg_timer+32'b1;
|
|
end
|
|
end
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
// SATURN CDC FIFO //
|
|
///////////////////////////////////////////////////////
|
|
|
|
|
|
wire fifo_reset = (NRESET==0 || st_fifo_reset==1);
|
|
wire fifo_empty;
|
|
wire fifo_full;
|
|
wire fifo_rd = (ss_rd_start==1 && ((ss_cdc_cs==1 && SS_ADDR[5:2]==0) || (ss_reg_cs==1 && SS_ADDR[5:2]==4'b01_10)) );
|
|
wire[15:0] fifo_q;
|
|
wire[15:0] fifo_wdata = ST_AD;
|
|
wire[10:0] fifo_usedw;
|
|
|
|
wire[15:0] ss_fifo_data_out = {fifo_q[7:0], fifo_q[15:8]};
|
|
|
|
cdcfifo _cdcfifo(
|
|
.sclr(fifo_reset),
|
|
.clock(mclk),
|
|
.rdreq(fifo_rd),
|
|
.q(fifo_q),
|
|
.wrreq(st_fifo_write),
|
|
.data(fifo_wdata),
|
|
.empty(fifo_empty),
|
|
.usedw(fifo_usedw),
|
|
.full(fifo_full)
|
|
);
|
|
|
|
///////////////////////////////////////////////////////
|
|
// SATURN CDC //
|
|
///////////////////////////////////////////////////////
|
|
|
|
reg[15:0] ss_cdc_data_out;
|
|
reg[15:0] ss_hirq_mask;
|
|
reg[15:0] ss_cr1;
|
|
reg[15:0] ss_cr2;
|
|
reg[15:0] ss_cr3;
|
|
reg[15:0] ss_cr4;
|
|
|
|
// enable CDC read out
|
|
wire ss_cdc_en = ss_reg_ctrl[15];
|
|
|
|
// 0x25800000
|
|
wire ss_cdc_cs = (SS_CS2==0 && SS_ADDR[14:12]==3'b000);
|
|
|
|
always @(posedge mclk)
|
|
begin
|
|
if(ss_wr_start==1 && ss_cdc_cs==1) begin
|
|
if(SS_ADDR[5:2]==4'b00_11) ss_hirq_mask <= SS_DATA;
|
|
if(SS_ADDR[5:2]==4'b01_10) ss_cr1 <= SS_DATA;
|
|
if(SS_ADDR[5:2]==4'b01_11) ss_cr2 <= SS_DATA;
|
|
if(SS_ADDR[5:2]==4'b10_00) ss_cr3 <= SS_DATA;
|
|
if(SS_ADDR[5:2]==4'b10_01) ss_cr4 <= SS_DATA;
|
|
end
|
|
end
|
|
|
|
always @(posedge mclk)
|
|
begin
|
|
ss_cdc_data_out <=
|
|
(SS_ADDR[5:2]==4'b00_00)? ss_fifo_data_out :
|
|
(SS_ADDR[5:2]==4'b00_10)? ss_hirq :
|
|
(SS_ADDR[5:2]==4'b00_11)? ss_hirq_mask :
|
|
(SS_ADDR[5:2]==4'b01_10)? ss_resp1 :
|
|
(SS_ADDR[5:2]==4'b01_11)? ss_resp2 :
|
|
(SS_ADDR[5:2]==4'b10_00)? ss_resp3 :
|
|
(SS_ADDR[5:2]==4'b10_01)? ss_resp4 :
|
|
16'h0000;
|
|
end
|
|
|
|
assign SS_SSEL = ~ss_cdc_en;
|
|
|
|
assign SS_IRQ = (ss_hirq&ss_hirq_mask)==0? 1'b0: 1'b1;
|
|
|
|
assign SS_OUTEN = ~ss_cdc_en;
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
// SDRAM //
|
|
///////////////////////////////////////////////////////
|
|
|
|
|
|
// STM32 is LittleEndian system
|
|
wire[25:0] st_ram_addr = {2'b0, fsmc_addr[23:0]};
|
|
wire[ 1:0] st_mask = {ST_BL1,ST_BL0};
|
|
wire[15:0] st_ram_data_out;
|
|
wire st_ram_wait;
|
|
|
|
// Saturn CS0 memmap:
|
|
// 02000000 - 02400000 : 4MB ROM Cart
|
|
// 02400000 - 02800000 : 4MB RAM Cart
|
|
// 02800000 - 03000000 : 8MB Free Space
|
|
// 03000000 - 04000000 : 16MB Free Space
|
|
// Saturn is BigEndian system
|
|
wire ss_ram_cs = ~SS_CS0;
|
|
wire[25:0] ss_ram_addr = {2'b0, SS_ADDR};
|
|
wire[ 1:0] ss_mask = {SS_WR0,SS_WR1};
|
|
wire[15:0] ss_ram_din = {SS_DATA[7:0], SS_DATA[15:8]};
|
|
wire[15:0] ss_ram_dout;
|
|
wire[15:0] ss_ram_data_out = {ss_ram_dout[7:0], ss_ram_dout[15:8]};
|
|
wire ss_ram_wait;
|
|
|
|
|
|
memhub _mh(
|
|
NRESET, mclk,
|
|
ss_ram_cs, ss_rd_start, ss_wr_start, ss_mask, ss_ram_wait, ss_ram_addr, ss_ram_din, ss_ram_dout,
|
|
st_ram_cs, st_rd_start, st_wr_start, st_mask, st_ram_wait, st_ram_addr, ST_AD, st_ram_data_out,
|
|
SD_CKE, SD_CS, SD_RAS, SD_CAS, SD_WE, SD_ADDR, SD_BA, SD_DQM, SD_DQ, ss_refresh
|
|
);
|
|
|
|
//assign SD_CLK = sdclk;
|
|
assign SD_CLK = mclk;
|
|
//assign PSRAM_CS = 1'b0;
|
|
|
|
assign SS_WAIT = ss_ram_wait;
|
|
assign ST_WAIT = st_ram_wait & ~ale_set & ~ale_ack & ~st_wr_start;
|
|
|
|
endmodule
|
|
|