mirror of https://github.com/efabless/caravel.git
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:
parent
e5c90daddd
commit
e6a94449ce
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue