From 12316d40128a4f422055c924aeebba9dc1b184cd Mon Sep 17 00:00:00 2001 From: ikari Date: Fri, 17 Dec 2010 03:01:39 +0100 Subject: [PATCH] MSU-1 support (RTL) --- verilog/sd2snes/address.v | 6 +- verilog/sd2snes/avr_cmd.v | 219 +++++++++-- verilog/sd2snes/dac_test.v | 101 +++++- verilog/sd2snes/data.v | 9 +- verilog/sd2snes/ipcore_dir/dac_buf.v | 145 ++++++++ verilog/sd2snes/ipcore_dir/dac_buf.xise | 382 ++++++++++++++++++++ verilog/sd2snes/ipcore_dir/msu_databuf.v | 145 ++++++++ verilog/sd2snes/ipcore_dir/msu_databuf.xise | 79 ++++ verilog/sd2snes/main.v | 87 ++++- verilog/sd2snes/msu.v | 174 +++++++++ verilog/sd2snes/sd2snes.xise | 18 + verilog/sd2snes/sd_dma.v | 27 +- 12 files changed, 1331 insertions(+), 61 deletions(-) create mode 100644 verilog/sd2snes/ipcore_dir/dac_buf.v create mode 100644 verilog/sd2snes/ipcore_dir/dac_buf.xise create mode 100644 verilog/sd2snes/ipcore_dir/msu_databuf.v create mode 100644 verilog/sd2snes/ipcore_dir/msu_databuf.xise create mode 100644 verilog/sd2snes/msu.v diff --git a/verilog/sd2snes/address.v b/verilog/sd2snes/address.v index 5defd3f..98ced2a 100644 --- a/verilog/sd2snes/address.v +++ b/verilog/sd2snes/address.v @@ -32,7 +32,9 @@ module address( input ADDR_WRITE, output ROM_ADDR0, input [23:0] SAVERAM_MASK, - input [23:0] ROM_MASK + input [23:0] ROM_MASK, + input use_msu, + output msu_enable ); wire [1:0] SRAM_BANK; @@ -102,5 +104,7 @@ assign ROM_ADDR = SRAM_ADDR_FULL[23:1]; assign ROM_SEL = 1'b0; // (MODE) ? CS_ARRAY[SRAM_BANK] : IS_SAVERAM ? 4'b1000 : CS_ARRAY[SRAM_BANK]; assign ROM_ADDR0 = SRAM_ADDR_FULL[0]; +//488888 +assign msu_enable = (!SNES_ADDR[22] && ((SNES_ADDR[15:0] & 16'hfff8) == 16'h2000)); endmodule diff --git a/verilog/sd2snes/avr_cmd.v b/verilog/sd2snes/avr_cmd.v index f643d19..5065213 100644 --- a/verilog/sd2snes/avr_cmd.v +++ b/verilog/sd2snes/avr_cmd.v @@ -40,12 +40,34 @@ module mcu_cmd( output [23:0] saveram_mask_out, output [23:0] rom_mask_out, - // SPI "DMA" extension + // SD "DMA" extension output SD_DMA_EN, input SD_DMA_STATUS, input SD_DMA_NEXTADDR, input [7:0] SD_DMA_SRAM_DATA, - input SD_DMA_SRAM_WE + input SD_DMA_SRAM_WE, + output [1:0] SD_DMA_TGT, + output SD_DMA_PARTIAL, + output [11:0] SD_DMA_PARTIAL_START, + output [11:0] SD_DMA_PARTIAL_END, + + // DAC + output [10:0] dac_addr_out, +// output [7:0] dac_volume_out, +// output dac_volume_latch_out, + input DAC_STATUS, + output dac_play_out, + output dac_reset_out, + + // MSU data + output [13:0] msu_addr_out, + input [6:0] MSU_STATUS, + output [5:0] msu_status_reset_out, + output [5:0] msu_status_set_out, + output msu_status_reset_we, + input [31:0] msu_addressrq, + input [15:0] msu_trackrq, + input [7:0] msu_volumerq ); reg [3:0] MAPPER_BUF; @@ -53,14 +75,46 @@ reg [3:0] SRAM_SIZE_BUF; reg MCU_READ_BUF; reg MCU_WRITE_BUF; reg [23:0] ADDR_OUT_BUF; +reg [10:0] DAC_ADDR_OUT_BUF; +reg [7:0] DAC_VOL_OUT_BUF; +reg DAC_VOL_LATCH_BUF; +reg DAC_PLAY_OUT_BUF; +reg DAC_RESET_OUT_BUF; +reg [13:0] MSU_ADDR_OUT_BUF; +reg [5:0] msu_status_set_out_buf; +reg [5:0] msu_status_reset_out_buf; +reg msu_status_reset_we_buf; reg [7:0] MCU_DATA_OUT_BUF; reg [7:0] MCU_DATA_IN_BUF; reg [1:0] mcu_nextaddr_buf; +reg SD_DMA_NEXTADDRr; +always @(posedge clk) SD_DMA_NEXTADDRr <= SD_DMA_NEXTADDR; + wire mcu_nextaddr; +reg DAC_STATUSr; +reg SD_DMA_STATUSr; +reg [6:0] MSU_STATUSr; +always @(posedge clk) begin + DAC_STATUSr <= DAC_STATUS; + SD_DMA_STATUSr <= SD_DMA_STATUS; + MSU_STATUSr <= MSU_STATUS; +end + +reg SD_DMA_PARTIALr; +assign SD_DMA_PARTIAL = SD_DMA_PARTIALr; + reg SD_DMA_ENr; assign SD_DMA_EN = SD_DMA_ENr; +reg [1:0] SD_DMA_TGTr; +assign SD_DMA_TGT = SD_DMA_TGTr; + +reg [11:0] SD_DMA_PARTIAL_STARTr; +reg [11:0] SD_DMA_PARTIAL_ENDr; +assign SD_DMA_PARTIAL_START = SD_DMA_PARTIAL_STARTr; +assign SD_DMA_PARTIAL_END = SD_DMA_PARTIAL_ENDr; + reg [2:0] spi_dma_nextaddr_r; reg [1:0] SRAM_MASK_IDX; @@ -71,6 +125,10 @@ assign spi_data_out = MCU_DATA_IN_BUF; initial begin ADDR_OUT_BUF = 0; + DAC_ADDR_OUT_BUF = 0; + MSU_ADDR_OUT_BUF = 0; + DAC_VOL_OUT_BUF = 0; + DAC_VOL_LATCH_BUF = 0; spi_dma_nextaddr_r = 0; SD_DMA_ENr = 0; end @@ -81,25 +139,51 @@ always @(posedge clk) begin case (cmd_data[7:4]) 4'h3: // select mapper MAPPER_BUF <= cmd_data[3:0]; - 4'h4: // SD DMA + 4'h4: begin// SD DMA SD_DMA_ENr <= 1; + SD_DMA_TGTr <= cmd_data[1:0]; + SD_DMA_PARTIALr <= cmd_data[2]; + end // 4'hE: // select memory unit endcase end else if (param_ready) begin - case (cmd_data[7:0]) - 8'h00: - case (spi_byte_cnt) - 32'h2: begin - ADDR_OUT_BUF[23:16] <= param_data; - ADDR_OUT_BUF[15:0] <= 16'b0; - end - 32'h3: - ADDR_OUT_BUF[15:8] <= param_data; - 32'h4: - ADDR_OUT_BUF[7:0] <= param_data; - endcase - 8'h01: + casex (cmd_data[7:0]) + 8'h0x: + case (cmd_data[1:0]) + 2'b01: begin + case (spi_byte_cnt) + 32'h2: begin + DAC_ADDR_OUT_BUF[10:8] <= param_data[2:0]; + DAC_ADDR_OUT_BUF[7:0] <= 8'b0; + end + 32'h3: + DAC_ADDR_OUT_BUF[7:0] <= param_data; + endcase + end + 2'b10: begin + case (spi_byte_cnt) + 32'h2: begin + MSU_ADDR_OUT_BUF[13:8] <= param_data[5:0]; + MSU_ADDR_OUT_BUF[7:0] <= 8'b0; + end + 32'h3: + MSU_ADDR_OUT_BUF[7:0] <= param_data; + endcase + end + default: + case (spi_byte_cnt) + 32'h2: begin + ADDR_OUT_BUF[23:16] <= param_data; + ADDR_OUT_BUF[15:0] <= 16'b0; + end + 32'h3: + ADDR_OUT_BUF[15:8] <= param_data; + 32'h4: + ADDR_OUT_BUF[7:0] <= param_data; + endcase + endcase + 8'h1x: case (spi_byte_cnt) 32'h2: ROM_MASK[23:16] <= param_data; @@ -108,7 +192,7 @@ always @(posedge clk) begin 32'h4: ROM_MASK[7:0] <= param_data; endcase - 8'h02: + 8'h2x: case (spi_byte_cnt) 32'h2: SAVERAM_MASK[23:16] <= param_data; @@ -117,16 +201,62 @@ always @(posedge clk) begin 32'h4: SAVERAM_MASK[7:0] <= param_data; endcase - 8'h40: + 8'h4x: SD_DMA_ENr <= 1'b0; - 8'h90: - MCU_DATA_OUT_BUF <= param_data; - 8'h91: +// 8'h5x: +// case (spi_byte_cnt) +// 32'h2: +// DAC_VOL_OUT_BUF <= param_data; +// 32'h3: +// DAC_VOL_LATCH_BUF <= 1'b1; +// 32'h4: +// DAC_VOL_LATCH_BUF <= 1'b0; +// endcase + 8'h6x: + case (spi_byte_cnt) + 32'h2: + SD_DMA_PARTIAL_STARTr[10:9] <= param_data[1:0]; + 32'h3: + SD_DMA_PARTIAL_STARTr[8:0] <= {param_data, 1'b0}; + 32'h4: + SD_DMA_PARTIAL_ENDr[10:9] <= param_data[1:0]; + 32'h5: + SD_DMA_PARTIAL_ENDr[8:0] <= {param_data, 1'b0}; + endcase + 8'h9x: MCU_DATA_OUT_BUF <= param_data; + 8'he0: + case (spi_byte_cnt) + 32'h2: begin + msu_status_set_out_buf <= param_data[5:0]; + end + 32'h3: begin + msu_status_reset_out_buf <= param_data[5:0]; + msu_status_reset_we_buf <= 1'b1; + end + 32'h4: + msu_status_reset_we_buf <= 1'b0; + endcase + 8'he1: // pause DAC + DAC_PLAY_OUT_BUF <= 1'b0; + 8'he2: // resume DAC + DAC_PLAY_OUT_BUF <= 1'b1; + 8'he3: // reset DAC (set DAC playback address = 0) + case (spi_byte_cnt) + 32'h2: + DAC_RESET_OUT_BUF <= 1'b1; + 32'h3: + DAC_RESET_OUT_BUF <= 1'b0; + endcase endcase end - if (SD_DMA_NEXTADDR | (mcu_nextaddr & (cmd_data[7:5] == 3'h4) && (cmd_data[0]) && (spi_byte_cnt > (32'h1+cmd_data[4])))) - ADDR_OUT_BUF <= ADDR_OUT_BUF + 1; + if (SD_DMA_NEXTADDR | (mcu_nextaddr & (cmd_data[7:5] == 3'h4) && (cmd_data[0]) && (spi_byte_cnt > (32'h1+cmd_data[4])))) begin + case (SD_DMA_TGTr) + 2'b00: ADDR_OUT_BUF <= ADDR_OUT_BUF + 1; + 2'b01: DAC_ADDR_OUT_BUF <= DAC_ADDR_OUT_BUF + 1; + 2'b10: MSU_ADDR_OUT_BUF <= MSU_ADDR_OUT_BUF + 1; + endcase + end end // value fetch during last SPI bit @@ -135,11 +265,39 @@ always @(posedge clk) begin if (cmd_data[7:0] == 8'hF0) MCU_DATA_IN_BUF <= 8'hA5; else if (cmd_data[7:0] == 8'hF1) - MCU_DATA_IN_BUF <= {SD_DMA_STATUS, 7'b0}; + case (spi_byte_cnt[0]) + 1'b1: // buffer status + MCU_DATA_IN_BUF <= {SD_DMA_STATUSr, DAC_STATUSr, MSU_STATUSr[6], 5'b0}; + 1'b0: // control status + MCU_DATA_IN_BUF <= {2'b0, MSU_STATUSr[5:0]}; + endcase + else if (cmd_data[7:0] == 8'hF2) + case (spi_byte_cnt) + 32'h1: + MCU_DATA_IN_BUF <= msu_addressrq[31:24]; + 32'h2: + MCU_DATA_IN_BUF <= msu_addressrq[23:16]; + 32'h3: + MCU_DATA_IN_BUF <= msu_addressrq[15:8]; + 32'h4: + MCU_DATA_IN_BUF <= msu_addressrq[7:0]; + endcase + else if (cmd_data[7:0] == 8'hF3) + case (spi_byte_cnt) + 23'h1: + MCU_DATA_IN_BUF <= msu_trackrq[15:8]; + 23'h2: + MCU_DATA_IN_BUF <= msu_trackrq[7:0]; + endcase + else if (cmd_data[7:0] == 8'hF4) + MCU_DATA_IN_BUF <= msu_volumerq; else if (cmd_data[7:0] == 8'hFF) MCU_DATA_IN_BUF <= param_data; - else + else if (cmd_data[7:4] == 4'h8) MCU_DATA_IN_BUF <= mcu_data_in; + else + MCU_DATA_IN_BUF <= cmd_data; + end // nextaddr pulse generation @@ -170,8 +328,17 @@ end assign mcu_nextaddr = mcu_nextaddr_buf == 2'b01; assign mcu_read = MCU_READ_BUF; -assign mcu_write = SD_DMA_STATUS ? SD_DMA_SRAM_WE : MCU_WRITE_BUF; +assign mcu_write = SD_DMA_STATUS ? (SD_DMA_TGTr == 2'b00 ? SD_DMA_SRAM_WE : 1'b1) : MCU_WRITE_BUF; assign addr_out = ADDR_OUT_BUF; +assign dac_addr_out = DAC_ADDR_OUT_BUF; +assign msu_addr_out = MSU_ADDR_OUT_BUF; +assign dac_volume_out = DAC_VOL_OUT_BUF; +assign dac_volume_latch_out = DAC_VOL_LATCH_BUF; +assign dac_play_out = DAC_PLAY_OUT_BUF; +assign dac_reset_out = DAC_RESET_OUT_BUF; +assign msu_status_reset_we = msu_status_reset_we_buf; +assign msu_status_reset_out = msu_status_reset_out_buf; +assign msu_status_set_out = msu_status_set_out_buf; assign mcu_data_out = SD_DMA_STATUS ? SD_DMA_SRAM_DATA : MCU_DATA_OUT_BUF; assign mcu_mapper = MAPPER_BUF; assign mcu_sram_size = SRAM_SIZE_BUF; diff --git a/verilog/sd2snes/dac_test.v b/verilog/sd2snes/dac_test.v index 1a78ba2..b268eec 100644 --- a/verilog/sd2snes/dac_test.v +++ b/verilog/sd2snes/dac_test.v @@ -20,51 +20,116 @@ ////////////////////////////////////////////////////////////////////////////////// module dac_test( input clkin, + input we, + input[10:0] pgm_address, + input[7:0] pgm_data, + input[7:0] volume, + input vol_latch, + input play, + input reset, output sdout, output lrck, - output mclk + output mclk, + output DAC_STATUS ); - + +reg[8:0] dac_address_r; +wire[8:0] dac_address = dac_address_r; +reg dac_nextaddr_r; + +wire[31:0] dac_data; +assign DAC_STATUS = dac_address_r[8]; +reg[7:0] vol_reg; +reg[7:0] vol_target_reg; +reg[1:0] vol_latch_reg; +reg vol_valid; + +dac_buf snes_dac_buf ( + .clka(clkin), + .wea(~we), // Bus [0 : 0] + .addra(pgm_address), // Bus [10 : 0] + .dina(pgm_data), // Bus [7 : 0] + .clkb(clkin), + .addrb(dac_address), // Bus [9 : 0] + .doutb(dac_data)); // Bus [15 : 0] + reg [15:0] cnt; reg [15:0] smpcnt; +reg [15:0] samples; wire [15:0] sample = {smpcnt[10] ? ~smpcnt[9:0] : smpcnt[9:0], 6'b0}; wire [15:0] sample2 = {smpcnt[9] ? ~smpcnt[8:0] : smpcnt[8:0], 7'b0}; reg [15:0] smpshift; +reg [15:0] smpdata; -assign mclk = cnt[3]; // mclk = clk/8 -assign lrck = cnt[11]; // lrck = mclk/256 -wire sclk = cnt[6]; // sclk = lrck*32 +assign mclk = cnt[2]; // mclk = clk/8 +assign lrck = cnt[10]; // lrck = mclk/256 +wire sclk = cnt[5]; // sclk = lrck*32 -reg [7:0] volume; -reg [1:0] lrck_sreg; -reg sclk_sreg; -wire lrck_rising = ({lrck_sreg[0],lrck} == 2'b01); -wire lrck_falling = ({lrck_sreg[0],lrck} == 2'b10); +reg [2:0] lrck_sreg; +reg [2:0] sclk_sreg; +wire lrck_rising = ({lrck_sreg[2:1]} == 2'b01); +wire lrck_falling = ({lrck_sreg[2:1]} == 2'b10); -wire sclk_rising = ({sclk_sreg, sclk} == 2'b01); +wire sclk_rising = ({sclk_sreg[2:1]} == 2'b01); +wire vol_latch_rising = (vol_latch_reg[1:0] == 2'b01); reg sdout_reg; assign sdout = sdout_reg; +reg [1:0] reset_sreg; +wire reset_rising = (reset_sreg[1:0] == 2'b01); + +reg play_r; + initial begin - cnt = 16'b0; + cnt = 16'hff00; smpcnt = 16'b0; - lrck_sreg = 2'b0; + lrck_sreg = 2'b11; sclk_sreg = 1'b0; - volume = 8'b0; + dac_address_r = 11'b0; + vol_valid = 1'b0; + vol_latch_reg = 1'b0; + vol_reg = 8'h0; + vol_target_reg = 8'h0; + samples <= 16'h0; end always @(posedge clkin) begin cnt <= cnt + 1; - lrck_sreg <= {lrck_sreg[0], lrck}; - sclk_sreg <= sclk; + lrck_sreg <= {lrck_sreg[1:0], lrck}; + sclk_sreg <= {sclk_sreg[1:0], sclk}; + vol_latch_reg <= {vol_latch_reg[0], vol_latch}; + play_r <= play; + reset_sreg <= {reset_sreg[0], reset}; +end + +always @(posedge clkin) begin + if (vol_latch_rising) begin + vol_valid <= 1'b1; + end + else if(vol_valid) begin + vol_target_reg <= volume; + vol_valid <= 1'b0; + end +end + +// ramp volume only every 4 samples +always @(posedge clkin) begin + if (lrck_rising && &samples[1:0]) begin + if(vol_reg > vol_target_reg) + vol_reg <= vol_reg - 1; + else if(vol_reg < vol_target_reg) + vol_reg <= vol_reg + 1; + end end always @(posedge clkin) begin if (lrck_rising) begin // right channel - smpshift <= (({16'h0, sample} * volume) >> 8) ^ 16'h8000; // convert to signed + smpshift <= (({16'h0, dac_data[31:16]^16'h8000} * vol_reg) >> 8) ^ 16'h8000; + dac_address_r <= reset_rising ? 9'h0 : (dac_address_r + play_r); + samples <= samples + 1; end else if (lrck_falling) begin // left channel - smpshift <= (({16'h0, sample2} * volume) >> 8) ^ 16'h8000; + smpshift <= (({16'h0, dac_data[15:0]^16'h8000} * vol_reg) >> 8) ^ 16'h8000; end else begin if (sclk_rising) begin smpcnt <= smpcnt + 1; diff --git a/verilog/sd2snes/data.v b/verilog/sd2snes/data.v index 16e8545..1a18cb2 100644 --- a/verilog/sd2snes/data.v +++ b/verilog/sd2snes/data.v @@ -34,7 +34,10 @@ module data( input ROM_DATA_TO_SNES_MEM, input ROM_DATA_TO_MCU_MEM, input MCU_OVR, - input ROM_ADDR0 + input ROM_ADDR0, + output [7:0] MSU_DATA_IN, + input [7:0] MSU_DATA_OUT, + input msu_enable ); reg [7:0] SNES_IN_MEM; @@ -44,7 +47,9 @@ reg [7:0] MCU_OUT_MEM; wire [7:0] FROM_ROM_BYTE; -assign SNES_DATA = SNES_READ ? 8'bZ : (!MCU_OVR ? 8'h00 : SNES_OUT_MEM); +assign MSU_DATA_IN = SNES_DATA; + +assign SNES_DATA = SNES_READ ? 8'bZ : (!MCU_OVR ? 8'h00 : (msu_enable ? MSU_DATA_OUT : SNES_OUT_MEM)); assign FROM_ROM_BYTE = (ROM_ADDR0 ? ROM_DATA[7:0] : ROM_DATA[15:8]); diff --git a/verilog/sd2snes/ipcore_dir/dac_buf.v b/verilog/sd2snes/ipcore_dir/dac_buf.v new file mode 100644 index 0000000..f84343f --- /dev/null +++ b/verilog/sd2snes/ipcore_dir/dac_buf.v @@ -0,0 +1,145 @@ +/******************************************************************************* +* This file is owned and controlled by Xilinx and must be used * +* solely for design, simulation, implementation and creation of * +* design files limited to Xilinx devices or technologies. Use * +* with non-Xilinx devices or technologies is expressly prohibited * +* and immediately terminates your license. * +* * +* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" * +* SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR * +* XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION * +* AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION * +* OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS * +* IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, * +* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE * +* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY * +* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE * +* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR * +* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF * +* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * +* FOR A PARTICULAR PURPOSE. * +* * +* Xilinx products are not intended for use in life support * +* appliances, devices, or systems. Use in such applications are * +* expressly prohibited. * +* * +* (c) Copyright 1995-2009 Xilinx, Inc. * +* All rights reserved. * +*******************************************************************************/ +// The synthesis directives "translate_off/translate_on" specified below are +// supported by Xilinx, Mentor Graphics and Synplicity synthesis +// tools. Ensure they are correct for your synthesis tool(s). + +// You must compile the wrapper file dac_buf.v when simulating +// the core, dac_buf. When compiling the wrapper file, be sure to +// reference the XilinxCoreLib Verilog simulation library. For detailed +// instructions, please refer to the "CORE Generator Help". + +`timescale 1ns/1ps + +module dac_buf( + clka, + wea, + addra, + dina, + clkb, + addrb, + doutb); + + +input clka; +input [0 : 0] wea; +input [10 : 0] addra; +input [7 : 0] dina; +input clkb; +input [8 : 0] addrb; +output [31 : 0] doutb; + +// synthesis translate_off + + BLK_MEM_GEN_V4_3 #( + .C_ADDRA_WIDTH(11), + .C_ADDRB_WIDTH(9), + .C_ALGORITHM(1), + .C_BYTE_SIZE(9), + .C_COMMON_CLK(1), + .C_DEFAULT_DATA("0"), + .C_DISABLE_WARN_BHV_COLL(0), + .C_DISABLE_WARN_BHV_RANGE(0), + .C_FAMILY("spartan3"), + .C_HAS_ENA(0), + .C_HAS_ENB(0), + .C_HAS_INJECTERR(0), + .C_HAS_MEM_OUTPUT_REGS_A(0), + .C_HAS_MEM_OUTPUT_REGS_B(0), + .C_HAS_MUX_OUTPUT_REGS_A(0), + .C_HAS_MUX_OUTPUT_REGS_B(0), + .C_HAS_REGCEA(0), + .C_HAS_REGCEB(0), + .C_HAS_RSTA(0), + .C_HAS_RSTB(0), + .C_HAS_SOFTECC_INPUT_REGS_A(0), + .C_HAS_SOFTECC_OUTPUT_REGS_B(0), + .C_INITA_VAL("0"), + .C_INITB_VAL("0"), + .C_INIT_FILE_NAME("no_coe_file_loaded"), + .C_LOAD_INIT_FILE(0), + .C_MEM_TYPE(1), + .C_MUX_PIPELINE_STAGES(0), + .C_PRIM_TYPE(1), + .C_READ_DEPTH_A(2048), + .C_READ_DEPTH_B(512), + .C_READ_WIDTH_A(8), + .C_READ_WIDTH_B(32), + .C_RSTRAM_A(0), + .C_RSTRAM_B(0), + .C_RST_PRIORITY_A("CE"), + .C_RST_PRIORITY_B("CE"), + .C_RST_TYPE("SYNC"), + .C_SIM_COLLISION_CHECK("ALL"), + .C_USE_BYTE_WEA(0), + .C_USE_BYTE_WEB(0), + .C_USE_DEFAULT_DATA(0), + .C_USE_ECC(0), + .C_USE_SOFTECC(0), + .C_WEA_WIDTH(1), + .C_WEB_WIDTH(1), + .C_WRITE_DEPTH_A(2048), + .C_WRITE_DEPTH_B(512), + .C_WRITE_MODE_A("WRITE_FIRST"), + .C_WRITE_MODE_B("WRITE_FIRST"), + .C_WRITE_WIDTH_A(8), + .C_WRITE_WIDTH_B(32), + .C_XDEVICEFAMILY("spartan3")) + inst ( + .CLKA(clka), + .WEA(wea), + .ADDRA(addra), + .DINA(dina), + .CLKB(clkb), + .ADDRB(addrb), + .DOUTB(doutb), + .RSTA(), + .ENA(), + .REGCEA(), + .DOUTA(), + .RSTB(), + .ENB(), + .REGCEB(), + .WEB(), + .DINB(), + .INJECTSBITERR(), + .INJECTDBITERR(), + .SBITERR(), + .DBITERR(), + .RDADDRECC()); + + +// synthesis translate_on + +// XST black box declaration +// box_type "black_box" +// synthesis attribute box_type of dac_buf is "black_box" + +endmodule + diff --git a/verilog/sd2snes/ipcore_dir/dac_buf.xise b/verilog/sd2snes/ipcore_dir/dac_buf.xise new file mode 100644 index 0000000..7c8d125 --- /dev/null +++ b/verilog/sd2snes/ipcore_dir/dac_buf.xise @@ -0,0 +1,382 @@ + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/verilog/sd2snes/ipcore_dir/msu_databuf.v b/verilog/sd2snes/ipcore_dir/msu_databuf.v new file mode 100644 index 0000000..c2a0a23 --- /dev/null +++ b/verilog/sd2snes/ipcore_dir/msu_databuf.v @@ -0,0 +1,145 @@ +/******************************************************************************* +* This file is owned and controlled by Xilinx and must be used * +* solely for design, simulation, implementation and creation of * +* design files limited to Xilinx devices or technologies. Use * +* with non-Xilinx devices or technologies is expressly prohibited * +* and immediately terminates your license. * +* * +* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" * +* SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR * +* XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION * +* AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION * +* OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS * +* IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, * +* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE * +* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY * +* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE * +* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR * +* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF * +* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * +* FOR A PARTICULAR PURPOSE. * +* * +* Xilinx products are not intended for use in life support * +* appliances, devices, or systems. Use in such applications are * +* expressly prohibited. * +* * +* (c) Copyright 1995-2009 Xilinx, Inc. * +* All rights reserved. * +*******************************************************************************/ +// The synthesis directives "translate_off/translate_on" specified below are +// supported by Xilinx, Mentor Graphics and Synplicity synthesis +// tools. Ensure they are correct for your synthesis tool(s). + +// You must compile the wrapper file msu_databuf.v when simulating +// the core, msu_databuf. When compiling the wrapper file, be sure to +// reference the XilinxCoreLib Verilog simulation library. For detailed +// instructions, please refer to the "CORE Generator Help". + +`timescale 1ns/1ps + +module msu_databuf( + clka, + wea, + addra, + dina, + clkb, + addrb, + doutb); + + +input clka; +input [0 : 0] wea; +input [13 : 0] addra; +input [7 : 0] dina; +input clkb; +input [13 : 0] addrb; +output [7 : 0] doutb; + +// synthesis translate_off + + BLK_MEM_GEN_V4_3 #( + .C_ADDRA_WIDTH(14), + .C_ADDRB_WIDTH(14), + .C_ALGORITHM(1), + .C_BYTE_SIZE(9), + .C_COMMON_CLK(1), + .C_DEFAULT_DATA("0"), + .C_DISABLE_WARN_BHV_COLL(0), + .C_DISABLE_WARN_BHV_RANGE(0), + .C_FAMILY("spartan3"), + .C_HAS_ENA(0), + .C_HAS_ENB(0), + .C_HAS_INJECTERR(0), + .C_HAS_MEM_OUTPUT_REGS_A(0), + .C_HAS_MEM_OUTPUT_REGS_B(0), + .C_HAS_MUX_OUTPUT_REGS_A(0), + .C_HAS_MUX_OUTPUT_REGS_B(0), + .C_HAS_REGCEA(0), + .C_HAS_REGCEB(0), + .C_HAS_RSTA(0), + .C_HAS_RSTB(0), + .C_HAS_SOFTECC_INPUT_REGS_A(0), + .C_HAS_SOFTECC_OUTPUT_REGS_B(0), + .C_INITA_VAL("0"), + .C_INITB_VAL("0"), + .C_INIT_FILE_NAME("no_coe_file_loaded"), + .C_LOAD_INIT_FILE(0), + .C_MEM_TYPE(1), + .C_MUX_PIPELINE_STAGES(0), + .C_PRIM_TYPE(1), + .C_READ_DEPTH_A(16384), + .C_READ_DEPTH_B(16384), + .C_READ_WIDTH_A(8), + .C_READ_WIDTH_B(8), + .C_RSTRAM_A(0), + .C_RSTRAM_B(0), + .C_RST_PRIORITY_A("CE"), + .C_RST_PRIORITY_B("CE"), + .C_RST_TYPE("SYNC"), + .C_SIM_COLLISION_CHECK("ALL"), + .C_USE_BYTE_WEA(0), + .C_USE_BYTE_WEB(0), + .C_USE_DEFAULT_DATA(0), + .C_USE_ECC(0), + .C_USE_SOFTECC(0), + .C_WEA_WIDTH(1), + .C_WEB_WIDTH(1), + .C_WRITE_DEPTH_A(16384), + .C_WRITE_DEPTH_B(16384), + .C_WRITE_MODE_A("WRITE_FIRST"), + .C_WRITE_MODE_B("WRITE_FIRST"), + .C_WRITE_WIDTH_A(8), + .C_WRITE_WIDTH_B(8), + .C_XDEVICEFAMILY("spartan3")) + inst ( + .CLKA(clka), + .WEA(wea), + .ADDRA(addra), + .DINA(dina), + .CLKB(clkb), + .ADDRB(addrb), + .DOUTB(doutb), + .RSTA(), + .ENA(), + .REGCEA(), + .DOUTA(), + .RSTB(), + .ENB(), + .REGCEB(), + .WEB(), + .DINB(), + .INJECTSBITERR(), + .INJECTDBITERR(), + .SBITERR(), + .DBITERR(), + .RDADDRECC()); + + +// synthesis translate_on + +// XST black box declaration +// box_type "black_box" +// synthesis attribute box_type of msu_databuf is "black_box" + +endmodule + diff --git a/verilog/sd2snes/ipcore_dir/msu_databuf.xise b/verilog/sd2snes/ipcore_dir/msu_databuf.xise new file mode 100644 index 0000000..39ae055 --- /dev/null +++ b/verilog/sd2snes/ipcore_dir/msu_databuf.xise @@ -0,0 +1,79 @@ + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/verilog/sd2snes/main.v b/verilog/sd2snes/main.v index 4df4f09..fac4ee3 100644 --- a/verilog/sd2snes/main.v +++ b/verilog/sd2snes/main.v @@ -79,6 +79,22 @@ wire [3:0] MAPPER; wire [23:0] SAVERAM_MASK; wire [23:0] ROM_MASK; wire [7:0] SD_DMA_SRAM_DATA; +wire [1:0] SD_DMA_TGT; +wire [10:0] SD_DMA_PARTIAL_START; +wire [10:0] SD_DMA_PARTIAL_END; + +wire [10:0] dac_addr; +//wire [7:0] dac_volume; +wire [7:0] msu_volumerq_out; +wire [6:0] msu_status_out; +wire [31:0] msu_addressrq_out; +wire [15:0] msu_trackrq_out; +wire [13:0] msu_addr; +wire [7:0] MSU_SNES_DATA_IN; +wire [7:0] MSU_SNES_DATA_OUT; +wire [5:0] msu_status_reset_bits; +wire [5:0] msu_status_set_bits; + //wire SD_DMA_EN; //SPI_DMA_CTRL; sd_dma snes_sd_dma(.CLK(CLK2), @@ -88,15 +104,48 @@ sd_dma snes_sd_dma(.CLK(CLK2), .SD_DMA_STATUS(SD_DMA_STATUS), .SD_DMA_SRAM_WE(SD_DMA_SRAM_WE), .SD_DMA_SRAM_DATA(SD_DMA_SRAM_DATA), - .SD_DMA_NEXTADDR(SD_DMA_NEXTADDR) + .SD_DMA_NEXTADDR(SD_DMA_NEXTADDR), + .SD_DMA_TGT(SD_DMA_TGT), + .SD_DMA_PARTIAL(SD_DMA_PARTIAL), + .SD_DMA_PARTIAL_START(SD_DMA_PARTIAL_START), + .SD_DMA_PARTIAL_END(SD_DMA_PARTIAL_END) ); dac_test snes_dac_test(.clkin(CLK2), .mclk(DAC_MCLK), .lrck(DAC_LRCK), - .sdout(DAC_SDOUT) + .sdout(DAC_SDOUT), + .we(SD_DMA_TGT==2'b01 ? SD_DMA_SRAM_WE : 1'b1), + .pgm_address(dac_addr), + .pgm_data(SD_DMA_SRAM_DATA), + .DAC_STATUS(DAC_STATUS), + .volume(msu_volumerq_out), + .vol_latch(msu_volume_latch_out), + .play(dac_play), + .reset(dac_reset) ); - + +msu snes_msu ( + .clkin(CLK2), + .enable(msu_enable), + .pgm_address(msu_addr), + .pgm_data(SD_DMA_SRAM_DATA), + .pgm_we(SD_DMA_TGT==2'b10 ? SD_DMA_SRAM_WE : 1'b1), + .reg_addr(SNES_ADDR), + .reg_data_in(MSU_SNES_DATA_IN), + .reg_data_out(MSU_SNES_DATA_OUT), + .reg_oe(SNES_READ), + .reg_we(SNES_WRITE), + .status_out(msu_status_out), + .volume_out(msu_volumerq_out), + .volume_latch_out(msu_volume_latch_out), + .addr_out(msu_addressrq_out), + .track_out(msu_trackrq_out), + .status_reset_bits(msu_status_reset_bits), + .status_set_bits(msu_status_set_bits), + .status_reset_we(msu_status_reset_we) + ); + spi snes_spi(.clk(CLK2), .MOSI(SPI_MOSI), .MISO(SPI_MISO), @@ -137,7 +186,25 @@ mcu_cmd snes_mcu_cmd( .SD_DMA_STATUS(SD_DMA_STATUS), .SD_DMA_NEXTADDR(SD_DMA_NEXTADDR), .SD_DMA_SRAM_DATA(SD_DMA_SRAM_DATA), - .SD_DMA_SRAM_WE(SD_DMA_SRAM_WE) + .SD_DMA_SRAM_WE(SD_DMA_SRAM_WE), + .SD_DMA_TGT(SD_DMA_TGT), + .SD_DMA_PARTIAL(SD_DMA_PARTIAL), + .SD_DMA_PARTIAL_START(SD_DMA_PARTIAL_START), + .SD_DMA_PARTIAL_END(SD_DMA_PARTIAL_END), + .dac_addr_out(dac_addr), + .DAC_STATUS(DAC_STATUS), +// .dac_volume_out(dac_volume), +// .dac_volume_latch_out(dac_vol_latch), + .dac_play_out(dac_play), + .dac_reset_out(dac_reset), + .msu_addr_out(msu_addr), + .MSU_STATUS(msu_status_out), + .msu_status_reset_out(msu_status_reset_bits), + .msu_status_set_out(msu_status_set_bits), + .msu_status_reset_we(msu_status_reset_we), + .msu_volumerq(msu_volumerq_out), + .msu_addressrq(msu_addressrq_out), + .msu_trackrq(msu_trackrq_out) ); // dcm1: dfs 4x @@ -238,7 +305,10 @@ address snes_addr( .MCU_ADDR(MCU_ADDR), .ROM_ADDR0(ROM_ADDR0), .SAVERAM_MASK(SAVERAM_MASK), - .ROM_MASK(ROM_MASK) + .ROM_MASK(ROM_MASK), + //MSU-1 + .use_msu(use_msu), + .msu_enable(msu_enable) ); wire SNES_READ_CYCLEw; @@ -261,7 +331,10 @@ data snes_data(.CLK(CLK2), .MCU_OVR(MCU_OVR), .MCU_IN_DATA(MCU_IN_DATA), .MCU_OUT_DATA(MCU_OUT_DATA), - .ROM_ADDR0(ROM_ADDR0) + .ROM_ADDR0(ROM_ADDR0), + .MSU_DATA_IN(MSU_SNES_DATA_IN), + .MSU_DATA_OUT(MSU_SNES_DATA_OUT), + .msu_enable(msu_enable) ); parameter MODE_SNES = 1'b0; @@ -497,7 +570,7 @@ assign ROM_BLE = !ROM_WE ? !ROM_ADDR0 : 1'b0; //assign SRAM_WE = !MCU_ENA ? MCU_WRITE : 1'b1; //assign SNES_DATABUS_OE = (!IS_SAVERAM & SNES_CS) | (SNES_READ & SNES_WRITE); -assign SNES_DATABUS_OE = (IS_ROM & SNES_CS) | (!IS_ROM & !IS_SAVERAM) | (SNES_READ & SNES_WRITE); +assign SNES_DATABUS_OE = msu_enable ? 1'b0 : ((IS_ROM & SNES_CS) | (!IS_ROM & !IS_SAVERAM) | (SNES_READ & SNES_WRITE)); assign SNES_DATABUS_DIR = !SNES_READ ? 1'b1 : 1'b0; assign SNES_DATA_TO_MEM = SNES_DATA_TO_MEM_ARRAY[SNES_WRITE_CYCLE][STATEIDX]; diff --git a/verilog/sd2snes/msu.v b/verilog/sd2snes/msu.v new file mode 100644 index 0000000..26a2eab --- /dev/null +++ b/verilog/sd2snes/msu.v @@ -0,0 +1,174 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 14:55:04 12/14/2010 +// Design Name: +// Module Name: msu +// Project Name: +// Target Devices: +// Tool versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// +module msu( + input clkin, + input enable, + input [13:0] pgm_address, + input [7:0] pgm_data, + input pgm_we, + input [2:0] reg_addr, + input [7:0] reg_data_in, + output [7:0] reg_data_out, + input reg_oe, + input reg_we, + output [6:0] status_out, + output [7:0] volume_out, + output volume_latch_out, + output [31:0] addr_out, + output [15:0] track_out, + input [5:0] status_reset_bits, + input [5:0] status_set_bits, + input status_reset_we + ); + +reg [1:0] status_reset_we_r; +always @(posedge clkin) status_reset_we_r = {status_reset_we_r[0], status_reset_we}; +wire status_reset_en = (status_reset_we_r == 2'b01); + +reg [13:0] msu_address_r; +wire [13:0] msu_address = msu_address_r; + +wire [7:0] msu_data; +reg [7:0] msu_data_r; + +reg [5:0] reg_oe_sreg; +always @(posedge clkin) reg_oe_sreg <= {reg_oe_sreg[4:0], reg_oe}; +wire reg_oe_falling = (reg_oe_sreg[5:0] == 6'b111110); +wire reg_oe_rising = (reg_oe_sreg[5:0] == 6'b000001); + +reg [1:0] reg_we_sreg; +always @(posedge clkin) reg_we_sreg <= {reg_we_sreg[0], reg_we}; +wire reg_we_rising = (reg_we_sreg[1:0] == 2'b01); + +reg [31:0] addr_out_r; +assign addr_out = addr_out_r; + +reg [15:0] track_out_r; +assign track_out = track_out_r; + +reg [7:0] volume_r; +assign volume_out = volume_r; + +reg volume_start_r; +assign volume_latch_out = volume_start_r; + +reg audio_start_r; +reg audio_busy_r; +reg data_start_r; +reg data_busy_r; +reg ctrl_start_r; +reg [1:0] audio_ctrl_r; +reg [1:0] audio_status_r; + +initial begin + audio_busy_r <= 1'b1; + data_busy_r <= 1'b1; +end + +assign status_out = {msu_address_r[13], + audio_start_r, data_start_r, volume_start_r, audio_ctrl_r, ctrl_start_r}; + +initial msu_address_r = 14'h0000; + +msu_databuf snes_msu_databuf ( + .clka(clkin), + .wea(~pgm_we), // Bus [0 : 0] + .addra(pgm_address), // Bus [13 : 0] + .dina(pgm_data), // Bus [7 : 0] + .clkb(clkin), + .addrb(msu_address), // Bus [13 : 0] + .doutb(msu_data)); // Bus [7 : 0] + +reg [7:0] msu_regs [7:0]; + +reg [7:0] data_out_r; +reg [7:0] data_in_r; +assign reg_data_out = data_out_r; +always @(posedge clkin) data_in_r <= reg_data_in; + +always @(posedge clkin) begin + case(reg_addr) + 3'h0: data_out_r <= {data_busy_r, audio_busy_r, audio_status_r, 4'b0001}; + 3'h1: data_out_r <= msu_data_r; + 3'h2: data_out_r <= 8'h53; + 3'h3: data_out_r <= 8'h2d; + 3'h4: data_out_r <= 8'h4d; + 3'h5: data_out_r <= 8'h53; + 3'h6: data_out_r <= 8'h55; + 3'h7: data_out_r <= 8'h31; + endcase +end + +always @(posedge clkin) begin + if(reg_we_rising && enable) begin + case(reg_addr) + 3'h0: addr_out_r[7:0] <= reg_data_in; + 3'h1: addr_out_r[15:8] <= reg_data_in; + 3'h2: addr_out_r[23:16] <= reg_data_in; + 3'h3: begin + addr_out_r[31:24] <= reg_data_in; + data_start_r <= 1'b1; + data_busy_r <= 1'b1; + end + 3'h4: begin + track_out_r[7:0] <= reg_data_in; + end + 3'h5: begin + track_out_r[15:8] <= reg_data_in; + audio_start_r <= 1'b1; + audio_busy_r <= 1'b1; + end + 3'h6: begin + volume_r <= reg_data_in; + volume_start_r <= 1'b1; + end + 3'h7: begin + if(!audio_busy_r) begin + audio_ctrl_r <= reg_data_in[1:0]; + ctrl_start_r <= 1'b1; + end + end + endcase + end else if (status_reset_en) begin + audio_busy_r <= (audio_busy_r | status_set_bits[5]) & ~status_reset_bits[5]; + if(status_reset_bits[5]) audio_start_r <= 1'b0; + + data_busy_r <= (data_busy_r | status_set_bits[4]) & ~status_reset_bits[4]; + if(status_reset_bits[4]) data_start_r <= 1'b0; + +// volume_start_r <= (volume_start_r | status_set_bits[3]) & ~status_reset_bits[3]; + + audio_status_r <= (audio_status_r | status_set_bits[2:1]) & ~status_reset_bits[2:1]; + + ctrl_start_r <= (ctrl_start_r | status_set_bits[0]) & ~status_reset_bits[0]; + end else begin + volume_start_r <= 1'b0; + end +end + +always @(posedge clkin) begin + if(reg_oe_falling && enable && reg_addr == 3'h1) begin + msu_address_r <= msu_address_r + 1; + msu_data_r <= msu_data; + end +end + +endmodule diff --git a/verilog/sd2snes/sd2snes.xise b/verilog/sd2snes/sd2snes.xise index dae01e0..c777896 100644 --- a/verilog/sd2snes/sd2snes.xise +++ b/verilog/sd2snes/sd2snes.xise @@ -50,6 +50,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/verilog/sd2snes/sd_dma.v b/verilog/sd2snes/sd_dma.v index 3e8b4bc..0f0397a 100644 --- a/verilog/sd2snes/sd_dma.v +++ b/verilog/sd2snes/sd_dma.v @@ -23,12 +23,21 @@ module sd_dma( inout SD_CLK, input CLK, input SD_DMA_EN, + input SD_DMA_TGT, output SD_DMA_STATUS, output SD_DMA_SRAM_WE, output SD_DMA_NEXTADDR, - output [7:0] SD_DMA_SRAM_DATA + output [7:0] SD_DMA_SRAM_DATA, + input SD_DMA_PARTIAL, + input [10:0] SD_DMA_PARTIAL_START, + input [10:0] SD_DMA_PARTIAL_END ); +reg [10:0] SD_DMA_STARTr; +reg [10:0] SD_DMA_ENDr; +reg SD_DMA_PARTIALr; +always @(posedge CLK) SD_DMA_PARTIALr <= SD_DMA_PARTIAL; + reg SD_DMA_DONEr; reg[2:0] SD_DMA_DONEr2; initial begin @@ -36,7 +45,7 @@ initial begin SD_DMA_DONEr = 1'b0; end always @(posedge CLK) SD_DMA_DONEr2 <= {SD_DMA_DONEr2[1:0], SD_DMA_DONEr}; -wire SD_DMA_DONE_rising = (SD_DMA_DONEr2 == 2'b01); +wire SD_DMA_DONE_rising = (SD_DMA_DONEr2[1:0] == 2'b01); reg [2:0] SD_DMA_ENr; initial SD_DMA_ENr = 3'b000; @@ -67,7 +76,11 @@ always @(posedge CLK) SD_CLKr <= clkcnt[1]; assign SD_CLK = SD_DMA_STATUSr ? SD_CLKr : 1'bZ; always @(posedge CLK) begin - if(SD_DMA_EN_rising) SD_DMA_STATUSr <= 1'b1; + if(SD_DMA_EN_rising) begin + SD_DMA_STATUSr <= 1'b1; + SD_DMA_STARTr <= (SD_DMA_PARTIALr ? SD_DMA_PARTIAL_START : 11'h0); + SD_DMA_ENDr <= (SD_DMA_PARTIALr ? SD_DMA_PARTIAL_END : 11'd1024); + end else if (SD_DMA_DONE_rising) SD_DMA_STATUSr <= 1'b0; end @@ -77,7 +90,7 @@ always @(posedge CLK) begin end always @(posedge CLK) begin - if(SD_DMA_EN_rising) begin + if(SD_DMA_EN_rising || !SD_DMA_STATUSr) begin clkcnt <= 0; end else begin if(SD_DMA_STATUSr) begin @@ -87,7 +100,7 @@ always @(posedge CLK) begin end always @(posedge CLK) begin - if(SD_DMA_EN_rising) cyclecnt <= 0; + if(SD_DMA_EN_rising || !SD_DMA_STATUSr) cyclecnt <= 0; else if(clkcnt[1:0] == 2'b11) cyclecnt <= cyclecnt + 1; end @@ -99,13 +112,13 @@ always @(posedge CLK) begin 3'h0: begin SD_DMA_SRAM_WEr <= 1'b1; SD_DMA_SRAM_DATAr[7:4] <= SD_DAT; - if(cyclecnt>0 && cyclecnt < 1025) SD_DMA_NEXTADDRr <= 1'b1; + if(cyclecnt>SD_DMA_STARTr && cyclecnt <= SD_DMA_ENDr) SD_DMA_NEXTADDRr <= 1'b1; end 3'h1: SD_DMA_NEXTADDRr <= 1'b0; // 3'h2: 3'h3: - SD_DMA_SRAM_WEr <= 1'b0; + if(cyclecnt>=SD_DMA_STARTr && cyclecnt <= SD_DMA_ENDr) SD_DMA_SRAM_WEr <= 1'b0; 3'h4: SD_DMA_SRAM_DATAr[3:0] <= SD_DAT; // 3'h5: