diff --git a/src/diskio.h b/src/diskio.h index f9fb70c..e2e8f2b 100644 --- a/src/diskio.h +++ b/src/diskio.h @@ -80,6 +80,8 @@ DRESULT disk_getinfo(BYTE drv, BYTE page, void *buffer); void disk_init(void); +uint8_t SD_SPI_OFFLOAD; + /* Will be set to DISK_ERROR if any access on the card fails */ enum diskstates { DISK_CHANGED = 0, DISK_REMOVED, DISK_OK, DISK_ERROR }; diff --git a/src/ff.c b/src/ff.c index 432b640..48d8ec1 100644 --- a/src/ff.c +++ b/src/ff.c @@ -60,6 +60,7 @@ #include "ff.h" /* FatFs declarations */ #include "diskio.h" /* Include file for user provided disk functions */ #include "uart.h" +#include "fpga.h" /*-------------------------------------------------------------------------- @@ -1603,8 +1604,12 @@ FRESULT f_read ( cc = btr / SS(fs); /* When left bytes >= SS(fs), */ if (cc) { /* Read maximum contiguous sectors directly */ if (cc > fp->csect) cc = fp->csect; + if(SPI_OFFLOAD) { + SD_SPI_OFFLOAD = 1; + } if (disk_read(fs->drive, rbuff, sect, (BYTE)cc) != RES_OK) goto fr_error; + SD_SPI_OFFLOAD = 0; fp->csect -= (BYTE)(cc - 1); fp->curr_sect += cc - 1; rcnt = cc * SS(fs); @@ -1619,10 +1624,13 @@ FRESULT f_read ( } } + SPI_OFFLOAD = 0; return FR_OK; fr_error: /* Abort this file due to an unrecoverable error */ fp->flag |= FA__ERROR; + SPI_OFFLOAD = 0; + SD_SPI_OFFLOAD = 0; return FR_RW_ERROR; } diff --git a/src/fpga.c b/src/fpga.c index 40453b0..8566508 100644 --- a/src/fpga.c +++ b/src/fpga.c @@ -55,6 +55,10 @@ void fpga_init() { DDRD |= _BV(PD3) | _BV(PD4); // PD3, PD4 are outputs DDRA = ~_BV(PA3); // PA3 is input <- DONE + + DDRB |= _BV(PB2); // DMA_CTRL preinit + PORTB |= _BV(PB2); + SPI_OFFLOAD=0; set_cclk(0); // initial clk=0 } @@ -64,7 +68,7 @@ int fpga_get_done(void) { void fpga_postinit() { DDRA |= _BV(PA0) | _BV(PA1) | _BV(PA2) | _BV(PA4) | _BV(PA5) | _BV(PA6); // MAPPER+NEXTADDR output - DDRB |= _BV(PB2) | _BV(PB1) | _BV(PB0); // turn PB2 into output, enable AVR_BANK + DDRB |= _BV(PB1) | _BV(PB0); // turn PB2 into output, enable AVR_BANK DDRD |= _BV(PD7); // turn PD7 into output } diff --git a/src/fpga.h b/src/fpga.h index bd2bb14..c904532 100644 --- a/src/fpga.h +++ b/src/fpga.h @@ -20,6 +20,7 @@ void set_avr_addr_en(uint8_t val); void set_avr_mapper(uint8_t val); void set_avr_bank(uint8_t val); +uint8_t SPI_OFFLOAD; #define FPGA_TEST_TOKEN (0xa5) diff --git a/src/main.c b/src/main.c index 63ccbee..7170b0b 100644 --- a/src/main.c +++ b/src/main.c @@ -48,6 +48,7 @@ #include "spi.h" #include "avrcompat.h" #include "filetypes.h" +#include "sdcard.h" void writetest(void) { // HERE BE LIONS, GET IN THE CAR @@ -116,12 +117,6 @@ void poison_memory(void) { } #endif -void avr_goto_addr(const uint32_t val) { - AVR_ADDR_RESET(); - for(uint32_t i=0; i 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1) int main(void) __attribute__((OS_main)); #endif @@ -189,7 +184,41 @@ restart: uint16_t mem_dir_id = sram_readshort(SRAM_DIRID); uint32_t mem_magic = sram_readlong(SRAM_SCRATCHPAD); - + while(0) { + SD_SPI_OFFLOAD=1; + sd_read(0, file_buf, 32L, 1); +// sram_writeblock((void*)file_buf, 0, 0x200); + sram_hexdump(0,0x10); + uart_putc('+'); + } +/* here be strange monsters */ + while(0){ +// uint16_t hurdur1 = 0, hurdur2 = 0; + spiTransferByte(0x00); + spiTransferByte(0x00); + spiTransferByte(0x00); + spiTransferByte(0x00); + spiTransferByte(0x00); + spiTransferByte(0x00); + spiTransferByte(0x00); + spiTransferByte(0x00); + spiTransferByte(0x00); + spiTransferByte(0x00); + spiTransferByte(0x00); + spiTransferByte(0x00); + spiTransferByte(0x00); + PORTB |= _BV(PB2); + DDRB |= _BV(PB2); + PORTB &= ~_BV(PB2); + DDRB &= ~_BV(PB7); // tristate SCK + PORTB |= _BV(PB2); + DDRB &= ~_BV(PB2); + while(!(PINB & _BV(PB2))) { + } + DDRB |= _BV(PB7); + _delay_ms(1); +// dprintf("hurdur1=%d hurdur2=%d\n", hurdur1, hurdur2); +} if((mem_magic != 0x12345678) || (mem_dir_id != saved_dir_id)) { uint16_t curr_dir_id = scan_dir(fs_path, 0, 0); // generate files footprint dprintf("curr dir id = %x\n", curr_dir_id); @@ -207,7 +236,7 @@ restart: save_sram((uint8_t*)"/sd2snes/sd2snes.db", endaddr-SRAM_DB_ADDR, SRAM_DB_ADDR); save_sram((uint8_t*)"/sd2snes/sd2snes.dir", direndaddr-(SRAM_DIR_ADDR), SRAM_DIR_ADDR); dprintf("done\n"); - sram_hexdump(SRAM_DB_ADDR, 0x400); +// sram_hexdump(SRAM_DB_ADDR, 0x400); } else { dprintf("saved dir id = %x\n", saved_dir_id); dprintf("different card, consistent db, loading db...\n"); @@ -229,10 +258,14 @@ restart: led_pwm(); +// sram_hexdump(0, 0x200); uart_putc('('); load_rom((uint8_t*)"/sd2snes/menu.bin"); set_rom_mask(0x3fffff); // force mirroring off uart_putc(')'); + uart_putcrlf(); +// sram_hexdump(0, 0x200); +// save_sram((uint8_t*)"/sd2snes/dump", 65536, 0); sram_writebyte(0, SRAM_CMD_ADDR); @@ -256,6 +289,7 @@ restart: set_avr_ena(0); dprintf("Selected name: %s\n", file_lfn); load_rom(file_lfn); +// save_sram((uint8_t*)"/sd2snes/test.smc", romprops.romsize_bytes, 0); if(romprops.ramsize_bytes) { strcpy(strrchr((char*)file_lfn, (int)'.'), ".srm"); dprintf("SRM file: %s\n", file_lfn); @@ -281,7 +315,6 @@ restart: uint8_t snes_reset_prev=0, snes_reset_now=0, snes_reset_state=0; uint16_t reset_count=0; while(fpga_test() == FPGA_TEST_TOKEN) { - dprintf("%02X\n", fpga_test()); snes_reset_now=get_snes_reset(); if(snes_reset_now) { if(!snes_reset_prev) { diff --git a/src/memory.c b/src/memory.c index d4ddd3a..5132836 100644 --- a/src/memory.c +++ b/src/memory.c @@ -124,7 +124,7 @@ void sram_writeblock(void* buf, uint32_t addr, uint16_t size) { } uint32_t load_rom(uint8_t* filename) { - uint8_t dummy; +// uint8_t dummy; set_avr_bank(0); UINT bytes_read; DWORD filesize; @@ -132,18 +132,25 @@ uint32_t load_rom(uint8_t* filename) { file_open(filename, FA_READ); filesize = file_handle.fsize; smc_id(&romprops); + dprintf("no nervous breakdown beyond this point! or else!\n"); if(file_res) { uart_putc('?'); uart_putc(0x30+file_res); return 0; } f_lseek(&file_handle, romprops.offset); + spi_none(); for(;;) { + SPI_OFFLOAD=1; spi_none(); bytes_read = file_read(); - spi_none(); if (file_res || !bytes_read) break; - spi_fpga(); + if(!(count++ % 8)) { +// toggle_busy_led(); + bounce_busy_led(); + uart_putc('.'); + } +/* spi_fpga(); spiTransferByte(0x91); // write w/ increment if(!(count++ % 8)) { // toggle_busy_led(); @@ -156,7 +163,7 @@ uint32_t load_rom(uint8_t* filename) { loop_until_bit_is_set(SPSR, SPIF); dummy = SPDR; } - spiTransferByte(0x00); // dummy tx for increment+write pulse + spiTransferByte(0x00); // dummy tx for increment+write pulse */ } file_close(); spi_none(); diff --git a/src/sdcard.c b/src/sdcard.c index 61b39ac..1fe6750 100644 --- a/src/sdcard.c +++ b/src/sdcard.c @@ -60,6 +60,7 @@ #include #include #include +#include #include "config.h" #include "avrcompat.h" #include "crc7.h" @@ -308,6 +309,8 @@ static void sdInit(const uint8_t card) { uint8_t i; uint16_t counter; + SD_SPI_OFFLOAD = 0; + counter = 0xffff; do { // Prepare for ACMD, send CMD55: APP_CMD @@ -557,24 +560,46 @@ DRESULT sd_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count) { // Get data crc = 0; - // Initiate data exchange over SPI - SPDR = 0xff; - for (i=0; i<512; i++) { - // Wait until data has been received - loop_until_bit_is_set(SPSR, SPIF); - tmp = SPDR; - // Transmit the next byte while we store the current one + if(SD_SPI_OFFLOAD) { +// uart_putc('O'); + PORTB |= _BV(PB2); + DDRB |= _BV(PB2); + PORTB &= ~_BV(PB2); + PORTB |= _BV(PB2); + PORTB &= ~_BV(PB7); + DDRB &= ~_BV(PB7); // tristate SCK +// SPCR=0; + DDRB &= ~_BV(PB2); + _delay_us(1); + loop_until_bit_is_set(PINB, PB2); + DDRB |= _BV(PB2); +// SPCR=0b01010000; + SD_SPI_OFFLOAD = 0; + deselectCard(drv); + DDRB |= _BV(PB7); + return RES_OK; SPDR = 0xff; - - *(buffer++) = tmp; + } else { + // Initiate data exchange over SPI + SPDR = 0xff; + + for (i=0; i<512; i++) { + // Wait until data has been received + loop_until_bit_is_set(SPSR, SPIF); + tmp = SPDR; + // Transmit the next byte while we store the current one + SPDR = 0xff; + + *(buffer++) = tmp; #ifdef CONFIG_SD_DATACRC - crc = _crc_xmodem_update(crc, tmp); + crc = _crc_xmodem_update(crc, tmp); #endif + } } // Wait until the first CRC byte is received loop_until_bit_is_set(SPSR, SPIF); - + // Check CRC recvcrc = (SPDR << 8) + spiTransferByte(0xff); #ifdef CONFIG_SD_DATACRC @@ -586,7 +611,6 @@ DRESULT sd_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count) { continue; } #endif - break; } deselectCard(drv); diff --git a/verilog/sd2snes/avr_cmd.v b/verilog/sd2snes/avr_cmd.v index 2466f0b..f5c087c 100644 --- a/verilog/sd2snes/avr_cmd.v +++ b/verilog/sd2snes/avr_cmd.v @@ -38,7 +38,13 @@ module avr_cmd( input endmessage, input startmessage, output [23:0] saveram_mask_out, - output [23:0] rom_mask_out + output [23:0] rom_mask_out, + + // SPI "DMA" extension + input spi_dma_ovr, + input spi_dma_nextaddr, + input [7:0] spi_dma_sram_data, + input spi_dma_sram_we ); reg [3:0] MAPPER_BUF; @@ -50,6 +56,8 @@ reg [7:0] AVR_DATA_OUT_BUF; reg [7:0] AVR_DATA_IN_BUF; reg [1:0] avr_nextaddr_buf; wire avr_nextaddr; +wire spi_dma_nextaddr_trig; +reg [2:0] spi_dma_nextaddr_r; reg [1:0] SRAM_MASK_IDX; reg [23:0] SAVERAM_MASK; @@ -59,17 +67,15 @@ assign spi_data_out = AVR_DATA_IN_BUF; initial begin ADDR_OUT_BUF = 0; + spi_dma_nextaddr_r = 0; end +// command interpretation always @(posedge clk) begin if (cmd_ready) begin case (cmd_data[7:4]) 4'h3: MAPPER_BUF <= cmd_data[3:0]; -// 4'h8: -// AVR_DATA_IN_BUF <= avr_data_in; -// 4'hF: -// TODO AVR_DATA_IN_BUF <= 8'hA5; endcase end else if (param_ready) begin case (cmd_data[7:4]) @@ -102,16 +108,15 @@ always @(posedge clk) begin 32'h4: SAVERAM_MASK[7:0] <= param_data; endcase -// 4'h8: -// AVR_DATA_IN_BUF <= avr_data_in; 4'h9: AVR_DATA_OUT_BUF <= param_data; endcase end - if (avr_nextaddr & (cmd_data[7:5] == 3'h4) && (cmd_data[0]) && (spi_byte_cnt > (32'h1+cmd_data[4]))) + if (spi_dma_nextaddr_trig | (avr_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; end +// value fetch during last SPI bit always @(posedge clk) begin if (spi_bit_cnt == 3'h7) if (cmd_data[7:4] == 4'hF) @@ -120,6 +125,7 @@ always @(posedge clk) begin AVR_DATA_IN_BUF <= avr_data_in; end +// nextaddr pulse generation always @(posedge clk) begin if (spi_bit_cnt == 3'h0) avr_nextaddr_buf <= {avr_nextaddr_buf[0], 1'b1}; @@ -127,23 +133,33 @@ always @(posedge clk) begin avr_nextaddr_buf <= {avr_nextaddr_buf[0], 1'b0}; end +assign spi_dma_nextaddr_trig = (spi_dma_nextaddr_r[2:1] == 2'b01); +always @(posedge clk) begin + spi_dma_nextaddr_r <= {spi_dma_nextaddr_r[1:0], spi_dma_nextaddr}; +end + +// r/w pulse always @(posedge clk) begin if ((spi_bit_cnt == 3'h1) & (cmd_data[7:4] == 4'h9) & (spi_byte_cnt > 32'h1)) AVR_WRITE_BUF <= 1'b0; else AVR_WRITE_BUF <= 1'b1; +// Read pulse is two spi cycles to ensure that the value +// is ready in the 2nd cycle in AVR master mode if ((spi_bit_cnt == 3'h6 || spi_bit_cnt == 3'h7) & (cmd_data[7:4] == 4'h8) & (spi_byte_cnt > 32'h0)) AVR_READ_BUF <= 1'b0; else AVR_READ_BUF <= 1'b1; end +// trigger for nextaddr assign avr_nextaddr = avr_nextaddr_buf == 2'b01; + assign avr_read = AVR_READ_BUF; -assign avr_write = AVR_WRITE_BUF; +assign avr_write = spi_dma_ovr ? spi_dma_sram_we : AVR_WRITE_BUF; assign addr_out = ADDR_OUT_BUF; -assign avr_data_out = AVR_DATA_OUT_BUF; +assign avr_data_out = spi_dma_ovr ? spi_dma_sram_data : AVR_DATA_OUT_BUF; assign avr_mapper = MAPPER_BUF; assign avr_sram_size = SRAM_SIZE_BUF; assign rom_mask_out = ROM_MASK; diff --git a/verilog/sd2snes/main.ucf b/verilog/sd2snes/main.ucf index 33a6d9f..078349d 100644 --- a/verilog/sd2snes/main.ucf +++ b/verilog/sd2snes/main.ucf @@ -40,7 +40,6 @@ NET "SNES_CPU_CLK" IOSTANDARD = LVCMOS33; NET "SNES_REFRESH" IOSTANDARD = LVCMOS33; NET "SPI_MISO" IOSTANDARD = LVCMOS33; NET "SPI_MOSI" IOSTANDARD = LVCMOS33; -NET "SPI_SCK" IOSTANDARD = LVCMOS33; NET "AVR_ENA" LOC = P58; NET "CLKIN" LOC = P125; NET "IRQ_DIR" LOC = P40; @@ -187,5 +186,7 @@ NET "SRAM_DATA[8]" IOSTANDARD = LVCMOS33; NET "SRAM_DATA[9]" IOSTANDARD = LVCMOS33; NET "SRAM_OE" IOSTANDARD = LVCMOS33; NET "SRAM_WE" IOSTANDARD = LVCMOS33; -TEMPERATURE = 60 C; -VOLTAGE = 1.25 V; +NET "SPI_DMA_CTRL" LOC = P41; +NET "SPI_DMA_CTRL" IOSTANDARD = LVCMOS33; +NET "SPI_SCK" IOSTANDARD = LVCMOS33; +NET "SPI_SCK" PULLDOWN; diff --git a/verilog/sd2snes/main.v b/verilog/sd2snes/main.v index d23c39b..56f317d 100644 --- a/verilog/sd2snes/main.v +++ b/verilog/sd2snes/main.v @@ -46,10 +46,11 @@ module main( /* AVR signals */ input SPI_MOSI, - output SPI_MISO, + inout SPI_MISO, input SPI_SS, - input SPI_SCK, - input AVR_ENA + inout SPI_SCK, + input AVR_ENA, + inout SPI_DMA_CTRL /* debug */ //output DCM_IN_STOPPED, @@ -69,13 +70,15 @@ wire [7:0] AVR_OUT_DATA; wire [3:0] MAPPER; wire [23:0] SAVERAM_MASK; wire [23:0] ROM_MASK; +wire [23:0] spi_dma_addr; +wire [7:0] spi_dma_sram_data; +wire spi_dma_trig = SPI_DMA_CTRL; spi snes_spi(.clk(CLK2), .MOSI(SPI_MOSI), .MISO(SPI_MISO), .SSEL(SPI_SS), .SCK(SPI_SCK), - .LED(SPI_LSB), .cmd_ready(spi_cmd_ready), .param_ready(spi_param_ready), .cmd_data(spi_cmd_data), @@ -84,7 +87,10 @@ spi snes_spi(.clk(CLK2), .startmessage(spi_startmessage), .input_data(spi_input_data), .byte_cnt(spi_byte_cnt), - .bit_cnt(spi_bit_cnt) + .bit_cnt(spi_bit_cnt), + + .spi_dma_sck(spi_dma_sck), + .spi_dma_ovr(spi_dma_ovr) ); avr_cmd snes_avr_cmd( @@ -106,10 +112,27 @@ avr_cmd snes_avr_cmd( .endmessage(spi_endmessage), .startmessage(spi_startmessage), .saveram_mask_out(SAVERAM_MASK), - .rom_mask_out(ROM_MASK) + .rom_mask_out(ROM_MASK), + + .spi_dma_ovr(spi_dma_ovr), + .spi_dma_nextaddr(spi_dma_nextaddr), + .spi_dma_sram_data(spi_dma_sram_data), + .spi_dma_sram_we(spi_dma_sram_we) ); -//wire [7:0] DCM_STATUS; +spi_dma snes_spi_dma( + .clk(CLK2), + .spi_dma_ovr(spi_dma_ovr), // to spi, avr_cmd + .spi_dma_miso(SPI_MISO), // to spi + .spi_dma_sck(spi_dma_sck), // to spi + .spi_dma_trig(spi_dma_trig), // from avr + .spi_dma_nextaddr(spi_dma_nextaddr), // to avr_cmd? + .spi_dma_sram_data(spi_dma_sram_data), // to avr_cmd? + .spi_dma_sram_we(spi_dma_sram_we), // to avr_cmd? + .spi_dma_done(spi_dma_done) // to avr +); + +assign SPI_DMA_CTRL = spi_dma_ovr ? 1'b0 : 1'bZ; // dcm1: dfs 4x my_dcm snes_dcm(.CLKIN(CLKIN), diff --git a/verilog/sd2snes/main_tf2.v b/verilog/sd2snes/main_tf2.v index 7a48010..9f4b4e5 100644 --- a/verilog/sd2snes/main_tf2.v +++ b/verilog/sd2snes/main_tf2.v @@ -46,7 +46,6 @@ module main_tf2; wire SRAM_WE; wire SPI_MISO; wire MODE; - wire SPI_LSB; wire SRAM_BHE; wire SRAM_BLE; diff --git a/verilog/sd2snes/sd2snes.xise b/verilog/sd2snes/sd2snes.xise index 975f83b..48c1616 100644 --- a/verilog/sd2snes/sd2snes.xise +++ b/verilog/sd2snes/sd2snes.xise @@ -69,6 +69,22 @@ + + + + + + + + + + + + + + + + @@ -92,9 +108,9 @@ - + - + @@ -104,8 +120,8 @@ - - + + diff --git a/verilog/sd2snes/spi.v b/verilog/sd2snes/spi.v index a233363..318090f 100644 --- a/verilog/sd2snes/spi.v +++ b/verilog/sd2snes/spi.v @@ -20,11 +20,10 @@ ////////////////////////////////////////////////////////////////////////////////// module spi(input clk, - input SCK, + inout SCK, input MOSI, - output MISO, + inout MISO, input SSEL, - output LED, output cmd_ready, output param_ready, output [7:0] cmd_data, @@ -33,15 +32,41 @@ module spi(input clk, output startmessage, input [7:0] input_data, output [31:0] byte_cnt, - output [2:0] bit_cnt); + output [2:0] bit_cnt, + +// spi "DMA" extension + input spi_dma_sck, + input spi_dma_ovr); reg [7:0] cmd_data_r; reg [7:0] param_data_r; // sync SCK to the FPGA clock using a 3-bits shift register +// SCK is an OUTPUT in "DMA" mode +reg [2:0] spi_dma_ovr_r; +reg [9:0] spi_dma_leadout_cnt; +reg spi_dma_leadout; +initial begin + spi_dma_ovr_r = 3'b000; + spi_dma_leadout_cnt <= 10'b0000000000; +end +always @(posedge clk) spi_dma_ovr_r <= {spi_dma_ovr_r[1:0], spi_dma_ovr}; +wire spi_dma_ovr_falling = (spi_dma_ovr_r[1:0] == 2'b10); +always @(posedge clk) begin + if (spi_dma_ovr_falling) begin + spi_dma_leadout <= 1; + spi_dma_leadout_cnt <= 0; + end else begin + if(spi_dma_leadout_cnt == 100) + spi_dma_leadout <= 0; + if(spi_dma_leadout) + spi_dma_leadout_cnt <= spi_dma_leadout_cnt + 1; + end +end +assign SCK = spi_dma_ovr ? spi_dma_sck : spi_dma_leadout ? 1'b0 : 1'bZ; reg [2:0] SCKr; always @(posedge clk) SCKr <= {SCKr[1:0], SCK}; -wire SCK_risingedge = (SCKr[2:1]==2'b01); // now we can detect SCK rising edges -wire SCK_fallingedge = (SCKr[2:1]==2'b10); // and falling edges +wire SCK_risingedge = spi_dma_ovr ? 0 : (SCKr[2:1]==2'b01); // now we can detect SCK rising edges +wire SCK_fallingedge = spi_dma_ovr ? 0 : (SCKr[2:1]==2'b10); // and falling edges // same thing for SSEL reg [2:0] SSELr; always @(posedge clk) SSELr <= {SSELr[1:0], SSEL}; @@ -55,7 +80,7 @@ assign startmessage = SSEL_startmessage; reg [1:0] MOSIr; always @(posedge clk) MOSIr <= {MOSIr[0], MOSI}; wire MOSI_data = MOSIr[1]; -// we handle SPI in 8-bits format, so we need a 3 bits counter to count the bits as they come in +// bit count for one SPI byte + byte count for the message reg [2:0] bitcnt; reg [31:0] byte_cnt_r; @@ -66,44 +91,32 @@ assign bit_cnt = bitcnt; always @(posedge clk) begin - if(~SSEL_active) begin - bitcnt <= 3'b000; - end else - if(SCK_risingedge) - begin - bitcnt <= bitcnt + 3'b001; - - // implement a shift-left register (since we receive the data MSB first) - byte_data_received <= {byte_data_received[6:0], MOSI_data}; - end + if(~SSEL_active) begin + bitcnt <= 3'b000; + end + else if(SCK_risingedge) begin + bitcnt <= bitcnt + 3'b001; + // shift received data into the register + byte_data_received <= {byte_data_received[6:0], MOSI_data}; + end end always @(posedge clk) byte_received <= SSEL_active && SCK_risingedge && (bitcnt==3'b111); -// we use the LSB of the data received to control an LED -reg LEDr; - always @(posedge clk) begin if(~SSEL_active) - byte_cnt_r <= 16'h0000; + byte_cnt_r <= 16'h0000; else if(byte_received) begin - LEDr <= byte_data_received[0]; byte_cnt_r <= byte_cnt_r + 16'h0001; end end -assign LED = LEDr; reg [7:0] byte_data_sent; -reg [7:0] cnt; -always @(posedge clk) begin - if(SSEL_startmessage) cnt<=cnt+8'h1; // count the messages -end - always @(posedge clk) begin if(SSEL_active) begin if(SSEL_startmessage) - byte_data_sent <= cnt; // first byte sent in a message is the message count + byte_data_sent <= 8'h5A; // dummy byte else if(SCK_fallingedge) begin if(bitcnt==3'b000) @@ -114,7 +127,8 @@ always @(posedge clk) begin end end -assign MISO = SSEL_active ? byte_data_sent[7] : 1'bZ; // send MSB first +// Slave out is an INPUT in "DMA" mode +assign MISO = spi_dma_ovr ? 1'bZ : SSEL_active ? byte_data_sent[7] : 1'bZ; // send MSB first reg cmd_ready_r; reg param_ready_r; @@ -128,6 +142,8 @@ assign byte_cnt = byte_cnt_r; always @(posedge clk) cmd_ready_r2 = byte_received && byte_cnt_r == 32'h0; always @(posedge clk) param_ready_r2 = byte_received && byte_cnt_r > 32'h0; + +// fill registers always @(posedge clk) begin if (SSEL_startmessage) cmd_data_r <= 8'h00; @@ -135,8 +151,9 @@ always @(posedge clk) begin cmd_data_r <= byte_data_received; else if(param_ready_r2) param_data_r <= byte_data_received; - end + +// delay ready signals by one clock (why did I do this again...) always @(posedge clk) begin cmd_ready_r <= cmd_ready_r2; param_ready_r <= param_ready_r2; diff --git a/verilog/sd2snes/spi_dma.v b/verilog/sd2snes/spi_dma.v new file mode 100644 index 0000000..024bdf9 --- /dev/null +++ b/verilog/sd2snes/spi_dma.v @@ -0,0 +1,143 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 22:18:56 12/20/2009 +// Design Name: +// Module Name: spi_dma +// Project Name: +// Target Devices: +// Tool versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// +module spi_dma( + input clk, + output spi_dma_ovr, + input spi_dma_miso, + output spi_dma_sck, + input spi_dma_trig, + output spi_dma_nextaddr, + output [7:0] spi_dma_sram_data, + output spi_dma_sram_we, + output spi_dma_done + ); + +reg spi_dma_sram_we_r; +reg spi_dma_done_r; +reg spi_dma_ovr_r; +reg spi_dma_nextaddr_r; +reg [7:0] spi_dma_sram_data_r; + +reg [3:0] spi_dma_bitcnt; // extra bits +reg [9:0] spi_dma_bytecnt; +reg [3:0] spi_dma_clkcnt; +reg [3:0] spi_dma_sck_int_r; +reg [5:0] spi_dma_trig_r; +reg [1:0] spi_dma_miso_r; +reg spi_dma_sck_out_r; +reg spi_dma_sck_out_r2; + +initial begin + spi_dma_clkcnt <= 4'b0000; + spi_dma_bitcnt <= 4'b1110; + spi_dma_bytecnt <= 10'b0000000000; + spi_dma_nextaddr_r <= 1'b0; + spi_dma_sram_we_r <= 1'b1; + spi_dma_done_r <= 1'b1; + spi_dma_sck_int_r <= 4'b0000; + spi_dma_trig_r <= 6'b000000; + spi_dma_ovr_r <= 1'b0; + spi_dma_sck_out_r <= 1'b0; + spi_dma_sck_out_r2 <= 1'b0; +end + +// synthesize clock +wire spi_dma_sck_int = spi_dma_clkcnt[1]; +assign spi_dma_sck = spi_dma_sck_out_r & spi_dma_sck_out_r2; +always @(posedge clk) begin + spi_dma_clkcnt <= spi_dma_clkcnt + 1; + spi_dma_sck_int_r <= {spi_dma_sck_int_r[2:0], spi_dma_sck_int}; + spi_dma_trig_r <= {spi_dma_trig_r[4:0], spi_dma_trig}; + spi_dma_miso_r <= {spi_dma_miso_r[0], spi_dma_miso}; +end + +wire spi_dma_trig_rising = (spi_dma_trig_r[5:1] == 5'b00011); +wire spi_dma_trig_falling = (spi_dma_trig_r[5:1] == 5'b11100); +wire spi_dma_sck_rising = (spi_dma_sck_int_r[1:0] == 2'b01); +wire spi_dma_sck_falling = (spi_dma_sck_int_r[1:0] == 2'b10); +wire spi_dma_sck_rising2 = (spi_dma_sck_int_r[1:0] == 2'b01); +wire spi_dma_sck_falling2 = (spi_dma_sck_int_r[1:0] == 2'b10); + +assign spi_dma_nextaddr = spi_dma_nextaddr_r; +assign spi_dma_sram_data = spi_dma_sram_data_r; +assign spi_dma_sram_we = spi_dma_sram_we_r; +assign spi_dma_done = spi_dma_done_r; +assign spi_dma_ovr = spi_dma_ovr_r; + +always @(posedge clk) begin + if (spi_dma_trig_falling & !spi_dma_ovr_r) begin + spi_dma_done_r <= 0; + spi_dma_ovr_r <= 1; + end else if (spi_dma_bitcnt == 0 && spi_dma_bytecnt == 512) begin + spi_dma_done_r <= 1; + spi_dma_ovr_r <= 0; + end +end + +always @(posedge clk) begin + if(spi_dma_sck_falling) + spi_dma_sck_out_r2 <= 0; + else if(spi_dma_sck_rising) + spi_dma_sck_out_r2 <= 1; +end + +always @(posedge clk) begin + if (spi_dma_sck_rising & spi_dma_ovr_r & spi_dma_bitcnt < 8) + spi_dma_sram_data_r <= {spi_dma_sram_data_r[6:0], spi_dma_miso}; +end + +always @(posedge clk) begin + if(spi_dma_sck_rising & spi_dma_ovr_r) begin + if (spi_dma_bitcnt < 8) begin + spi_dma_sck_out_r <= 1; + spi_dma_bitcnt <= spi_dma_bitcnt + 1; + end else if (spi_dma_bitcnt == 8) begin + spi_dma_sck_out_r <= 0; + spi_dma_bitcnt <= spi_dma_bitcnt + 1; + spi_dma_sram_we_r <= 0; + end else if (spi_dma_bitcnt == 9) begin + spi_dma_sck_out_r <= 0; + spi_dma_sram_we_r <= 1; + spi_dma_bytecnt <= spi_dma_bytecnt + 1; + spi_dma_bitcnt <= 10; + end else if (spi_dma_bitcnt == 10) begin + spi_dma_nextaddr_r <= 1; + spi_dma_bitcnt <= spi_dma_bitcnt + 1; + end else if (spi_dma_bitcnt == 11) begin + spi_dma_nextaddr_r <= 0; + spi_dma_bitcnt <= spi_dma_bitcnt + 1; + end else if (spi_dma_bitcnt == 12) begin + spi_dma_bitcnt <= 0; + end else if (spi_dma_bitcnt == 4'b1101) begin + spi_dma_sck_out_r <= 0; + spi_dma_bitcnt <= 4'b1110; + end else if (spi_dma_bitcnt == 4'b1110) begin + spi_dma_bitcnt <= spi_dma_bitcnt + 1; + end else if (spi_dma_bitcnt == 4'b1111) begin + spi_dma_bitcnt <= 0; + end + end else if (spi_dma_sck_rising & !spi_dma_ovr_r) begin + spi_dma_bitcnt <= 4'b1101; + spi_dma_bytecnt <= 10'b0000000000; + end +end + +endmodule diff --git a/verilog/sd2snes/tf_main_3.v b/verilog/sd2snes/tf_main_3.v new file mode 100644 index 0000000..52e761d --- /dev/null +++ b/verilog/sd2snes/tf_main_3.v @@ -0,0 +1,132 @@ +`timescale 1ns / 1ps + +//////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 04:03:25 12/21/2009 +// Design Name: main +// Module Name: /home/ikari/prj/sd2snes/verilog/sd2snes/tf_main_3.v +// Project Name: sd2snes +// Target Device: +// Tool versions: +// Description: +// +// Verilog Test Fixture created by ISE for module: main +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +//////////////////////////////////////////////////////////////////////////////// + +module tf_main_3; + + // Inputs + reg CLKIN; + reg [23:0] SNES_ADDR; + reg SNES_READ; + reg SNES_WRITE; + reg SNES_CS; + reg SNES_CPU_CLK; + reg SNES_REFRESH; + reg SPI_MOSI; + reg SPI_SS; + reg AVR_ENA; + + // Outputs + wire SNES_DATABUS_OE; + wire SNES_DATABUS_DIR; + wire IRQ_DIR; + wire [19:0] SRAM_ADDR; + wire [3:0] SRAM_CE2; + wire SRAM_OE; + wire SRAM_WE; + wire SRAM_BHE; + wire SRAM_BLE; + + // Bidirs + wire [7:0] SNES_DATA; + wire SNES_IRQ; + wire [15:0] SRAM_DATA; + wire SPI_MISO; + wire SPI_SCK; + wire SPI_DMA_CTRL; + + reg SPI_DMA_CTRLdir; + reg SPI_DMA_CTRLr; + + reg SPI_MISOdir; + reg SPI_MISOr; + // Instantiate the Unit Under Test (UUT) + main uut ( + .CLKIN(CLKIN), + .SNES_ADDR(SNES_ADDR), + .SNES_READ(SNES_READ), + .SNES_WRITE(SNES_WRITE), + .SNES_CS(SNES_CS), + .SNES_DATA(SNES_DATA), + .SNES_CPU_CLK(SNES_CPU_CLK), + .SNES_REFRESH(SNES_REFRESH), + .SNES_IRQ(SNES_IRQ), + .SNES_DATABUS_OE(SNES_DATABUS_OE), + .SNES_DATABUS_DIR(SNES_DATABUS_DIR), + .IRQ_DIR(IRQ_DIR), + .SRAM_DATA(SRAM_DATA), + .SRAM_ADDR(SRAM_ADDR), + .SRAM_CE2(SRAM_CE2), + .SRAM_OE(SRAM_OE), + .SRAM_WE(SRAM_WE), + .SRAM_BHE(SRAM_BHE), + .SRAM_BLE(SRAM_BLE), + .SPI_MOSI(SPI_MOSI), + .SPI_MISO(SPI_MISO), + .SPI_SS(SPI_SS), + .SPI_SCK(SPI_SCK), + .AVR_ENA(AVR_ENA), + .SPI_DMA_CTRL(SPI_DMA_CTRL) + ); + + initial begin + // Initialize Inputs + CLKIN = 0; + SNES_ADDR = 0; + SNES_READ = 0; + SNES_WRITE = 0; + SNES_CS = 0; + SNES_CPU_CLK = 0; + SNES_REFRESH = 0; + SPI_MOSI = 0; + SPI_SS = 0; + AVR_ENA = 0; + SPI_DMA_CTRLr = 1; + SPI_DMA_CTRLdir = 0; + SPI_MISOr = 0; + SPI_MISOdir = 0; + // Wait 100 ns for global reset to finish + #100; + #600; // dcm? + // Add stimulus here + SPI_DMA_CTRLr = 1; + SPI_DMA_CTRLdir = 1; + #100 SPI_DMA_CTRLr = 0; + #100 SPI_DMA_CTRLr = 1'bZ; + SPI_DMA_CTRLdir = 0; + SPI_MISOdir = 1; + #260 SPI_MISOr = 1; + #80 SPI_MISOr = 0; + #80 SPI_MISOr = 0; + #80 SPI_MISOr = 1; + #80 SPI_MISOr = 0; + #80 SPI_MISOr = 1; + #80 SPI_MISOr = 0; + #80 SPI_MISOr = 1; + end + + assign SPI_DMA_CTRL = SPI_DMA_CTRLdir ? SPI_DMA_CTRLr : 1'bZ; + assign SPI_MISO = SPI_MISOdir ? SPI_MISOr : 1'bZ; + always #35 CLKIN = ~CLKIN; +endmodule +