|
@@ -40,29 +40,35 @@ module spirom (
|
|
|
reg [23:2] datalen;
|
|
|
reg [2:0] cmdlen;
|
|
|
reg go_spi;
|
|
|
+ reg is_spi;
|
|
|
reg go_ram;
|
|
|
reg is_ram;
|
|
|
reg spi_dual;
|
|
|
reg spi_more; // Do not raise CS# after command done
|
|
|
reg ram_done;
|
|
|
reg ram_done_q;
|
|
|
+ reg cpu_wr_q;
|
|
|
reg [31:0] spi_in_shr; // Input shift register for one-bit input
|
|
|
wire spi_active_s;
|
|
|
|
|
|
- always @(negedge rst_n or posedge sys_clk)
|
|
|
+ wire cpu_wr_w = cpu_valid & cpu_wstrb[0];
|
|
|
+
|
|
|
+ always @(negedge rst_n or posedge ram_clk)
|
|
|
if (~rst_n)
|
|
|
begin
|
|
|
ramstart <= 23'b0;
|
|
|
romcmd <= 32'b0;
|
|
|
datalen <= 22'b0;
|
|
|
- cmdlen <= 3'bx;
|
|
|
+ cmdlen <= 3'b0;
|
|
|
go_spi <= 1'b0;
|
|
|
+ is_spi <= 1'b0;
|
|
|
go_ram <= 1'b0;
|
|
|
is_ram <= 1'b0;
|
|
|
ram_done_q <= 1'b1;
|
|
|
irq <= 1'b1;
|
|
|
spi_dual <= 1'b0;
|
|
|
spi_more <= 1'b0;
|
|
|
+ cpu_wr_q <= 1'b0;
|
|
|
end
|
|
|
else
|
|
|
begin
|
|
@@ -76,7 +82,10 @@ module spirom (
|
|
|
if (ram_done_q & ~go_ram & ~spi_active_s & ~go_spi)
|
|
|
irq <= 1'b1;
|
|
|
|
|
|
- if (cpu_valid & cpu_wstrb[0])
|
|
|
+ cpu_wr_q <= cpu_wr_w;
|
|
|
+
|
|
|
+ // Don't allow writing unless the unit is idle (IRQ = 1)
|
|
|
+ if (cpu_wr_w & ~cpu_wr_q & irq)
|
|
|
begin
|
|
|
// Only full word accesses supported via DMA!!
|
|
|
case (cpu_addr)
|
|
@@ -90,10 +99,12 @@ module spirom (
|
|
|
datalen <= cpu_wdata[23:2];
|
|
|
cmdlen <= cpu_wdata[26:24];
|
|
|
go_spi <= cpu_wdata[26:24] != 3'd0;
|
|
|
+ is_spi <= cpu_wdata[26:24] != 3'd0;
|
|
|
spi_dual <= cpu_wdata[27];
|
|
|
spi_more <= cpu_wdata[28];
|
|
|
is_ram <= cpu_wdata[29];
|
|
|
- go_ram <= cpu_wdata[29] & |cpu_wdata[23:2];
|
|
|
+ go_ram <= cpu_wdata[29];
|
|
|
+ irq <= 1'b0;
|
|
|
end
|
|
|
default: begin
|
|
|
// Do nothing
|
|
@@ -104,12 +115,12 @@ module spirom (
|
|
|
|
|
|
always_comb
|
|
|
case (cpu_addr)
|
|
|
- 3'b000: cpu_rdata = { 7'b0, ramstart, 2'b0 };
|
|
|
- 3'b001: cpu_rdata = romcmd;
|
|
|
- 3'b010: cpu_rdata = { 2'b0, is_ram, spi_more, spi_dual,
|
|
|
- cmdlen, datalen, 2'b0 };
|
|
|
- 3'b011: cpu_rdata = { 31'b0, irq };
|
|
|
- 3'b100: cpu_rdata = spi_in_shr;
|
|
|
+ 3'b000: cpu_rdata = { 7'b0, ramstart, 2'b0 };
|
|
|
+ 3'b001: cpu_rdata = romcmd;
|
|
|
+ 3'b010: cpu_rdata = { 2'b0, is_ram, spi_more, spi_dual,
|
|
|
+ cmdlen, datalen, 2'b0 };
|
|
|
+ 3'b011: cpu_rdata = { 31'b0, irq };
|
|
|
+ 3'b100: cpu_rdata = spi_in_shr;
|
|
|
default: cpu_rdata = 32'bx;
|
|
|
endcase // case (cpu_addr)
|
|
|
|
|
@@ -122,7 +133,6 @@ module spirom (
|
|
|
wire [11:0] wrusedw;
|
|
|
wire [8:0] rdusedw;
|
|
|
wire [15:0] fifo_out;
|
|
|
- reg from_spi;
|
|
|
|
|
|
ddufifo spirom_fifo (
|
|
|
.aclr ( ~rst_n ),
|
|
@@ -134,7 +144,7 @@ module spirom (
|
|
|
|
|
|
.rdclk ( ram_clk ),
|
|
|
.q ( fifo_out ),
|
|
|
- .rdreq ( wacc & from_spi ),
|
|
|
+ .rdreq ( wacc & is_spi ),
|
|
|
.rdusedw ( rdusedw )
|
|
|
);
|
|
|
|
|
@@ -144,21 +154,24 @@ module spirom (
|
|
|
// Shuffle fifo_out because SPI brings in data in bigendian bit
|
|
|
// order within bytes, but the FIFO IP assumes littleendian
|
|
|
//
|
|
|
- assign wd[ 7: 6] = {2{from_spi}} & fifo_out[ 1: 0];
|
|
|
- assign wd[ 5: 4] = {2{from_spi}} & fifo_out[ 3: 2];
|
|
|
- assign wd[ 3: 2] = {2{from_spi}} & fifo_out[ 5: 4];
|
|
|
- assign wd[ 1: 0] = {2{from_spi}} & fifo_out[ 7: 6];
|
|
|
+ wire [15:0] spi_wd;
|
|
|
|
|
|
- assign wd[15:14] = {2{from_spi}} & fifo_out[ 9: 8];
|
|
|
- assign wd[13:12] = {2{from_spi}} & fifo_out[11:10];
|
|
|
- assign wd[11:10] = {2{from_spi}} & fifo_out[13:12];
|
|
|
- assign wd[ 9: 8] = {2{from_spi}} & fifo_out[15:14];
|
|
|
+ assign spi_wd[ 7: 6] = fifo_out[ 1: 0];
|
|
|
+ assign spi_wd[ 5: 4] = fifo_out[ 3: 2];
|
|
|
+ assign spi_wd[ 3: 2] = fifo_out[ 5: 4];
|
|
|
+ assign spi_wd[ 1: 0] = fifo_out[ 7: 6];
|
|
|
+
|
|
|
+ assign spi_wd[15:14] = fifo_out[ 9: 8];
|
|
|
+ assign spi_wd[13:12] = fifo_out[11:10];
|
|
|
+ assign spi_wd[11:10] = fifo_out[13:12];
|
|
|
+ assign spi_wd[ 9: 8] = fifo_out[15:14];
|
|
|
|
|
|
reg [24:1] waddr_q;
|
|
|
reg [23:1] ram_data_ctr;
|
|
|
reg wacc_q;
|
|
|
|
|
|
assign waddr = waddr_q;
|
|
|
+ assign wd = is_spi ? spi_wd : 16'h0000;
|
|
|
|
|
|
always @(negedge rst_n or posedge ram_clk)
|
|
|
if (~rst_n)
|
|
@@ -171,11 +184,13 @@ module spirom (
|
|
|
end
|
|
|
else
|
|
|
begin
|
|
|
+ wacc_q <= wacc;
|
|
|
+
|
|
|
if (|ram_data_ctr)
|
|
|
begin
|
|
|
ram_done <= 1'b0;
|
|
|
|
|
|
- if (from_spi)
|
|
|
+ if (is_spi)
|
|
|
begin
|
|
|
// Reading from SPI ROM
|
|
|
wrq[0] <= rdusedw >= 9'd4; // 4*2 = 8 bytes min available
|
|
@@ -188,8 +203,7 @@ module spirom (
|
|
|
wrq[1] <= |ram_data_ctr[23:4];
|
|
|
end
|
|
|
|
|
|
- wacc_q <= wacc;
|
|
|
- waddr_q <= waddr_q + wacc_q;
|
|
|
+ waddr_q <= waddr_q + wacc_q;
|
|
|
ram_data_ctr <= ram_data_ctr - wacc_q;
|
|
|
end // if (|ram_data_ctr)
|
|
|
else
|
|
@@ -201,7 +215,7 @@ module spirom (
|
|
|
begin
|
|
|
waddr_q <= { ramstart, 1'b0 };
|
|
|
ram_data_ctr <= { datalen, 1'b0 };
|
|
|
- from_spi <= |cmdlen;
|
|
|
+ ram_done <= 1'b0;
|
|
|
end
|
|
|
end
|
|
|
end // else: !if(~rst_n)
|
|
@@ -288,7 +302,7 @@ module spirom (
|
|
|
if ( spi_cmd_ctr == 6'd1 )
|
|
|
spi_mosi_en <= ~spi_dual;
|
|
|
|
|
|
- if ( spi_cmd_ctr == 6'd0 )
|
|
|
+ if ( ~|spi_cmd_ctr )
|
|
|
begin
|
|
|
spi_in_req <= 1'b1;
|
|
|
spi_data_ctr <= spi_data_ctr - 1'b1;
|