new files (SPI)

This commit is contained in:
ikari 2009-09-04 10:56:59 +02:00
parent ceb5bec774
commit be0fde297d
5 changed files with 968 additions and 0 deletions

52
src/fpga_spi.c Normal file
View File

@ -0,0 +1,52 @@
// insert cool lengthy disclaimer here
/*
fpga_spi.c: SPI functions for SRAM interfacing and mapper config
SPI commands
cmd param function
=============================================
00 bb[hh[ll]] set address to 0xbbhhll
2s - set SRAM size to s
3m - set mapper to m
0=HiROM, 1=LoROM
80 - read with increment
81 - read w/o increment
90 {xx}* write xx with increment
91 {xx}* write xx w/o increment
*/
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "avrcompat.h"
#include "fpga.h"
#include "config.h"
#include "uart.h"
#include "spi.h"
#include "fpga_spi.h"
void spi_fpga(void) {
SPI_SS_HIGH();
FPGA_SS_LOW();
}
void spi_sd(void) {
FPGA_SS_HIGH();
SPI_SS_LOW();
}
void fpga_spi_init(void) {
DDRC = _BV(PC7);
FPGA_SS_HIGH();
}
void set_avr_addr(uint32_t address) {
spi_fpga();
spiTransferByte(0x00);
spiTransferByte((address>>16)&0xff);
spiTransferByte((address>>8)&0xff);
spiTransferByte((address)&0xff);
spi_sd();
}

10
src/fpga_spi.h Normal file
View File

@ -0,0 +1,10 @@
// insert cool lengthy disclaimer here
#define FPGA_SS_HIGH() do {PORTC |= _BV(PC7);} while (0)
#define FPGA_SS_LOW() do {PORTC &= ~_BV(PC7);} while (0)
void fpga_spi_init(void);
void fpga_spi_test(void);
void spi_fpga(void);
void spi_sd(void);
void set_avr_addr(uint32_t);

118
verilog/sd2snes/avr_cmd.v Normal file
View File

@ -0,0 +1,118 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 21:57:50 08/25/2009
// Design Name:
// Module Name: avr_cmd
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module avr_cmd(
input clk,
input cmd_ready,
input param_ready,
input [7:0] cmd_data,
input [7:0] param_data,
output [3:0] avr_mapper,
output [3:0] avr_sram_size,
output avr_read,
output avr_write,
output [7:0] avr_data_out,
input [7:0] avr_data_in,
output [7:0] spi_data_out,
input [31:0] spi_byte_cnt,
input [2:0] spi_bit_cnt,
output [23:0] addr_out,
output [3:0] mapper,
input endmessage,
input startmessage
);
reg [3:0] MAPPER_BUF;
reg [3:0] SRAM_SIZE_BUF;
reg AVR_READ_BUF;
reg AVR_WRITE_BUF;
reg [23:0] ADDR_OUT_BUF;
reg [7:0] AVR_DATA_OUT_BUF;
reg [7:0] AVR_DATA_IN_BUF;
reg [1:0] avr_nextaddr_buf;
wire avr_nextaddr;
assign spi_data_out = AVR_DATA_IN_BUF;
initial begin
ADDR_OUT_BUF = 0;
end
always @(posedge clk) begin
if (cmd_ready) begin
case (cmd_data[7:4])
4'h2:
SRAM_SIZE_BUF <= cmd_data[3:0];
4'h3:
MAPPER_BUF <= cmd_data[3:0];
4'h8:
AVR_DATA_IN_BUF <= avr_data_in;
endcase
end else if (param_ready) begin
case (cmd_data[7:4])
4'h0:
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
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'h0+2*cmd_data[4])))
ADDR_OUT_BUF <= ADDR_OUT_BUF + 1;
end
always @(posedge clk) begin
if (spi_bit_cnt == 3'h0)
avr_nextaddr_buf <= {avr_nextaddr_buf[0], 1'b1};
else
avr_nextaddr_buf <= {avr_nextaddr_buf[0], 1'b0};
end
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;
if ((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
assign avr_nextaddr = avr_nextaddr_buf == 2'b01;
assign avr_read = AVR_READ_BUF;
assign avr_write = AVR_WRITE_BUF;
assign addr_out = ADDR_OUT_BUF;
assign avr_data_out = AVR_DATA_OUT_BUF;
assign avr_mapper = MAPPER_BUF;
assign avr_sram_size = SRAM_SIZE_BUF;
endmodule

643
verilog/sd2snes/main_tf2.v Normal file
View File

@ -0,0 +1,643 @@
`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 00:20:33 07/14/2009
// Design Name: main
// Module Name: /home/ikari/prj/sd2snes/verilog/sd2snes/main_tf2.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 main_tf2;
// 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 SPI_SCK;
reg AVR_ENA;
// Outputs
wire SNES_DATABUS_OE;
wire SNES_DATABUS_DIR;
wire [19:0] SRAM_ADDR;
wire [3:0] ROM_SEL;
wire SRAM_OE;
wire SRAM_WE;
wire SPI_MISO;
wire MODE;
wire SPI_LSB;
wire SRAM_BHE;
wire SRAM_BLE;
// Bidirs
wire [7:0] SNES_DATA;
wire SNES_IRQ;
wire [15:0] SRAM_DATA;
reg [15:0] SRAM_DATA_BUF;
// 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),
.IRQ_DIR(IRQ_DIR),
.SNES_DATABUS_OE(SNES_DATABUS_OE),
.SNES_DATABUS_DIR(SNES_DATABUS_DIR),
.SRAM_DATA(SRAM_DATA),
.SRAM_ADDR(SRAM_ADDR),
.SRAM_CE2(ROM_SEL),
.SRAM_OE(SRAM_OE),
.SRAM_WE(SRAM_WE),
.SPI_MOSI(SPI_MOSI),
.SPI_MISO(SPI_MISO),
.SPI_SS(SPI_SS),
.SPI_SCK(SPI_SCK),
.AVR_ENA(AVR_ENA),
.SRAM_BHE(SRAM_BHE),
.SRAM_BLE(SRAM_BLE)
);
initial begin
// Initialize Inputs
CLKIN = 0;
SNES_ADDR = 0;
SNES_READ = 1;
SNES_WRITE = 1;
SNES_CS = 0;
SNES_CPU_CLK = 0;
SNES_REFRESH = 0;
SPI_MOSI = 0;
SPI_SS = 1;
SPI_SCK = 0;
AVR_ENA = 0;
// Wait 100 ns for global reset to finish
#100;
// Wait for DCM to stabilize
#5000;
// Add stimulus here
// Add stimulus here
SPI_SS = 0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#200;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#200;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#100 SPI_SS=1;
#200;
SPI_SS=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#200;
SPI_SS=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#200;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#200;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#200;
#100 SPI_SS=1;
#200;
SPI_SS=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#200;
SPI_SS=1;
#200;
/*
* READ TEST
*/
AVR_ENA=1;
SPI_SS=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#100;
#100;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#200;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#200;
SPI_SS=1;
#300;
SPI_SS=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#200;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#200;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#200;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#200;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#200;
SPI_SS=1;
AVR_ENA=1;
#280;
// Initialize Inputs
SNES_ADDR = 24'h223456;
SNES_READ = 1;
SNES_WRITE = 1;
SNES_CS = 0;
AVR_ENA = 1;
SRAM_DATA_BUF = 8'hff;
// Wait for global reset to finish
#276;
SNES_ADDR <= 24'h123456;
SNES_READ <= 0;
#176;
SNES_READ <= 1;
#100;
SNES_WRITE <= 0;
#176;
SNES_WRITE <= 1;
#100;
SNES_READ <= 0;
#276;
// AVR_READ <= 1;
// Add stimulus here
SPI_SS = 0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#200;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#200;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=0;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
SPI_MOSI=1;
#100 SPI_SCK=1;
#100 SPI_SCK=0;
#100 SPI_SS=1;
#200;
end
always begin
#23 CLKIN = ~CLKIN;
end
always begin
#150 SNES_READ = ~SNES_READ;
end
endmodule

145
verilog/sd2snes/spi.v Normal file
View File

@ -0,0 +1,145 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 21:16:09 07/10/2009
// Design Name:
// Module Name: spi
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module spi(input clk,
input SCK,
input MOSI,
output MISO,
input SSEL,
output LED,
output cmd_ready,
output param_ready,
output [7:0] cmd_data,
output [7:0] param_data,
output endmessage,
output startmessage,
input [7:0] input_data,
output [31:0] byte_cnt,
output [2:0] bit_cnt);
reg [7:0] cmd_data_r;
reg [7:0] param_data_r;
// sync SCK to the FPGA clock using a 3-bits shift register
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
// same thing for SSEL
reg [2:0] SSELr; always @(posedge clk) SSELr <= {SSELr[1:0], SSEL};
wire SSEL_active = ~SSELr[1]; // SSEL is active low
wire SSEL_startmessage = (SSELr[2:1]==2'b10); // message starts at falling edge
wire SSEL_endmessage = (SSELr[2:1]==2'b01); // message stops at rising edge
assign endmessage = SSEL_endmessage;
assign startmessage = SSEL_startmessage;
// and for MOSI
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
reg [2:0] bitcnt;
reg [31:0] byte_cnt_r;
reg byte_received; // high when a byte has been received
reg [7:0] byte_data_received;
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
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;
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
else
if(SCK_fallingedge) begin
if(bitcnt==3'b000)
byte_data_sent <= input_data; // after that, we send whatever we get
else
byte_data_sent <= {byte_data_sent[6:0], 1'b0};
end
end
end
assign MISO = SSEL_active ? byte_data_sent[7] : 1'bZ; // send MSB first
reg cmd_ready_r;
reg param_ready_r;
reg cmd_ready_r2;
reg param_ready_r2;
assign cmd_ready = cmd_ready_r;
assign param_ready = param_ready_r;
assign cmd_data = cmd_data_r;
assign param_data = param_data_r;
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;
always @(posedge clk) begin
if (SSEL_startmessage)
cmd_data_r <= 8'h00;
else if(cmd_ready_r2)
cmd_data_r <= byte_data_received;
else if(param_ready_r2)
param_data_r <= byte_data_received;
end
always @(posedge clk) begin
cmd_ready_r <= cmd_ready_r2;
param_ready_r <= param_ready_r2;
end
endmodule