From 968c347986aaa0e8a83c1d0bebb27ab7675b39a9 Mon Sep 17 00:00:00 2001 From: Maximilian Rehkopf Date: Mon, 9 Jul 2012 02:17:01 +0200 Subject: [PATCH] FPGA/SPI: detect end of byte via MSB toggle instead of constant compare of async input --- verilog/sd2snes/mcu_cmd.v | 7 ++++--- verilog/sd2snes/spi.v | 39 +++++++++++++++++++++++++------------ verilog/sd2snes_cx4/spi.v | 41 ++++++++++++++++++++++++++------------- verilog/sd2sneslite/spi.v | 31 ++++++++++++++++++----------- 4 files changed, 79 insertions(+), 39 deletions(-) diff --git a/verilog/sd2snes/mcu_cmd.v b/verilog/sd2snes/mcu_cmd.v index 1e79c30..330c776 100644 --- a/verilog/sd2snes/mcu_cmd.v +++ b/verilog/sd2snes/mcu_cmd.v @@ -143,12 +143,13 @@ reg [55:0] rtc_data_out_buf; reg rtc_pgm_we_buf; reg srtc_reset_buf; +initial srtc_reset_buf = 0; reg [31:0] SNES_SYSCLK_FREQ_BUF; reg [7:0] MCU_DATA_OUT_BUF; reg [7:0] MCU_DATA_IN_BUF; -reg [1:0] mcu_nextaddr_buf; +reg [2:0] mcu_nextaddr_buf; wire mcu_nextaddr; @@ -413,9 +414,9 @@ end // value fetch during last SPI bit always @(posedge clk) begin - if (cmd_data[7:4] == 4'h8 && mcu_nextaddr_buf == 2'b01) + if (cmd_data[7:4] == 4'h8 && mcu_nextaddr) MCU_DATA_IN_BUF <= mcu_data_in; - else if (spi_bit_cnt == 3'h7) begin + else if (cmd_ready | param_ready /* bit_cnt == 7 */) begin if (cmd_data[7:0] == 8'hF0) MCU_DATA_IN_BUF <= 8'hA5; else if (cmd_data[7:0] == 8'hF1) diff --git a/verilog/sd2snes/spi.v b/verilog/sd2snes/spi.v index cb6bf79..6b16083 100644 --- a/verilog/sd2snes/spi.v +++ b/verilog/sd2snes/spi.v @@ -39,15 +39,27 @@ module spi( reg [7:0] cmd_data_r; reg [7:0] param_data_r; -reg [1:0] SSELr; always @(posedge clk) SSELr <= {SSELr[0], SSEL}; +reg [2:0] SSELr; +reg [2:0] SSELSCKr; + +always @(posedge clk) SSELr <= {SSELr[1:0], SSEL}; +always @(posedge SCK) SSELSCKr <= {SSELSCKr[1:0], SSEL}; + +wire SSEL_inactive = SSELr[1]; wire SSEL_active = ~SSELr[1]; // SSEL is active low -wire SSEL_startmessage = (SSELr[1:0]==2'b10); // message starts at falling edge -wire SSEL_endmessage = (SSELr[1:0]==2'b01); // message stops at rising edge +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; // bit count for one SPI byte + byte count for the message reg [2:0] bitcnt; +initial bitcnt = 3'b000; +wire bitcnt_msb = bitcnt[2]; +reg [2:0] bitcnt_wrap_r; +always @(posedge clk) bitcnt_wrap_r <= {bitcnt_wrap_r[1:0], bitcnt_msb}; +wire byte_received_sync = (bitcnt_wrap_r[2:1] == 2'b10); + reg [31:0] byte_cnt_r; reg byte_received; // high when a byte has been received @@ -56,23 +68,26 @@ reg [7:0] byte_data_received; assign bit_cnt = bitcnt; always @(posedge SCK) begin - if(SSEL) bitcnt <= 3'b000; - else begin - bitcnt <= bitcnt + 3'b001; + if(SSELSCKr[1]) bitcnt <= 3'b000; + else bitcnt <= bitcnt + 3'b001; +end + +always @(posedge SCK) begin + if(~SSELSCKr[1]) begin byte_data_received <= {byte_data_received[6:0], MOSI}; end - if(~SSEL && bitcnt==3'b111) byte_received <= 1'b1; + if(~SSELSCKr[1] && bitcnt==3'b111) byte_received <= 1'b1; else byte_received <= 1'b0; end -reg [1:0] byte_received_r; -always @(posedge clk) byte_received_r <= {byte_received_r[0], byte_received}; -wire byte_received_sync = (byte_received_r == 2'b01); +//reg [2:0] byte_received_r; +//always @(posedge clk) byte_received_r <= {byte_received_r[1:0], byte_received}; +//wire byte_received_sync = (byte_received_r[2:1] == 2'b01); always @(posedge clk) begin - if(~SSEL_active) + if(SSEL_inactive) begin byte_cnt_r <= 16'h0000; - else if(byte_received_sync) begin + end else if(byte_received_sync) begin byte_cnt_r <= byte_cnt_r + 16'h0001; end end diff --git a/verilog/sd2snes_cx4/spi.v b/verilog/sd2snes_cx4/spi.v index 8b9b0fd..6b16083 100644 --- a/verilog/sd2snes_cx4/spi.v +++ b/verilog/sd2snes_cx4/spi.v @@ -39,15 +39,27 @@ module spi( reg [7:0] cmd_data_r; reg [7:0] param_data_r; -reg [1:0] SSELr; always @(posedge clk) SSELr <= {SSELr[0], SSEL}; +reg [2:0] SSELr; +reg [2:0] SSELSCKr; + +always @(posedge clk) SSELr <= {SSELr[1:0], SSEL}; +always @(posedge SCK) SSELSCKr <= {SSELSCKr[1:0], SSEL}; + +wire SSEL_inactive = SSELr[1]; wire SSEL_active = ~SSELr[1]; // SSEL is active low -wire SSEL_startmessage = (SSELr[1:0]==2'b10); // message starts at falling edge -wire SSEL_endmessage = (SSELr[1:0]==2'b01); // message stops at rising edge +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; // bit count for one SPI byte + byte count for the message reg [2:0] bitcnt; +initial bitcnt = 3'b000; +wire bitcnt_msb = bitcnt[2]; +reg [2:0] bitcnt_wrap_r; +always @(posedge clk) bitcnt_wrap_r <= {bitcnt_wrap_r[1:0], bitcnt_msb}; +wire byte_received_sync = (bitcnt_wrap_r[2:1] == 2'b10); + reg [31:0] byte_cnt_r; reg byte_received; // high when a byte has been received @@ -56,23 +68,26 @@ reg [7:0] byte_data_received; assign bit_cnt = bitcnt; always @(posedge SCK) begin - if(SSEL) bitcnt <= 3'b000; - else begin - bitcnt <= bitcnt + 3'b001; - byte_data_received <= {byte_data_received[6:0], MOSI}; + if(SSELSCKr[1]) bitcnt <= 3'b000; + else bitcnt <= bitcnt + 3'b001; +end + +always @(posedge SCK) begin + if(~SSELSCKr[1]) begin + byte_data_received <= {byte_data_received[6:0], MOSI}; end - if(~SSEL && bitcnt==3'b111) byte_received <= 1'b1; + if(~SSELSCKr[1] && bitcnt==3'b111) byte_received <= 1'b1; else byte_received <= 1'b0; end -reg [1:0] byte_received_r; -always @(posedge clk) byte_received_r <= {byte_received_r[0], byte_received}; -wire byte_received_sync = (byte_received_r == 2'b01); +//reg [2:0] byte_received_r; +//always @(posedge clk) byte_received_r <= {byte_received_r[1:0], byte_received}; +//wire byte_received_sync = (byte_received_r[2:1] == 2'b01); always @(posedge clk) begin - if(~SSEL_active) + if(SSEL_inactive) begin byte_cnt_r <= 16'h0000; - else if(byte_received_sync) begin + end else if(byte_received_sync) begin byte_cnt_r <= byte_cnt_r + 16'h0001; end end diff --git a/verilog/sd2sneslite/spi.v b/verilog/sd2sneslite/spi.v index 02d15a5..64d4655 100644 --- a/verilog/sd2sneslite/spi.v +++ b/verilog/sd2sneslite/spi.v @@ -47,11 +47,15 @@ wire SSEL_inactive = SSELr[1]; 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; // bit count for one SPI byte + byte count for the message reg [2:0] bitcnt; +initial bitcnt = 3'b000; +wire bitcnt_msb = bitcnt[2]; +reg [2:0] bitcnt_wrap_r; +always @(posedge clk) bitcnt_wrap_r <= {bitcnt_wrap_r[1:0], bitcnt_msb}; +wire byte_received_sync = (bitcnt_wrap_r[2:1] == 2'b10); + reg [31:0] byte_cnt_r; reg byte_received; // high when a byte has been received @@ -60,27 +64,32 @@ reg [7:0] byte_data_received; assign bit_cnt = bitcnt; always @(posedge SCK) begin - if(SSEL) bitcnt <= 3'b000; - else begin - bitcnt <= bitcnt + 3'b001; + if(SSELSCKr[1]) bitcnt <= 3'b000; + else bitcnt <= bitcnt + 3'b001; +end + +always @(posedge SCK) begin + if(~SSELSCKr[1]) begin byte_data_received <= {byte_data_received[6:0], MOSI}; end - if(~SSEL && bitcnt==3'b111) byte_received <= 1'b1; + if(~SSELSCKr[1] && bitcnt==3'b111) byte_received <= 1'b1; else byte_received <= 1'b0; end -reg [1:0] byte_received_r; -always @(posedge clk) byte_received_r <= {byte_received_r[0], byte_received}; -wire byte_received_sync = (byte_received_r == 2'b01); +//reg [2:0] byte_received_r; +//always @(posedge clk) byte_received_r <= {byte_received_r[1:0], byte_received}; +//wire byte_received_sync = (byte_received_r[2:1] == 2'b01); always @(posedge clk) begin - if(~SSEL_active) + if(SSEL_inactive) begin byte_cnt_r <= 16'h0000; - else if(byte_received_sync) begin + end else if(byte_received_sync) begin byte_cnt_r <= byte_cnt_r + 16'h0001; end end +reg [7:0] byte_data_sent; + assign MISO = ~SSEL ? input_data[7-bitcnt] : 1'bZ; // send MSB first reg cmd_ready_r;