Modified the housekeeping SPI to generate a read strobe (or rather

status) so that between rdstb and wrstb, the SPI signals when it is
about to read or write a byte.  The back-door wishbone interface then
stalls the CPU during these periods.  That allows the CPU to continue
running while the SPI is being accessed without data collisions and
without having to stall for the entire time CSB is held low.
Because SCK is asynchronous to the clock, rare collisions are still
possible;  this is not expected to be an issue but might be worth
investigating.
This commit is contained in:
Tim Edwards 2021-10-23 22:06:24 -04:00
parent e5c90daddd
commit e6a94449ce
2 changed files with 39 additions and 19 deletions

View File

@ -653,8 +653,13 @@ module housekeeping #(
wbbd_data <= wb_dat_i[7:0];
end
wbbd_write <= wb_sel_i[0] & wb_we_i;
// If the SPI is being accessed and about to read or
// write a byte, then stall until the SPI is ready.
if (!spi_is_busy) begin
wbbd_state <= `WBBD_RW0;
end
end
`WBBD_RW0: begin
wbbd_sck <= 1'b1;
wb_dat_o[7:0] <= odata;
@ -667,8 +672,10 @@ module housekeeping #(
wbbd_data <= wb_dat_i[15:8];
end
wbbd_write <= wb_sel_i[1] & wb_we_i;
if (!spi_is_busy) begin
wbbd_state <= `WBBD_RW1;
end
end
`WBBD_RW1: begin
wbbd_sck <= 1'b1;
wb_dat_o[15:8] <= odata;
@ -681,8 +688,10 @@ module housekeeping #(
wbbd_data <= wb_dat_i[23:16];
end
wbbd_write <= wb_sel_i[2] & wb_we_i;
if (!spi_is_busy) begin
wbbd_state <= `WBBD_RW2;
end
end
`WBBD_RW2: begin
wbbd_sck <= 1'b1;
wb_dat_o[23:16] <= odata;
@ -695,8 +704,10 @@ module housekeeping #(
wbbd_data <= wb_dat_i[31:24];
end
wbbd_write <= wb_sel_i[3] & wb_we_i;
if (!spi_is_busy) begin
wbbd_state <= `WBBD_RW3;
end
end
`WBBD_RW3: begin
wbbd_sck <= 1'b1;
wb_dat_o[31:24] <= odata;
@ -736,9 +747,13 @@ module housekeeping #(
);
// SPI is considered active when the GPIO for CSB is set to input and
// CSB is low.
// CSB is low. SPI is considered "busy" when rdstb or wrstb are high,
// indicating that the SPI will read or write a byte on the next SCK
// transition.
wire spi_is_enabled = (~gpio_configure[3][INP_DIS]) & (~hkspi_disable);
wire spi_is_active = spi_is_enabled && (mgmt_gpio_in[3] == 1'b0);
wire spi_is_busy = spi_is_active && (rdstb || wrstb);
// GPIO data handling to and from the management SoC
@ -952,10 +967,10 @@ module housekeeping #(
// not an input). To do: Provide an independent way to disable
// the SPI.
assign caddr = (spi_is_active) ? iaddr : wbbd_addr;
assign csclk = (spi_is_active) ? mgmt_gpio_in[4] : wbbd_sck;
assign cdata = (spi_is_active) ? idata : wbbd_data;
assign cwstb = (spi_is_active) ? wrstb : wbbd_write;
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);
// Register mapping and I/O to SPI interface module

View File

@ -35,7 +35,7 @@
// idata --- Data from chip to transmit out, in 8 bits
// odata --- Input data to chip, in 8 bits
// addr --- Decoded address to upstream circuits
// rdstb --- Read strobe, tells upstream circuit to supply next byte to idata
// rdstb --- Read strobe, tells upstream circuit that data will be latched.
// wrstb --- Write strobe, tells upstream circuit to latch odata.
// Data format (general purpose):
@ -158,6 +158,7 @@ module housekeeping_spi(reset, SCK, SDI, CSB, SDO,
end else begin
wrstb <= 1'b0;
end
end else if (state == `MGMTPASS || state == `USERPASS) begin
wrstb <= 1'b0;
sdoenb <= 1'b0;
@ -217,13 +218,14 @@ module housekeeping_spi(reset, SCK, SDI, CSB, SDO,
count <= count + 1;
addr <= {addr[6:0], SDI};
if (count == 3'b111) begin
state <= `DATA;
if (readmode == 1'b1) begin
rdstb <= 1'b1;
end
state <= `DATA;
end else begin
rdstb <= 1'b0;
end
end else if (state == `DATA) begin
predata <= {predata[6:0], SDI};
count <= count + 1;
@ -236,6 +238,9 @@ module housekeeping_spi(reset, SCK, SDI, CSB, SDO,
end else begin
addr <= addr + 1; // Auto increment address (streaming)
end
if (readmode == 1'b1) begin
rdstb <= 1'b1;
end
end else begin
rdstb <= 1'b0;
end