Forum Discussion
Altera_Forum
Honored Contributor
15 years agoMMC SPI Core with FIFO
Hi, The MMC SD card access using Altera's normal spi IP core is quite slow, because the core has only one byte Tx and Rx buffer, so the driver can send and receive only one byte at once. The s...
Altera_Forum
Honored Contributor
9 years agoThank you for the really informative post! Several years and versions of Quartus have gone by and I was hoping you might be willing to update the instructions for a current system?
I created a project in Quartus and then a working Nios system in QSYS with a spi port. I then added the two files from your tgz into the submodules directory and edited my spi.v file as per your instructions to generate the following diff:
@@ -85,3 +85,3 @@ module ft3_proto_qsys_fpga_spi0 (
reg ROE;
- reg RRDY;
+ wire RRDY;
wire SCLK;
@@ -138,2 +138,39 @@ module ft3_proto_qsys_fpga_spi0 (
wire write_tx_holding;
+
+ wire tx_fifo_data_out;
+ wire tx_fifo_count;
+ wire tx_fifo_empty;
+ wire tx_fifo_full;
+
+ wire rx_fifo_data_out;
+ wire rx_fifo_count;
+ wire rx_fifo_empty;
+ wire rx_fifo_full;
+
+ mmc_spi_tx_fifio the_mmc_spi_tx_fifio (
+ .aclr (~reset_n),
+ .clock (clk),
+ .data (data_from_cpu),
+ .rdreq (write_shift_reg),
+ .sclr (status_wr_strobe),
+ .wrreq (write_tx_holding),
+ .empty (tx_fifo_empty),
+ .full (tx_fifo_full),
+ .q (tx_fifo_data_out),
+ .usedw (tx_fifo_count)
+ );
+
+mmc_spi_rx_fifo the_mmc_spi_rx_fifo (
+ .aclr (~reset_n),
+ .clock (clk),
+ .data (shift_reg),
+ .rdreq (data_rd_strobe),
+ .sclr (status_wr_strobe),
+ .wrreq ((state == 17) & (slowcount == 0)),
+ .empty (rx_fifo_empty),
+ .full (rx_fifo_full),
+ .q (rx_fifo_data_out),
+ .usedw (rx_fifo_count)
+ );
+
//spi_control_port, which is an e_avalon_slave
@@ -185,3 +222,4 @@ module ft3_proto_qsys_fpga_spi0 (
assign endofpacketvalue_wr_strobe = wr_strobe & (mem_addr == 6);
- assign TMT = ~transmitting & ~tx_holding_primed;
+// assign TMT = ~transmitting & ~tx_holding_primed;
+ assign TMT = ~transmitting & tx_fifo_empty;
assign E = ROE | TOE;
@@ -192,3 +230,4 @@ module ft3_proto_qsys_fpga_spi0 (
// Ready to accept streaming data.
- assign readyfordata = TRDY;
+// assign readyfordata = TRDY;
+ assign readyfordata = ~tx_fifo_full;
@@ -286,3 +325,4 @@ module ft3_proto_qsys_fpga_spi0 (
((mem_addr == 5))? spi_slave_select_reg :
- rx_holding_reg;
+// rx_holding_reg;
+ {rx_fifo_count & ~rx_fifo_empty, rx_fifo_data_out};
@@ -324,9 +364,12 @@ module ft3_proto_qsys_fpga_spi0 (
//it's safe to write data.
- assign TRDY = ~(transmitting & tx_holding_primed);
+// assign TRDY = ~(transmitting & tx_holding_primed);
+ assign TRDY = ~tx_fifo_count;
// Enable write to tx_holding_register.
- assign write_tx_holding = data_wr_strobe & TRDY;
+// assign write_tx_holding = data_wr_strobe & TRDY;
+ assign write_tx_holding = data_wr_strobe;
// Enable write to shift register.
- assign write_shift_reg = tx_holding_primed & ~transmitting;
+// assign write_shift_reg = tx_holding_primed & ~transmitting;
+ assign write_shift_reg = ~tx_fifo_empty & ~transmitting;
@@ -339,3 +382,3 @@ module ft3_proto_qsys_fpga_spi0 (
EOP <= 0;
- RRDY <= 0;
+// RRDY <= 0;
ROE <= 0;
@@ -355,3 +398,4 @@ module ft3_proto_qsys_fpga_spi0 (
end
- if (data_wr_strobe & ~TRDY)
+// if (data_wr_strobe & ~TRDY)
+ if (data_wr_strobe & tx_fifo_full)
// You wrote when I wasn't ready.
@@ -364,3 +408,4 @@ module ft3_proto_qsys_fpga_spi0 (
begin
- shift_reg <= tx_holding_reg;
+// shift_reg <= tx_holding_reg;
+ shift_reg <= tx_fifo_data_out;
transmitting <= 1;
@@ -371,5 +416,5 @@ module ft3_proto_qsys_fpga_spi0 (
- if (data_rd_strobe)
- // On data read, clear the RRDY bit.
- RRDY <= 0;
+// if (data_rd_strobe)
+// // On data read, clear the RRDY bit.
+// RRDY <= 0;
@@ -380,3 +425,3 @@ module ft3_proto_qsys_fpga_spi0 (
- RRDY <= 0;
+// RRDY <= 0;
ROE <= 0;
@@ -389,6 +434,7 @@ module ft3_proto_qsys_fpga_spi0 (
transmitting <= 0;
- RRDY <= 1;
+// RRDY <= 1;
rx_holding_reg <= shift_reg;
SCLK_reg <= 0;
- if (RRDY)
+// if (RRDY)
+ if (rx_fifo_full)
ROE <= 1;
I have two questions: 1) All I have to do now is re-compile the main project in Quartus (16) and then use it? 2) Is there a more modern/current fifo I should be using instead? I noticed that lpm_fifo is still supported for compatibility but isn't the normal wizard generated FIFO anymore. Thank you again, Hunter