|
@@ -61,9 +61,15 @@ module abcbus (
|
|
|
output reg sdram_wstrb
|
|
|
);
|
|
|
|
|
|
+ // SDRAM base address, used for reading back the map registers
|
|
|
+ parameter [31:0] sdram_base_addr;
|
|
|
+
|
|
|
// Set if MOSFETs Q1-Q6 are installed rather than the corresponding
|
|
|
// resistors. BOTH CANNOT BE INSTALLED AT THE SAME TIME.
|
|
|
parameter [6:1] mosfet_installed = 6'b111_111;
|
|
|
+
|
|
|
+ // Are the auxiliary extension header bits reversed (this may be
|
|
|
+ // programmable in the future depending on orientation of the header)?
|
|
|
parameter [0:0] exth_reversed = 1'b0;
|
|
|
|
|
|
// Synchronizer for ABC-bus input signals; also changes
|
|
@@ -103,26 +109,45 @@ module abcbus (
|
|
|
wire abc80 = abc_xinpstb_s & abc_xoutpstb_s;
|
|
|
wire abc800 = ~abc80;
|
|
|
|
|
|
+ wire xinpstb_s = (abc800 & abc_xinpstb_s) | (|abc_inp_s);
|
|
|
+ wire xoutpstb_s = (abc800 & abc_xinpstb_s) | (|abc_out_s);
|
|
|
// Memory and I/O read/write strobes for ABC-bus
|
|
|
reg abc_xmemrd;
|
|
|
reg abc_xmemwr;
|
|
|
+ reg abc_xinpstb;
|
|
|
+ reg abc_xoutpstb;
|
|
|
reg [1:0] abc_inp;
|
|
|
reg [4:0] abc_out;
|
|
|
reg abc_rst;
|
|
|
reg abc_cs;
|
|
|
reg [3:1] abc_stb; // Delayed strobes
|
|
|
|
|
|
- always @(posedge sdram_clk)
|
|
|
+ always @(negedge rst_n or posedge sdram_clk)
|
|
|
+ if (~rst_n)
|
|
|
+ begin
|
|
|
+ abc_xmemrd <= 1'b0;
|
|
|
+ abc_xmemwr <= 1'b0;
|
|
|
+ abc_inp <= 2'b0;
|
|
|
+ abc_out <= 5'b0;
|
|
|
+ abc_xinpstb <= 1'b0;
|
|
|
+ abc_xoutpstb <= 1'b0;
|
|
|
+ abc_rst <= 1'b0;
|
|
|
+ abc_cs <= 1'b0;
|
|
|
+ abc_stb <= 'b0;
|
|
|
+ end
|
|
|
+ else
|
|
|
begin
|
|
|
abc_xmemrd <= abc_clk_active & abc_xmemfl_s;
|
|
|
abc_xmemwr <= abc_clk_active &
|
|
|
(abc800 ? abc_xmemw800_s : abc_xmemw80_s);
|
|
|
abc_inp <= abc_inp_s & {2{abc_clk_active}};
|
|
|
abc_out <= abc_out_s & {5{abc_clk_active}};
|
|
|
+ abc_xinpstb <= xinpstb_s & abc_clk_active;
|
|
|
+ abc_xoutpstb <= xoutpstb_s & abc_clk_active;
|
|
|
abc_rst <= abc_rst_s & abc_clk_active;
|
|
|
abc_cs <= abc_cs_s & abc_clk_active;
|
|
|
- abc_stb <= { abc_stb, |{abc_inp, abc_out, abc_rst,
|
|
|
- abc_cs, abc_xmemrd, abc_xmemwr} };
|
|
|
+ abc_stb <= { abc_stb,
|
|
|
+ abc_xinpstb|abc_xoutpstb|abc_xmemrd|abc_xmemwr };
|
|
|
end
|
|
|
|
|
|
reg [7:0] abc_do;
|
|
@@ -245,41 +270,47 @@ module abcbus (
|
|
|
// ABC SDRAM interface
|
|
|
//
|
|
|
// Memory map for ABC-bus memory references.
|
|
|
- // 512 byte granularity for memory (registers 0-127),
|
|
|
- // one input and one output queue per select code for I/O (128-255).
|
|
|
+ // 1024 byte granularity in two maps for memory (registers 0-127).
|
|
|
//
|
|
|
- // bit [15:0] = SDRAM address [24:9] ( bits 24:9 from CPU )
|
|
|
- // bit [16] = write enable ( bit 30 from CPU )
|
|
|
- // bit [17] = read enable ( bit 31 from CPU )
|
|
|
+ // For simplicity, the data bits from the CPU are reorganized
|
|
|
+ // so the SDRAM address is the same as the CPU uses.
|
|
|
//
|
|
|
- // Accesses from the internal CPU supports 32-bit accesses only!
|
|
|
+ // bit [14:0] = SDRAM address [24:10] ( bits 24:10 from RV32 )
|
|
|
+ // bit [15] = write enable ( bit 0 from RV32 )
|
|
|
+ // bit [16] = read enable ( bit 1 from RV32 )
|
|
|
+ // bit [17] = assert XM# ( bit 2 from RV32 )
|
|
|
//
|
|
|
- wire [17:0] rdata_abcmemmap;
|
|
|
- wire [17:0] abc_memmap_rd;
|
|
|
-
|
|
|
- abcmapram abcmapram (
|
|
|
- .aclr ( ~rst_n ),
|
|
|
+ // Accesses from RV32 supports 32-bit accesses only!
|
|
|
+ //
|
|
|
+ logic abc_a_map;
|
|
|
+ wire [17:0] rdata_abcmemmap; // RV32 access port
|
|
|
+ wire [17:0] abc_memmap_rd; // ABC-bus access port
|
|
|
|
|
|
- .clock ( sdram_clk ),
|
|
|
+ abcmapram
|
|
|
+ (
|
|
|
+ .aclr ( ~rst_n ),
|
|
|
|
|
|
- .address_a ( abc_a_s[15:9] ),
|
|
|
- .data_a ( 18'bx ),
|
|
|
- .wren_a ( 1'b0 ),
|
|
|
- .q_a ( abc_memmap_rd ),
|
|
|
+ .clock ( sdram_clk ),
|
|
|
|
|
|
- .address_b ( cpu_addr[8:2] ),
|
|
|
- .data_b ( { cpu_wdata[31:30], cpu_wdata[24:9] } ),
|
|
|
- .wren_b ( map_valid & cpu_wstrb[0] ),
|
|
|
+ .address_a ( { abc_a_map, abc_a_s[15:10] } ),
|
|
|
+ .data_a ( 18'bx ),
|
|
|
+ .wren_a ( 1'b0 ),
|
|
|
+ .q_a ( abc_memmap_rd ),
|
|
|
|
|
|
- .q_b ( rdata_abcmemmap )
|
|
|
- );
|
|
|
+ .address_b ( cpu_addr[8:2] ),
|
|
|
+ .data_b ( { cpu_wdata[2:0], cpu_wdata[24:10] } ),
|
|
|
+ .wren_b ( map_valid & cpu_wstrb[0] ),
|
|
|
|
|
|
- assign cpu_rdata_map = { rdata_abcmemmap[17:16], 5'b0,
|
|
|
- rdata_abcmemmap[15:0], 9'b0 };
|
|
|
+ .q_b ( rdata_abcmemmap )
|
|
|
+ );
|
|
|
|
|
|
- wire abc_rden = abc_memmap_rd[17];
|
|
|
- wire abc_wren = abc_memmap_rd[16];
|
|
|
- wire [24:0] abc_memaddr = { abc_memmap_rd[15:0], abc_a_s[8:0] };
|
|
|
+ assign cpu_rdata_map = sdram_base_addr | // Fixed bits
|
|
|
+ { 7'b0, rdata_abcmemmap[14:0], // Address
|
|
|
+ 7'b0, rdata_abcmemmap[17:15] }; // Flags
|
|
|
+ wire abc_xmen = abc_memmap_rd[17];
|
|
|
+ wire abc_rden = abc_memmap_rd[16];
|
|
|
+ wire abc_wren = abc_memmap_rd[15];
|
|
|
+ wire [24:0] abc_memaddr = { abc_memmap_rd[14:0], abc_a_s[9:0] };
|
|
|
|
|
|
reg abc_memrd_en;
|
|
|
reg abc_memwr_en;
|
|
@@ -295,6 +326,7 @@ module abcbus (
|
|
|
abc_do_memwr <= 1'b0;
|
|
|
sdram_valid <= 1'b0;
|
|
|
sdram_wstrb <= 1'b0;
|
|
|
+ abc_xm <= 1'b0;
|
|
|
end
|
|
|
else
|
|
|
begin
|
|
@@ -309,12 +341,15 @@ module abcbus (
|
|
|
|
|
|
sdram_valid <= abc_do_memrd | abc_do_memwr;
|
|
|
sdram_wstrb <= abc_do_memwr;
|
|
|
+
|
|
|
+ abc_xm <= abc_xmen;
|
|
|
end // else: !if(~rst_n)
|
|
|
|
|
|
assign sdram_addr = abc_memaddr;
|
|
|
assign sdram_wd = abc_di;
|
|
|
|
|
|
- // I/O data registers; RST# is considered OUT 7 even through
|
|
|
+ //
|
|
|
+ // 4680 data registers; RST# is considered OUT 7 even through
|
|
|
// it is an IN from the ABC point of view.
|
|
|
//
|
|
|
// OUT register, written from ABC: <addr 2:0> <data 7:0>
|
|
@@ -365,7 +400,7 @@ module abcbus (
|
|
|
abc_wait <= abc_wait_force | (rst_n & |set_busy & is_busy);
|
|
|
|
|
|
//
|
|
|
- // I/O data registers
|
|
|
+ // 4680 bus data registers
|
|
|
//
|
|
|
reg [2:0] reg_out_addr;
|
|
|
reg [7:0] reg_out_data;
|
|
@@ -391,6 +426,46 @@ module abcbus (
|
|
|
end // if (|busy_io[7:0])
|
|
|
end // always @ (posedge sdram_clk)
|
|
|
|
|
|
+ //
|
|
|
+ // ABC800 non-4680 I/O ports
|
|
|
+ //
|
|
|
+ reg abc800mac_en = 1'b0;
|
|
|
+ reg [7:1] abc800mac_iobase = 7'b0;
|
|
|
+ reg [15:0] abc800mac_xmmask = 16'b0;
|
|
|
+ wire abc800mac_avalid =
|
|
|
+ abc800mac_en && abc_a_s[7:1] == abc800mac_iobase;
|
|
|
+ wire cpu_xmmask = rst_n && abc_valid && cpu_addr[6:2] == 5'b01001;
|
|
|
+
|
|
|
+ // XMMASK logic (abc800mac_en is handled with other CPU registers)
|
|
|
+ always @(posedge sdram_clk)
|
|
|
+ begin
|
|
|
+ if (abc_xoutpstb & abc800mac_avalid & !abc_a_s[0])
|
|
|
+ abc800mac_xmmask[7:0] <= abc_di;
|
|
|
+ else if (cpu_xmmask & cpu_wstrb[0])
|
|
|
+ abc800mac_xmmask[7:0] <= cpu_wdata[7:0];
|
|
|
+
|
|
|
+ if (abc_xoutpstb & abc800mac_avalid & abc_a_s[1])
|
|
|
+ abc800mac_xmmask[15:8] <= abc_di;
|
|
|
+ else if (cpu_xmmask & cpu_wstrb[1])
|
|
|
+ abc800mac_xmmask[15:8] <= cpu_wdata[15:8];
|
|
|
+ end // always @ (posedge sdram_clk)
|
|
|
+
|
|
|
+ //
|
|
|
+ // "ROM hack" map control logic
|
|
|
+ //
|
|
|
+ reg romhack_en = 1'b0; // Enable
|
|
|
+ reg [5:0] romhack_addr = 6'b0; // Address mask (1K granular)
|
|
|
+ reg romhack_map = 1'b0; // Current map
|
|
|
+ wire cpu_romhackmap = rst_n && abc_valid && cpu_addr[6:2] == 5'b01011;
|
|
|
+
|
|
|
+ always @(posedge sdram_clk)
|
|
|
+ begin
|
|
|
+ if (abc_xmemwr & romhack_en & (abc_a_s[15:10] == romhack_addr))
|
|
|
+ romhack_map <= abc_a_s[0];
|
|
|
+ else if (cpu_romhackmap & cpu_wstrb[0])
|
|
|
+ romhack_map <= cpu_wdata[0];
|
|
|
+ end
|
|
|
+
|
|
|
//
|
|
|
// ABC data out (= ABC host read) logic
|
|
|
//
|
|
@@ -424,8 +499,28 @@ module abcbus (
|
|
|
abc_d_oe <= 1'b1;
|
|
|
abc_do <= reg_inp_data[1];
|
|
|
end
|
|
|
+ else if (abc_xinpstb & abc800mac_avalid)
|
|
|
+ begin
|
|
|
+ abc_d_oe <= 1'b1;
|
|
|
+ case (abc_a_s[0])
|
|
|
+ 1'b0: abc_do <= abc800mac_xmmask[7:0];
|
|
|
+ 1'b1: abc_do <= abc800mac_xmmask[15:8];
|
|
|
+ endcase // case (abc_a_s[0])
|
|
|
+ end
|
|
|
end // else: !if(~rst_n)
|
|
|
|
|
|
+ //
|
|
|
+ // Memory map control logic
|
|
|
+ //
|
|
|
+ always_comb
|
|
|
+ begin
|
|
|
+ abc_a_map = 1'b0;
|
|
|
+ if (abc800mac_en)
|
|
|
+ abc_a_map |= abc800mac_xmmask[abc_a_s[15:12]];
|
|
|
+ if (romhack_en)
|
|
|
+ abc_a_map |= romhack_map;
|
|
|
+ end
|
|
|
+
|
|
|
// Memory read latency counter
|
|
|
reg [7:0] memrd_latency_ctr = 'b0;
|
|
|
reg [7:0] memrd_latency_max = 'b0;
|
|
@@ -477,6 +572,8 @@ module abcbus (
|
|
|
inp_en <= 2'b00;
|
|
|
bus_change_status <= 4'b0;
|
|
|
bus_change_mask <= 4'b0;
|
|
|
+ abc800mac_en <= 1'b0;
|
|
|
+ romhack_en <= 1'b0;
|
|
|
|
|
|
// abc_resin, nmi, int and force_wait are deliberately not affected
|
|
|
// by an internal CPU reset. They are, however, inherently asserted
|
|
@@ -490,8 +587,8 @@ module abcbus (
|
|
|
|
|
|
if (abc_valid)
|
|
|
begin
|
|
|
- casez (cpu_addr[5:2] )
|
|
|
- 5'b??010: begin
|
|
|
+ casez (cpu_addr[6:2] )
|
|
|
+ 5'b00010: begin
|
|
|
if (cpu_wstrb[0])
|
|
|
busy_status[7:0] <= set_busy[7:0] | (busy_status[7:0] & ~cpu_wdata[7:0]);
|
|
|
if (cpu_wstrb[1])
|
|
@@ -507,7 +604,7 @@ module abcbus (
|
|
|
bus_change_mask <= cpu_wdata[31:28] & bus_change_valid;
|
|
|
end
|
|
|
end
|
|
|
- 5'b??011: begin
|
|
|
+ 5'b00011: begin
|
|
|
if (cpu_wstrb[0])
|
|
|
begin
|
|
|
abc_resin <= cpu_wdata[3];
|
|
@@ -516,17 +613,31 @@ module abcbus (
|
|
|
abc_wait_force <= cpu_wdata[0];
|
|
|
end
|
|
|
end
|
|
|
- 5'b??101: begin
|
|
|
+ 5'b00101: begin
|
|
|
if (cpu_wstrb[0])
|
|
|
reg_inp_data[0] <= cpu_wdata[7:0];
|
|
|
+ if (cpu_wstrb[1])
|
|
|
+ reg_inp_data[1] <= cpu_wdata[15:8];
|
|
|
+ if (cpu_wstrb[2])
|
|
|
+ inp_en <= cpu_wdata[17:16];
|
|
|
+ end
|
|
|
+ 5'b01000: begin
|
|
|
+ if (cpu_wstrb[0])
|
|
|
+ abc800mac_iobase <= cpu_wdata[7:1];
|
|
|
+ if (cpu_wstrb[3])
|
|
|
+ abc800mac_en <= cpu_wdata[31];
|
|
|
+ end
|
|
|
+ // 5'b01001: abc800mac_xmdata - handled elsewhere
|
|
|
+ 5'b01010: begin
|
|
|
if (cpu_wstrb[1])
|
|
|
- reg_inp_data[1] <= cpu_wdata[15:8];
|
|
|
- if (cpu_wstrb[2])
|
|
|
- inp_en <= cpu_wdata[17:16];
|
|
|
- end
|
|
|
+ romhack_addr <= cpu_wdata[15:10];
|
|
|
+ if (cpu_wstrb[3])
|
|
|
+ romhack_en <= cpu_wdata[31];
|
|
|
+ end
|
|
|
+ // 5'b01011: romhack_map - handled elsewhere
|
|
|
default:
|
|
|
/* do nothing */ ;
|
|
|
- endcase // casez (cpu_addr[5:2])
|
|
|
+ endcase // casez (cpu_addr[6:2])
|
|
|
end // if (abc_valid & cpu_wstrb[0])
|
|
|
end
|
|
|
|
|
@@ -545,7 +656,11 @@ module abcbus (
|
|
|
5'b00100: cpu_rdata = { 21'b0, reg_out_addr, reg_out_data };
|
|
|
5'b00101: cpu_rdata = { 14'b0, inp_en, reg_inp_data[1], reg_inp_data[0] };
|
|
|
5'b00111: cpu_rdata = { 23'b0, memrd_latency_err, memrd_latency_max };
|
|
|
+ 5'b01000: cpu_rdata = { abc800mac_en, 23'b0, abc800mac_iobase, 1'b0 };
|
|
|
+ 5'b01001: cpu_rdata = { 16'b0, abc800mac_xmmask };
|
|
|
+ 5'b01010: cpu_rdata = { romhack_en, 15'b0, romhack_addr, 10'b0 };
|
|
|
+ 5'b01011: cpu_rdata = { 31'b0, romhack_map };
|
|
|
default: cpu_rdata = 32'bx;
|
|
|
- endcase // casez (cpu_addr[5:2])
|
|
|
+ endcase // casez (cpu_addr[6:2])
|
|
|
|
|
|
endmodule // abcbus
|