Update to the back-door wishbone access to housekeeping to better

implement the arbitration between SPI and back-door.  The back-door
access flags when it is going to do a read or write, and the SPI
can have an invalid read or fail a write if the SPI is too fast,
but the wishbone access should be valid.  As long as the SPI is
much slower than the core clock (say, 1MHz) then there should be no
contention, which means that contention can always be avoided simply
by slowing the SPI signaling down.
This commit is contained in:
Tim Edwards 2021-10-24 16:58:47 -04:00
parent e6a94449ce
commit a7fec91c4c
1 changed files with 20 additions and 6 deletions

View File

@ -316,6 +316,7 @@ module housekeeping #(
reg [7:0] wbbd_data; /* SPI data translated from WB */ reg [7:0] wbbd_data; /* SPI data translated from WB */
reg wbbd_sck; /* wishbone access trigger (back-door clock) */ reg wbbd_sck; /* wishbone access trigger (back-door clock) */
reg wbbd_write; /* wishbone write trigger (back-door strobe) */ reg wbbd_write; /* wishbone write trigger (back-door strobe) */
reg wbbd_busy; /* Raised during a wishbone read or write */
reg wb_ack_o; /* acknowledge signal back to wishbone bus */ reg wb_ack_o; /* acknowledge signal back to wishbone bus */
reg [31:0] wb_dat_o; /* data output to wishbone bus */ reg [31:0] wb_dat_o; /* data output to wishbone bus */
@ -636,11 +637,13 @@ module housekeeping #(
wbbd_write <= 1'b0; wbbd_write <= 1'b0;
wbbd_addr <= 8'd0; wbbd_addr <= 8'd0;
wbbd_data <= 8'd0; wbbd_data <= 8'd0;
wbbd_busy <= 1'b0;
wb_ack_o <= 1'b0; wb_ack_o <= 1'b0;
wbbd_state <= `WBBD_IDLE; wbbd_state <= `WBBD_IDLE;
end else begin end else begin
case (wbbd_state) case (wbbd_state)
`WBBD_IDLE: begin `WBBD_IDLE: begin
wbbd_busy <= 1'b0;
if (wb_cyc_i && (sys_select | gpio_select | spi_select)) begin if (wb_cyc_i && (sys_select | gpio_select | spi_select)) begin
wb_ack_o <= 1'b0; wb_ack_o <= 1'b0;
wbbd_state <= `WBBD_SETUP0; wbbd_state <= `WBBD_SETUP0;
@ -653,6 +656,7 @@ module housekeeping #(
wbbd_data <= wb_dat_i[7:0]; wbbd_data <= wb_dat_i[7:0];
end end
wbbd_write <= wb_sel_i[0] & wb_we_i; wbbd_write <= wb_sel_i[0] & wb_we_i;
wbbd_busy <= 1'b1;
// If the SPI is being accessed and about to read or // If the SPI is being accessed and about to read or
// write a byte, then stall until the SPI is ready. // write a byte, then stall until the SPI is ready.
@ -661,11 +665,13 @@ module housekeeping #(
end end
end end
`WBBD_RW0: begin `WBBD_RW0: begin
wbbd_busy <= 1'b1;
wbbd_sck <= 1'b1; wbbd_sck <= 1'b1;
wb_dat_o[7:0] <= odata; wb_dat_o[7:0] <= odata;
wbbd_state <= `WBBD_SETUP1; wbbd_state <= `WBBD_SETUP1;
end end
`WBBD_SETUP1: begin `WBBD_SETUP1: begin
wbbd_busy <= 1'b1;
wbbd_sck <= 1'b0; wbbd_sck <= 1'b0;
wbbd_addr <= spiaddr(wb_adr_i + 1); wbbd_addr <= spiaddr(wb_adr_i + 1);
if (wb_sel_i[1] & wb_we_i) begin if (wb_sel_i[1] & wb_we_i) begin
@ -677,11 +683,13 @@ module housekeeping #(
end end
end end
`WBBD_RW1: begin `WBBD_RW1: begin
wbbd_busy <= 1'b1;
wbbd_sck <= 1'b1; wbbd_sck <= 1'b1;
wb_dat_o[15:8] <= odata; wb_dat_o[15:8] <= odata;
wbbd_state <= `WBBD_SETUP2; wbbd_state <= `WBBD_SETUP2;
end end
`WBBD_SETUP2: begin `WBBD_SETUP2: begin
wbbd_busy <= 1'b1;
wbbd_sck <= 1'b0; wbbd_sck <= 1'b0;
wbbd_addr <= spiaddr(wb_adr_i + 2); wbbd_addr <= spiaddr(wb_adr_i + 2);
if (wb_sel_i[2] & wb_we_i) begin if (wb_sel_i[2] & wb_we_i) begin
@ -693,11 +701,13 @@ module housekeeping #(
end end
end end
`WBBD_RW2: begin `WBBD_RW2: begin
wbbd_busy <= 1'b1;
wbbd_sck <= 1'b1; wbbd_sck <= 1'b1;
wb_dat_o[23:16] <= odata; wb_dat_o[23:16] <= odata;
wbbd_state <= `WBBD_SETUP3; wbbd_state <= `WBBD_SETUP3;
end end
`WBBD_SETUP3: begin `WBBD_SETUP3: begin
wbbd_busy <= 1'b1;
wbbd_sck <= 1'b0; wbbd_sck <= 1'b0;
wbbd_addr <= spiaddr(wb_adr_i + 3); wbbd_addr <= spiaddr(wb_adr_i + 3);
if (wb_sel_i[3] & wb_we_i) begin if (wb_sel_i[3] & wb_we_i) begin
@ -709,12 +719,14 @@ module housekeeping #(
end end
end end
`WBBD_RW3: begin `WBBD_RW3: begin
wbbd_busy <= 1'b1;
wbbd_sck <= 1'b1; wbbd_sck <= 1'b1;
wb_dat_o[31:24] <= odata; wb_dat_o[31:24] <= odata;
wb_ack_o <= 1'b1; // Release hold on wishbone bus wb_ack_o <= 1'b1; // Release hold on wishbone bus
wbbd_state <= `WBBD_DONE; wbbd_state <= `WBBD_DONE;
end end
`WBBD_DONE: begin `WBBD_DONE: begin
wbbd_busy <= 1'b1;
wbbd_sck <= 1'b0; wbbd_sck <= 1'b0;
wb_ack_o <= 1'b0; // Reset for next access wb_ack_o <= 1'b0; // Reset for next access
wbbd_write <= 1'b0; wbbd_write <= 1'b0;
@ -964,13 +976,15 @@ module housekeeping #(
// SPI Data transfer protocol. The wishbone back door may only be // SPI Data transfer protocol. The wishbone back door may only be
// used if the front door is closed (CSB is high or the CSB pin is // used if the front door is closed (CSB is high or the CSB pin is
// not an input). To do: Provide an independent way to disable // not an input). The time to apply values for the back door access
// the SPI. // is limited to the clock cycle around the read or write from the
// wbbd state machine (see below).
assign caddr = (wbbd_busy) ? wbbd_addr : iaddr;
assign csclk = (wbbd_busy) ? wbbd_sck : ((spi_is_active) ? mgmt_gpio_in[4] : 1'b0);
assign cdata = (wbbd_busy) ? wbbd_data : idata;
assign cwstb = (wbbd_busy) ? wbbd_write : wrstb;
assign caddr = (spi_is_busy) ? iaddr : wbbd_addr;
assign csclk = (spi_is_busy) ? mgmt_gpio_in[4] : wbbd_sck;
assign cdata = (spi_is_busy) ? idata : wbbd_data;
assign cwstb = (spi_is_busy) ? wrstb : wbbd_write;
assign odata = fdata(caddr); assign odata = fdata(caddr);
// Register mapping and I/O to SPI interface module // Register mapping and I/O to SPI interface module