mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Connected AHB bus to Uncore
This commit is contained in:
parent
73a584b223
commit
a357f2a0e7
@ -61,14 +61,14 @@
|
||||
// Peripheral memory space extends from BASE to BASE+RANGE
|
||||
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
|
||||
|
||||
`define TIMBASE 64'h0000000080000000
|
||||
`define TIMRANGE 64'h000000000007FFFF
|
||||
`define CLINTBASE 64'h0000000002000000
|
||||
`define CLINTRANGE 64'h000000000000FFFF
|
||||
`define GPIOBASE 64'h0000000010012000
|
||||
`define GPIORANGE 64'h00000000000000FF
|
||||
`define UARTBASE 64'h0000000010000000
|
||||
`define UARTRANGE 64'h0000000000000007
|
||||
`define TIMBASE 32'h80000000
|
||||
`define TIMRANGE 32'h0007FFFF
|
||||
`define CLINTBASE 32'h02000000
|
||||
`define CLINTRANGE 32'h0000FFFF
|
||||
`define GPIOBASE 32'h10012000
|
||||
`define GPIORANGE 32'h000000FF
|
||||
`define UARTBASE 32'h10000000
|
||||
`define UARTRANGE 32'h00000007
|
||||
|
||||
// Bus Interface width
|
||||
`define AHBW 32
|
||||
|
@ -65,14 +65,14 @@
|
||||
// Peripheral memory space extends from BASE to BASE+RANGE
|
||||
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
|
||||
|
||||
`define TIMBASE 64'h0000000080000000
|
||||
`define TIMRANGE 64'h000000000007FFFF
|
||||
`define CLINTBASE 64'h0000000002000000
|
||||
`define CLINTRANGE 64'h000000000000FFFF
|
||||
`define GPIOBASE 64'h0000000010012000
|
||||
`define GPIORANGE 64'h00000000000000FF
|
||||
`define UARTBASE 64'h0000000010000000
|
||||
`define UARTRANGE 64'h0000000000000007
|
||||
`define TIMBASE 32'h80000000
|
||||
`define TIMRANGE 32'h0007FFFF
|
||||
`define CLINTBASE 32'h02000000
|
||||
`define CLINTRANGE 32'h0000FFFF
|
||||
`define GPIOBASE 32'h10012000
|
||||
`define GPIORANGE 32'h000000FF
|
||||
`define UARTBASE 32'h10000000
|
||||
`define UARTRANGE 32'h00000007
|
||||
|
||||
// Test modes
|
||||
|
||||
|
@ -64,8 +64,8 @@ add wave -divider
|
||||
#add wave -hex /testbench/dut/hart/ifu/InstrM
|
||||
add wave /testbench/InstrMName
|
||||
add wave /testbench/dut/uncore/dtim/memwrite
|
||||
add wave -hex /testbench/dut/uncore/AdrM
|
||||
add wave -hex /testbench/dut/uncore/WriteDataM
|
||||
add wave -hex /testbench/dut/uncore/HADDR
|
||||
add wave -hex /testbench/dut/uncore/HWDATA
|
||||
add wave -divider
|
||||
add wave -hex /testbench/dut/hart/ifu/PCW
|
||||
add wave /testbench/InstrWName
|
||||
|
@ -26,19 +26,19 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module adrdec (
|
||||
input logic [`XLEN-1:0] AdrM,
|
||||
input logic [`XLEN-1:0] Base, Range,
|
||||
output logic En
|
||||
input logic [31:0] HADDR,
|
||||
input logic [31:0] Base, Range,
|
||||
output logic HSEL
|
||||
);
|
||||
|
||||
logic [`XLEN-1:0] match;
|
||||
logic [31:0] match;
|
||||
|
||||
// determine if an address is in a range starting at the base
|
||||
// for example, if Base = 0x04002000 and range = 0x00000FFF,
|
||||
// then anything address between 0x04002000 and 0x04002FFF should match (En=1)
|
||||
// then anything address between 0x04002000 and 0x04002FFF should match (HSEL=1)
|
||||
|
||||
assign match = (AdrM ~^ Base) | Range;
|
||||
assign En = &match;
|
||||
assign match = (HADDR ~^ Base) | Range;
|
||||
assign HSEL = &match;
|
||||
|
||||
endmodule
|
||||
|
||||
|
@ -32,6 +32,8 @@
|
||||
|
||||
module ahblite (
|
||||
input logic clk, reset,
|
||||
// Load control
|
||||
input logic UnsignedLoadM,
|
||||
// Signals from Instruction Cache
|
||||
input logic [`XLEN-1:0] IPAdrD,
|
||||
input logic IReadD,
|
||||
@ -60,6 +62,7 @@ module ahblite (
|
||||
logic HCLK, HRESETn;
|
||||
logic GrantData;
|
||||
logic [2:0] ISize;
|
||||
logic [`AHBW-1:0] HRDATAMasked;
|
||||
|
||||
assign HCLK = clk;
|
||||
assign HRESETn = ~reset;
|
||||
@ -77,7 +80,8 @@ module ahblite (
|
||||
|
||||
// drive bus outputs
|
||||
assign HADDR = GrantData ? DPAdrM[31:0] : IPAdrD[31:0];
|
||||
flop #(`XLEN) wdreg(HCLK, DWDataM, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN
|
||||
assign HWDATA = DWDataM;
|
||||
//flop #(`XLEN) wdreg(HCLK, DWDataM, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN
|
||||
assign HWRITE = DWriteM; // *** check no level to pulse conversion needed
|
||||
assign HSIZE = GrantData ? {1'b0, DSizeM} : ISize;
|
||||
assign HBURST = 3'b000; // Single burst only supported; consider generalizing for cache fillsfHPROT
|
||||
@ -87,13 +91,15 @@ module ahblite (
|
||||
|
||||
// Route signals to Instruction and Data Caches
|
||||
// *** assumes AHBW = XLEN
|
||||
assign IRData = HRDATA;
|
||||
assign IRData = HRDATAMasked;
|
||||
assign IReady = HREADY & IReadD & ~GrantData;
|
||||
assign DRData = HRDATA;
|
||||
assign DRData = HRDATAMasked;
|
||||
assign DReady = HREADY & GrantData;
|
||||
|
||||
// *** consider adding memory access faults based on HRESP being high
|
||||
// InstrAccessFaultF, DataAccessFaultM,
|
||||
|
||||
subwordread swr(.*);
|
||||
|
||||
endmodule
|
||||
|
||||
|
@ -27,12 +27,13 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module clint (
|
||||
input logic clk, reset,
|
||||
input logic [1:0] MemRWclintM,
|
||||
input logic [15:0] AdrM,
|
||||
input logic [`XLEN-1:0] MaskedWriteDataM,
|
||||
output logic [`XLEN-1:0] RdCLINTM,
|
||||
output logic TimerIntM, SwIntM);
|
||||
input logic clk, reset,
|
||||
input logic [1:0] MemRWclint,
|
||||
input logic [15:0] HADDR,
|
||||
input logic [`XLEN-1:0] HWDATA,
|
||||
output logic [`XLEN-1:0] HREADCLINT,
|
||||
output logic HRESPCLINT, HREADYCLINT,
|
||||
output logic TimerIntM, SwIntM);
|
||||
|
||||
logic [63:0] MTIMECMP, MTIME;
|
||||
logic MSIP;
|
||||
@ -40,15 +41,17 @@ module clint (
|
||||
logic [15:0] entry;
|
||||
logic memread, memwrite;
|
||||
|
||||
assign memread = MemRWclintM[1];
|
||||
assign memwrite = MemRWclintM[0];
|
||||
assign memread = MemRWclint[1];
|
||||
assign memwrite = MemRWclint[0];
|
||||
assign HRESPCLINT = 0; // OK
|
||||
assign HREADYCLINT = 1; // Respond immediately
|
||||
|
||||
// word aligned reads
|
||||
generate
|
||||
if (`XLEN==64)
|
||||
assign #2 entry = {AdrM[15:3], 3'b000};
|
||||
assign #2 entry = {HADDR[15:3], 3'b000};
|
||||
else
|
||||
assign #2 entry = {AdrM[15:2], 2'b00};
|
||||
assign #2 entry = {HADDR[15:2], 2'b00};
|
||||
endgenerate
|
||||
|
||||
|
||||
@ -57,10 +60,10 @@ module clint (
|
||||
if (`XLEN==64) begin
|
||||
always_comb begin
|
||||
case(entry)
|
||||
16'h0000: RdCLINTM = {63'b0, MSIP};
|
||||
16'h4000: RdCLINTM = MTIMECMP;
|
||||
16'hBFF8: RdCLINTM = MTIME;
|
||||
default: RdCLINTM = 0;
|
||||
16'h0000: HREADCLINT = {63'b0, MSIP};
|
||||
16'h4000: HREADCLINT = MTIMECMP;
|
||||
16'hBFF8: HREADCLINT = MTIME;
|
||||
default: HREADCLINT = 0;
|
||||
endcase
|
||||
end
|
||||
always_ff @(posedge clk or posedge reset)
|
||||
@ -70,21 +73,21 @@ module clint (
|
||||
MTIMECMP <= 0;
|
||||
// MTIMECMP is not reset
|
||||
end else if (memwrite) begin
|
||||
if (entry == 16'h0000) MSIP <= MaskedWriteDataM[0];
|
||||
if (entry == 16'h4000) MTIMECMP <= MaskedWriteDataM;
|
||||
if (entry == 16'h0000) MSIP <= HWDATA[0];
|
||||
if (entry == 16'h4000) MTIMECMP <= HWDATA;
|
||||
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
|
||||
if (entry == 16'hBFF8) MTIME <= MaskedWriteDataM;
|
||||
if (entry == 16'hBFF8) MTIME <= HWDATA;
|
||||
else MTIME <= MTIME + 1;
|
||||
end
|
||||
end else begin // 32-bit
|
||||
always_comb begin
|
||||
case(entry)
|
||||
16'h0000: RdCLINTM = {31'b0, MSIP};
|
||||
16'h4000: RdCLINTM = MTIMECMP[31:0];
|
||||
16'h4004: RdCLINTM = MTIMECMP[63:32];
|
||||
16'hBFF8: RdCLINTM = MTIME[31:0];
|
||||
16'hBFFC: RdCLINTM = MTIME[63:32];
|
||||
default: RdCLINTM = 0;
|
||||
16'h0000: HREADCLINT = {31'b0, MSIP};
|
||||
16'h4000: HREADCLINT = MTIMECMP[31:0];
|
||||
16'h4004: HREADCLINT = MTIMECMP[63:32];
|
||||
16'hBFF8: HREADCLINT = MTIME[31:0];
|
||||
16'hBFFC: HREADCLINT = MTIME[63:32];
|
||||
default: HREADCLINT = 0;
|
||||
endcase
|
||||
end
|
||||
always_ff @(posedge clk or posedge reset)
|
||||
@ -94,12 +97,12 @@ module clint (
|
||||
MTIMECMP <= 0;
|
||||
// MTIMECMP is not reset
|
||||
end else if (memwrite) begin
|
||||
if (entry == 16'h0000) MSIP <= MaskedWriteDataM[0];
|
||||
if (entry == 16'h4000) MTIMECMP[31:0] <= MaskedWriteDataM;
|
||||
if (entry == 16'h4004) MTIMECMP[63:32] <= MaskedWriteDataM;
|
||||
if (entry == 16'h0000) MSIP <= HWDATA[0];
|
||||
if (entry == 16'h4000) MTIMECMP[31:0] <= HWDATA;
|
||||
if (entry == 16'h4004) MTIMECMP[63:32] <= HWDATA;
|
||||
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
|
||||
if (entry == 16'hBFF8) MTIME[31:0] <= MaskedWriteDataM;
|
||||
else if (entry == 16'hBFFC) MTIME[63:32]<= MaskedWriteDataM;
|
||||
if (entry == 16'hBFF8) MTIME[31:0] <= HWDATA;
|
||||
else if (entry == 16'hBFFC) MTIME[63:32]<= HWDATA;
|
||||
else MTIME <= MTIME + 1;
|
||||
end
|
||||
end
|
||||
|
@ -169,7 +169,7 @@ module csrm #(parameter
|
||||
PMPCFG0: CSRMReadValM = PMPCFG01_REGW[`XLEN-1:0];
|
||||
PMPCFG1: CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG01_REGW[63:31]};
|
||||
PMPCFG2: CSRMReadValM = PMPCFG23_REGW[`XLEN-1:0];
|
||||
PMPCFG3: CSRMReadValM = PMPCFG23_REGW[63:31];
|
||||
PMPCFG3: CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG23_REGW[63:31]};
|
||||
PMPADDR0: CSRMReadValM = PMPADDR0_REGW;
|
||||
default: begin
|
||||
CSRMReadValM = 0;
|
||||
|
@ -27,28 +27,32 @@
|
||||
|
||||
module dtim (
|
||||
input logic clk,
|
||||
input logic [1:0] MemRWdtimM,
|
||||
input logic [1:0] MemRWtim,
|
||||
// input logic [7:0] ByteMaskM,
|
||||
input logic [18:0] AdrM,
|
||||
input logic [`XLEN-1:0] MaskedWriteDataM,
|
||||
output logic [`XLEN-1:0] RdTimM);
|
||||
input logic [18:0] HADDR,
|
||||
input logic [`XLEN-1:0] HWDATA,
|
||||
output logic [`XLEN-1:0] HREADTim,
|
||||
output logic HRESPTim, HREADYTim
|
||||
);
|
||||
|
||||
logic [`XLEN-1:0] RAM[0:65535];
|
||||
logic [`XLEN-1:0] write;
|
||||
logic [15:0] entry;
|
||||
logic memread, memwrite;
|
||||
|
||||
assign memread = MemRWdtimM[1];
|
||||
assign memwrite = MemRWdtimM[0];
|
||||
assign memread = MemRWtim[1];
|
||||
assign memwrite = MemRWtim[0];
|
||||
assign HRESPTim = 0; // OK
|
||||
assign HREADYTim= 1; // Respond immediately; *** extend this
|
||||
|
||||
// word aligned reads
|
||||
generate
|
||||
if (`XLEN==64)
|
||||
assign #2 entry = AdrM[18:3];
|
||||
assign #2 entry = HADDR[18:3];
|
||||
else
|
||||
assign #2 entry = AdrM[17:2];
|
||||
assign #2 entry = HADDR[17:2];
|
||||
endgenerate
|
||||
assign RdTimM = RAM[entry];
|
||||
assign HREADTim = RAM[entry];
|
||||
|
||||
// write each byte based on the byte mask
|
||||
// UInstantiate a byte-writable memory here if possible
|
||||
@ -58,37 +62,37 @@ module dtim (
|
||||
|
||||
if (`XLEN==64) begin
|
||||
always_comb begin
|
||||
write=RdTimM;
|
||||
if (ByteMaskM[0]) write[7:0] = WriteDataM[7:0];
|
||||
if (ByteMaskM[1]) write[15:8] = WriteDataM[15:8];
|
||||
if (ByteMaskM[2]) write[23:16] = WriteDataM[23:16];
|
||||
if (ByteMaskM[3]) write[31:24] = WriteDataM[31:24];
|
||||
if (ByteMaskM[4]) write[39:32] = WriteDataM[39:32];
|
||||
if (ByteMaskM[5]) write[47:40] = WriteDataM[47:40];
|
||||
if (ByteMaskM[6]) write[55:48] = WriteDataM[55:48];
|
||||
if (ByteMaskM[7]) write[63:56] = WriteDataM[63:56];
|
||||
write=HREADTim;
|
||||
if (ByteMaskM[0]) write[7:0] = HWDATA[7:0];
|
||||
if (ByteMaskM[1]) write[15:8] = HWDATA[15:8];
|
||||
if (ByteMaskM[2]) write[23:16] = HWDATA[23:16];
|
||||
if (ByteMaskM[3]) write[31:24] = HWDATA[31:24];
|
||||
if (ByteMaskM[4]) write[39:32] = HWDATA[39:32];
|
||||
if (ByteMaskM[5]) write[47:40] = HWDATA[47:40];
|
||||
if (ByteMaskM[6]) write[55:48] = HWDATA[55:48];
|
||||
if (ByteMaskM[7]) write[63:56] = HWDATA[63:56];
|
||||
end
|
||||
always_ff @(posedge clk)
|
||||
if (memwrite) RAM[AdrM[18:3]] <= write;
|
||||
if (memwrite) RAM[HADDR[18:3]] <= write;
|
||||
end else begin // 32-bit
|
||||
always_comb begin
|
||||
write=RdTimM;
|
||||
if (ByteMaskM[0]) write[7:0] = WriteDataM[7:0];
|
||||
if (ByteMaskM[1]) write[15:8] = WriteDataM[15:8];
|
||||
if (ByteMaskM[2]) write[23:16] = WriteDataM[23:16];
|
||||
if (ByteMaskM[3]) write[31:24] = WriteDataM[31:24];
|
||||
write=HREADTim;
|
||||
if (ByteMaskM[0]) write[7:0] = HWDATA[7:0];
|
||||
if (ByteMaskM[1]) write[15:8] = HWDATA[15:8];
|
||||
if (ByteMaskM[2]) write[23:16] = HWDATA[23:16];
|
||||
if (ByteMaskM[3]) write[31:24] = HWDATA[31:24];
|
||||
end
|
||||
always_ff @(posedge clk)
|
||||
if (memwrite) RAM[AdrM[17:2]] <= write;
|
||||
if (memwrite) RAM[HADDR[17:2]] <= write;
|
||||
end
|
||||
endgenerate */
|
||||
generate
|
||||
if (`XLEN == 64) begin
|
||||
always_ff @(posedge clk)
|
||||
if (memwrite) RAM[AdrM[17:3]] <= MaskedWriteDataM;
|
||||
if (memwrite) RAM[HADDR[17:3]] <= HWDATA;
|
||||
end else begin
|
||||
always_ff @(posedge clk)
|
||||
if (memwrite) RAM[AdrM[17:2]] <= MaskedWriteDataM;
|
||||
if (memwrite) RAM[HADDR[17:2]] <= HWDATA;
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
|
@ -28,29 +28,31 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module gpio (
|
||||
input logic clk, reset,
|
||||
input logic [1:0] MemRWgpioM,
|
||||
// input logic [7:0] ByteMaskM,
|
||||
input logic [7:0] AdrM,
|
||||
input logic [`XLEN-1:0] MaskedWriteDataM,
|
||||
output logic [`XLEN-1:0] RdGPIOM,
|
||||
input logic [31:0] GPIOPinsIn,
|
||||
output logic [31:0] GPIOPinsOut, GPIOPinsEn);
|
||||
input logic clk, reset,
|
||||
input logic [1:0] MemRWgpio,
|
||||
input logic [7:0] HADDR,
|
||||
input logic [`XLEN-1:0] HWDATA,
|
||||
output logic [`XLEN-1:0] HREADGPIO,
|
||||
output logic HRESPGPIO, HREADYGPIO,
|
||||
input logic [31:0] GPIOPinsIn,
|
||||
output logic [31:0] GPIOPinsOut, GPIOPinsEn);
|
||||
|
||||
logic [31:0] INPUT_VAL, INPUT_EN, OUTPUT_EN, OUTPUT_VAL;
|
||||
|
||||
logic [7:0] entry;
|
||||
logic memread, memwrite;
|
||||
|
||||
assign memread = MemRWgpioM[1];
|
||||
assign memwrite = MemRWgpioM[0];
|
||||
assign memread = MemRWgpio[1];
|
||||
assign memwrite = MemRWgpio[0];
|
||||
assign HRESPGPIO = 0; // OK
|
||||
assign HREADYGPIO = 1; // Respond immediately
|
||||
|
||||
// word aligned reads
|
||||
generate
|
||||
if (`XLEN==64)
|
||||
assign #2 entry = {AdrM[7:3], 3'b000};
|
||||
assign #2 entry = {HADDR[7:3], 3'b000};
|
||||
else
|
||||
assign #2 entry = {AdrM[7:2], 2'b00};
|
||||
assign #2 entry = {HADDR[7:2], 2'b00};
|
||||
endgenerate
|
||||
|
||||
generate
|
||||
@ -67,10 +69,10 @@ module gpio (
|
||||
if (`XLEN==64) begin
|
||||
always_comb begin
|
||||
case(entry)
|
||||
8'h00: RdGPIOM = {INPUT_EN, INPUT_VAL};
|
||||
8'h08: RdGPIOM = {OUTPUT_VAL, OUTPUT_EN};
|
||||
8'h40: RdGPIOM = 0; // OUT_XOR reads as 0
|
||||
default: RdGPIOM = 0;
|
||||
8'h00: HREADGPIO = {INPUT_EN, INPUT_VAL};
|
||||
8'h08: HREADGPIO = {OUTPUT_VAL, OUTPUT_EN};
|
||||
8'h40: HREADGPIO = 0; // OUT_XOR reads as 0
|
||||
default: HREADGPIO = 0;
|
||||
endcase
|
||||
end
|
||||
always_ff @(posedge clk or posedge reset)
|
||||
@ -79,19 +81,19 @@ module gpio (
|
||||
OUTPUT_EN <= 0;
|
||||
OUTPUT_VAL <= 0; // spec indicates synchronous reset (software control)
|
||||
end else if (memwrite) begin
|
||||
if (entry == 8'h00) INPUT_EN <= MaskedWriteDataM[63:32];
|
||||
if (entry == 8'h08) {OUTPUT_VAL, OUTPUT_EN} <= MaskedWriteDataM;
|
||||
if (entry == 8'h40) OUTPUT_VAL <= OUTPUT_VAL ^ MaskedWriteDataM[31:0]; // OUT_XOR
|
||||
if (entry == 8'h00) INPUT_EN <= HWDATA[63:32];
|
||||
if (entry == 8'h08) {OUTPUT_VAL, OUTPUT_EN} <= HWDATA;
|
||||
if (entry == 8'h40) OUTPUT_VAL <= OUTPUT_VAL ^ HWDATA[31:0]; // OUT_XOR
|
||||
end
|
||||
end else begin // 32-bit
|
||||
always_comb begin
|
||||
case(entry)
|
||||
8'h00: RdGPIOM = INPUT_VAL;
|
||||
8'h04: RdGPIOM = INPUT_EN;
|
||||
8'h08: RdGPIOM = OUTPUT_EN;
|
||||
8'h0C: RdGPIOM = OUTPUT_VAL;
|
||||
8'h40: RdGPIOM = 0; // OUT_XOR reads as 0
|
||||
default: RdGPIOM = 0;
|
||||
8'h00: HREADGPIO = INPUT_VAL;
|
||||
8'h04: HREADGPIO = INPUT_EN;
|
||||
8'h08: HREADGPIO = OUTPUT_EN;
|
||||
8'h0C: HREADGPIO = OUTPUT_VAL;
|
||||
8'h40: HREADGPIO = 0; // OUT_XOR reads as 0
|
||||
default: HREADGPIO = 0;
|
||||
endcase
|
||||
end
|
||||
always_ff @(posedge clk or posedge reset)
|
||||
@ -100,10 +102,10 @@ module gpio (
|
||||
OUTPUT_EN <= 0;
|
||||
//OUTPUT_VAL <= 0;// spec indicates synchronous rset (software control)
|
||||
end else if (memwrite) begin
|
||||
if (entry == 8'h04) INPUT_EN <= MaskedWriteDataM;
|
||||
if (entry == 8'h08) OUTPUT_EN <= MaskedWriteDataM;
|
||||
if (entry == 8'h0C) OUTPUT_VAL <= MaskedWriteDataM;
|
||||
if (entry == 8'h40) OUTPUT_VAL <= OUTPUT_VAL ^ MaskedWriteDataM; // OUT_XOR
|
||||
if (entry == 8'h04) INPUT_EN <= HWDATA;
|
||||
if (entry == 8'h08) OUTPUT_EN <= HWDATA;
|
||||
if (entry == 8'h0C) OUTPUT_VAL <= HWDATA;
|
||||
if (entry == 8'h40) OUTPUT_VAL <= OUTPUT_VAL ^ HWDATA; // OUT_XOR
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
@ -1,188 +0,0 @@
|
||||
///////////////////////////////////////////
|
||||
// subword.sv
|
||||
//
|
||||
// Written: David_Harris@hmc.edu 9 January 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: Masking and muxing for subword accesses
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module subword (
|
||||
input logic [1:0] MemRWM,
|
||||
input logic [`XLEN-1:0] ReadDataUnmaskedM,
|
||||
input logic [`XLEN-1:0] AdrM,
|
||||
input logic [2:0] Funct3M,
|
||||
output logic [`XLEN-1:0] ReadDataM,
|
||||
input logic [`XLEN-1:0] WriteDataM,
|
||||
output logic [`XLEN-1:0] MaskedWriteDataM
|
||||
);
|
||||
|
||||
logic [7:0] ByteM; // *** declare locally to generate as either 4 or 8 bits
|
||||
logic [15:0] HalfwordM;
|
||||
logic [`XLEN-1:0] WriteDataSubwordDuplicated;
|
||||
logic [7:0] ByteMaskM;
|
||||
|
||||
generate
|
||||
if (`XLEN == 64) begin
|
||||
// ByteMe mux
|
||||
always_comb
|
||||
case(AdrM[2:0])
|
||||
3'b000: ByteM = ReadDataUnmaskedM[7:0];
|
||||
3'b001: ByteM = ReadDataUnmaskedM[15:8];
|
||||
3'b010: ByteM = ReadDataUnmaskedM[23:16];
|
||||
3'b011: ByteM = ReadDataUnmaskedM[31:24];
|
||||
3'b100: ByteM = ReadDataUnmaskedM[39:32];
|
||||
3'b101: ByteM = ReadDataUnmaskedM[47:40];
|
||||
3'b110: ByteM = ReadDataUnmaskedM[55:48];
|
||||
3'b111: ByteM = ReadDataUnmaskedM[63:56];
|
||||
endcase
|
||||
|
||||
// halfword mux
|
||||
always_comb
|
||||
case(AdrM[2:1])
|
||||
2'b00: HalfwordM = ReadDataUnmaskedM[15:0];
|
||||
2'b01: HalfwordM = ReadDataUnmaskedM[31:16];
|
||||
2'b10: HalfwordM = ReadDataUnmaskedM[47:32];
|
||||
2'b11: HalfwordM = ReadDataUnmaskedM[63:48];
|
||||
endcase
|
||||
|
||||
logic [31:0] WordM;
|
||||
|
||||
always_comb
|
||||
case(AdrM[2])
|
||||
1'b0: WordM = ReadDataUnmaskedM[31:0];
|
||||
1'b1: WordM = ReadDataUnmaskedM[63:32];
|
||||
endcase
|
||||
|
||||
// sign extension
|
||||
always_comb
|
||||
case(Funct3M)
|
||||
3'b000: ReadDataM = {{56{ByteM[7]}}, ByteM}; // lb
|
||||
3'b001: ReadDataM = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
|
||||
3'b010: ReadDataM = {{32{WordM[31]}}, WordM[31:0]}; // lw
|
||||
3'b011: ReadDataM = ReadDataUnmaskedM; // ld
|
||||
3'b100: ReadDataM = {56'b0, ByteM[7:0]}; // lbu
|
||||
3'b101: ReadDataM = {48'b0, HalfwordM[15:0]}; // lhu
|
||||
3'b110: ReadDataM = {32'b0, WordM[31:0]}; // lwu
|
||||
default: ReadDataM = 64'b0;
|
||||
endcase
|
||||
|
||||
// Memory control
|
||||
|
||||
// Compute write mask
|
||||
always_comb
|
||||
case(Funct3M)
|
||||
3'b000: begin ByteMaskM = 8'b00000000; ByteMaskM[AdrM[2:0]] = 1; end // sb
|
||||
3'b001: case (AdrM[2:1])
|
||||
2'b00: ByteMaskM = 8'b00000011;
|
||||
2'b01: ByteMaskM = 8'b00001100;
|
||||
2'b10: ByteMaskM = 8'b00110000;
|
||||
2'b11: ByteMaskM = 8'b11000000;
|
||||
endcase
|
||||
3'b010: if (AdrM[2]) ByteMaskM = 8'b11110000;
|
||||
else ByteMaskM = 8'b00001111;
|
||||
3'b011: ByteMaskM = 8'b11111111;
|
||||
default: ByteMaskM = 8'b00000000;
|
||||
endcase
|
||||
|
||||
// Handle subword writes
|
||||
always_comb
|
||||
case(Funct3M)
|
||||
3'b000: WriteDataSubwordDuplicated = {8{WriteDataM[7:0]}}; // sb
|
||||
3'b001: WriteDataSubwordDuplicated = {4{WriteDataM[15:0]}}; // sh
|
||||
3'b010: WriteDataSubwordDuplicated = {2{WriteDataM[31:0]}}; // sw
|
||||
3'b011: WriteDataSubwordDuplicated = WriteDataM; // sw
|
||||
default: WriteDataSubwordDuplicated = 64'b0;
|
||||
endcase
|
||||
|
||||
always_comb begin
|
||||
MaskedWriteDataM=ReadDataUnmaskedM;
|
||||
if (ByteMaskM[0]) MaskedWriteDataM[7:0] = WriteDataSubwordDuplicated[7:0];
|
||||
if (ByteMaskM[1]) MaskedWriteDataM[15:8] = WriteDataSubwordDuplicated[15:8];
|
||||
if (ByteMaskM[2]) MaskedWriteDataM[23:16] = WriteDataSubwordDuplicated[23:16];
|
||||
if (ByteMaskM[3]) MaskedWriteDataM[31:24] = WriteDataSubwordDuplicated[31:24];
|
||||
if (ByteMaskM[4]) MaskedWriteDataM[39:32] = WriteDataSubwordDuplicated[39:32];
|
||||
if (ByteMaskM[5]) MaskedWriteDataM[47:40] = WriteDataSubwordDuplicated[47:40];
|
||||
if (ByteMaskM[6]) MaskedWriteDataM[55:48] = WriteDataSubwordDuplicated[55:48];
|
||||
if (ByteMaskM[7]) MaskedWriteDataM[63:56] = WriteDataSubwordDuplicated[63:56];
|
||||
end
|
||||
|
||||
end else begin // 32-bit
|
||||
// byte mux
|
||||
always_comb
|
||||
case(AdrM[1:0])
|
||||
2'b00: ByteM = ReadDataUnmaskedM[7:0];
|
||||
2'b01: ByteM = ReadDataUnmaskedM[15:8];
|
||||
2'b10: ByteM = ReadDataUnmaskedM[23:16];
|
||||
2'b11: ByteM = ReadDataUnmaskedM[31:24];
|
||||
endcase
|
||||
|
||||
// halfword mux
|
||||
always_comb
|
||||
case(AdrM[1])
|
||||
1'b0: HalfwordM = ReadDataUnmaskedM[15:0];
|
||||
1'b1: HalfwordM = ReadDataUnmaskedM[31:16];
|
||||
endcase
|
||||
|
||||
// sign extension
|
||||
always_comb
|
||||
case(Funct3M)
|
||||
3'b000: ReadDataM = {{24{ByteM[7]}}, ByteM}; // lb
|
||||
3'b001: ReadDataM = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
|
||||
3'b010: ReadDataM = ReadDataUnmaskedM; // lw
|
||||
3'b100: ReadDataM = {24'b0, ByteM[7:0]}; // lbu
|
||||
3'b101: ReadDataM = {16'b0, HalfwordM[15:0]}; // lhu
|
||||
default: ReadDataM = 32'b0;
|
||||
endcase
|
||||
|
||||
// Memory control
|
||||
|
||||
// Compute write mask
|
||||
always_comb
|
||||
case(Funct3M)
|
||||
3'b000: begin ByteMaskM = 8'b0000; ByteMaskM[{1'b0, AdrM[1:0]}] = 1; end // sb
|
||||
3'b001: if (AdrM[1]) ByteMaskM = 8'b1100;
|
||||
else ByteMaskM = 8'b0011;
|
||||
3'b010: ByteMaskM = 8'b1111;
|
||||
default: ByteMaskM = 8'b0000;
|
||||
endcase
|
||||
|
||||
// Handle subword writes
|
||||
always_comb
|
||||
case(Funct3M)
|
||||
3'b000: WriteDataSubwordDuplicated = {4{WriteDataM[7:0]}}; // sb
|
||||
3'b001: WriteDataSubwordDuplicated = {2{WriteDataM[15:0]}}; // sh
|
||||
3'b010: WriteDataSubwordDuplicated = WriteDataM; // sw
|
||||
default: WriteDataSubwordDuplicated = 32'b0;
|
||||
endcase
|
||||
|
||||
always_comb begin
|
||||
MaskedWriteDataM=ReadDataUnmaskedM;
|
||||
if (ByteMaskM[0]) MaskedWriteDataM[7:0] = WriteDataSubwordDuplicated[7:0];
|
||||
if (ByteMaskM[1]) MaskedWriteDataM[15:8] = WriteDataSubwordDuplicated[15:8];
|
||||
if (ByteMaskM[2]) MaskedWriteDataM[23:16] = WriteDataSubwordDuplicated[23:16];
|
||||
if (ByteMaskM[3]) MaskedWriteDataM[31:24] = WriteDataSubwordDuplicated[31:24];
|
||||
end
|
||||
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
115
wally-pipelined/src/subwordread.sv
Normal file
115
wally-pipelined/src/subwordread.sv
Normal file
@ -0,0 +1,115 @@
|
||||
///////////////////////////////////////////
|
||||
// subwordread.sv
|
||||
//
|
||||
// Written: David_Harris@hmc.edu 9 January 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: Extract subwords and sign extend for reads
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module subwordread (
|
||||
// input logic [1:0] MemRWM,
|
||||
input logic [`XLEN-1:0] HRDATA,
|
||||
input logic [31:0] HADDR,
|
||||
input logic UnsignedLoadM,
|
||||
input logic [2:0] HSIZE,
|
||||
output logic [`XLEN-1:0] HRDATAMasked
|
||||
// input logic [`XLEN-1:0] HWDATA,
|
||||
// output logic [`XLEN-1:0] HWDATA
|
||||
);
|
||||
|
||||
logic [7:0] ByteM; // *** declare locally to generate as either 4 or 8 bits
|
||||
logic [15:0] HalfwordM;
|
||||
|
||||
generate
|
||||
if (`XLEN == 64) begin
|
||||
// ByteMe mux
|
||||
always_comb
|
||||
case(HADDR[2:0])
|
||||
3'b000: ByteM = HRDATA[7:0];
|
||||
3'b001: ByteM = HRDATA[15:8];
|
||||
3'b010: ByteM = HRDATA[23:16];
|
||||
3'b011: ByteM = HRDATA[31:24];
|
||||
3'b100: ByteM = HRDATA[39:32];
|
||||
3'b101: ByteM = HRDATA[47:40];
|
||||
3'b110: ByteM = HRDATA[55:48];
|
||||
3'b111: ByteM = HRDATA[63:56];
|
||||
endcase
|
||||
|
||||
// halfword mux
|
||||
always_comb
|
||||
case(HADDR[2:1])
|
||||
2'b00: HalfwordM = HRDATA[15:0];
|
||||
2'b01: HalfwordM = HRDATA[31:16];
|
||||
2'b10: HalfwordM = HRDATA[47:32];
|
||||
2'b11: HalfwordM = HRDATA[63:48];
|
||||
endcase
|
||||
|
||||
logic [31:0] WordM;
|
||||
|
||||
always_comb
|
||||
case(HADDR[2])
|
||||
1'b0: WordM = HRDATA[31:0];
|
||||
1'b1: WordM = HRDATA[63:32];
|
||||
endcase
|
||||
|
||||
// sign extension
|
||||
always_comb
|
||||
case({UnsignedLoadM, HSIZE[1:0]})
|
||||
3'b000: HRDATAMasked = {{56{ByteM[7]}}, ByteM}; // lb
|
||||
3'b001: HRDATAMasked = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
|
||||
3'b010: HRDATAMasked = {{32{WordM[31]}}, WordM[31:0]}; // lw
|
||||
3'b011: HRDATAMasked = HRDATA; // ld
|
||||
3'b100: HRDATAMasked = {56'b0, ByteM[7:0]}; // lbu
|
||||
3'b101: HRDATAMasked = {48'b0, HalfwordM[15:0]}; // lhu
|
||||
3'b110: HRDATAMasked = {32'b0, WordM[31:0]}; // lwu
|
||||
default: HRDATAMasked = HRDATA; // Shouldn't happen
|
||||
endcase
|
||||
end else begin // 32-bit
|
||||
// byte mux
|
||||
always_comb
|
||||
case(HADDR[1:0])
|
||||
2'b00: ByteM = HRDATA[7:0];
|
||||
2'b01: ByteM = HRDATA[15:8];
|
||||
2'b10: ByteM = HRDATA[23:16];
|
||||
2'b11: ByteM = HRDATA[31:24];
|
||||
endcase
|
||||
|
||||
// halfword mux
|
||||
always_comb
|
||||
case(HADDR[1])
|
||||
1'b0: HalfwordM = HRDATA[15:0];
|
||||
1'b1: HalfwordM = HRDATA[31:16];
|
||||
endcase
|
||||
|
||||
// sign extension
|
||||
always_comb
|
||||
case({UnsignedLoadM, HSIZE[1:0]})
|
||||
3'b000: HRDATAMasked = {{24{ByteM[7]}}, ByteM}; // lb
|
||||
3'b001: HRDATAMasked = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
|
||||
3'b010: HRDATAMasked = HRDATA; // lw
|
||||
3'b100: HRDATAMasked = {24'b0, ByteM[7:0]}; // lbu
|
||||
3'b101: HRDATAMasked = {16'b0, HalfwordM[15:0]}; // lhu
|
||||
default: HRDATAMasked = HRDATA;
|
||||
endcase
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
110
wally-pipelined/src/subwordwrite.sv
Normal file
110
wally-pipelined/src/subwordwrite.sv
Normal file
@ -0,0 +1,110 @@
|
||||
///////////////////////////////////////////
|
||||
// subwordwrite.sv
|
||||
//
|
||||
// Written: David_Harris@hmc.edu 9 January 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: Masking and muxing for subword writes
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module subwordwrite (
|
||||
input logic [`XLEN-1:0] HRDATA,
|
||||
input logic [31:0] HADDR,
|
||||
input logic [2:0] HSIZE,
|
||||
input logic [`XLEN-1:0] HWDATAIN,
|
||||
output logic [`XLEN-1:0] HWDATA
|
||||
);
|
||||
|
||||
logic [7:0] ByteM; // *** declare locally to generate as either 4 or 8 bits
|
||||
logic [15:0] HalfwordM;
|
||||
logic [`XLEN-1:0] WriteDataSubwordDuplicated;
|
||||
logic [7:0] ByteMaskM;
|
||||
|
||||
generate
|
||||
if (`XLEN == 64) begin
|
||||
// Compute write mask
|
||||
always_comb
|
||||
case(HSIZE[1:0])
|
||||
2'b00: begin ByteMaskM = 8'b00000000; ByteMaskM[HADDR[2:0]] = 1; end // sb
|
||||
2'b01: case (HADDR[2:1])
|
||||
2'b00: ByteMaskM = 8'b00000011;
|
||||
2'b01: ByteMaskM = 8'b00001100;
|
||||
2'b10: ByteMaskM = 8'b00110000;
|
||||
2'b11: ByteMaskM = 8'b11000000;
|
||||
endcase
|
||||
2'b10: if (HADDR[2]) ByteMaskM = 8'b11110000;
|
||||
else ByteMaskM = 8'b00001111;
|
||||
2'b11: ByteMaskM = 8'b11111111;
|
||||
endcase
|
||||
|
||||
// Handle subword writes
|
||||
always_comb
|
||||
case(HSIZE[1:0])
|
||||
2'b00: WriteDataSubwordDuplicated = {8{HWDATAIN[7:0]}}; // sb
|
||||
2'b01: WriteDataSubwordDuplicated = {4{HWDATAIN[15:0]}}; // sh
|
||||
2'b10: WriteDataSubwordDuplicated = {2{HWDATAIN[31:0]}}; // sw
|
||||
2'b11: WriteDataSubwordDuplicated = HWDATAIN; // sw
|
||||
endcase
|
||||
|
||||
always_comb begin
|
||||
HWDATA=HRDATA;
|
||||
if (ByteMaskM[0]) HWDATA[7:0] = WriteDataSubwordDuplicated[7:0];
|
||||
if (ByteMaskM[1]) HWDATA[15:8] = WriteDataSubwordDuplicated[15:8];
|
||||
if (ByteMaskM[2]) HWDATA[23:16] = WriteDataSubwordDuplicated[23:16];
|
||||
if (ByteMaskM[3]) HWDATA[31:24] = WriteDataSubwordDuplicated[31:24];
|
||||
if (ByteMaskM[4]) HWDATA[39:32] = WriteDataSubwordDuplicated[39:32];
|
||||
if (ByteMaskM[5]) HWDATA[47:40] = WriteDataSubwordDuplicated[47:40];
|
||||
if (ByteMaskM[6]) HWDATA[55:48] = WriteDataSubwordDuplicated[55:48];
|
||||
if (ByteMaskM[7]) HWDATA[63:56] = WriteDataSubwordDuplicated[63:56];
|
||||
end
|
||||
|
||||
end else begin // 32-bit
|
||||
// Compute write mask
|
||||
always_comb
|
||||
case(HSIZE[1:0])
|
||||
2'b00: begin ByteMaskM = 8'b0000; ByteMaskM[{1'b0, HADDR[1:0]}] = 1; end // sb
|
||||
2'b01: if (HADDR[1]) ByteMaskM = 8'b1100;
|
||||
else ByteMaskM = 8'b0011;
|
||||
2'b10: ByteMaskM = 8'b1111;
|
||||
default: ByteMaskM = 8'b111; // shouldn't happen
|
||||
endcase
|
||||
|
||||
// Handle subword writes
|
||||
always_comb
|
||||
case(HSIZE[1:0])
|
||||
2'b00: WriteDataSubwordDuplicated = {4{HWDATAIN[7:0]}}; // sb
|
||||
2'b01: WriteDataSubwordDuplicated = {2{HWDATAIN[15:0]}}; // sh
|
||||
2'b10: WriteDataSubwordDuplicated = HWDATAIN; // sw
|
||||
default: WriteDataSubwordDuplicated = HWDATAIN; // shouldn't happen
|
||||
endcase
|
||||
|
||||
always_comb begin
|
||||
HWDATA=HRDATA;
|
||||
if (ByteMaskM[0]) HWDATA[7:0] = WriteDataSubwordDuplicated[7:0];
|
||||
if (ByteMaskM[1]) HWDATA[15:8] = WriteDataSubwordDuplicated[15:8];
|
||||
if (ByteMaskM[2]) HWDATA[23:16] = WriteDataSubwordDuplicated[23:16];
|
||||
if (ByteMaskM[3]) HWDATA[31:24] = WriteDataSubwordDuplicated[31:24];
|
||||
end
|
||||
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
@ -29,11 +29,11 @@
|
||||
|
||||
module uart (
|
||||
input logic clk, reset,
|
||||
input logic [1:0] MemRWuartM,
|
||||
// input logic [7:0] ByteMaskM,
|
||||
input logic [`XLEN-1:0] AdrM,
|
||||
input logic [`XLEN-1:0] MaskedWriteDataM,
|
||||
output logic [`XLEN-1:0] RdUARTM,
|
||||
input logic [1:0] MemRWuart,
|
||||
input logic [2:0] HADDR,
|
||||
input logic [`XLEN-1:0] HWDATA,
|
||||
output logic [`XLEN-1:0] HREADUART,
|
||||
output logic HRESPUART, HREADYUART,
|
||||
input logic SIN, DSRb, DCDb, CTSb, RIb, // from E1A driver from RS232 interface
|
||||
output logic SOUT, RTSb, DTRb, // to E1A driver to RS232 interface
|
||||
output logic OUT1b, OUT2b, INTR, TXRDYb, RXRDYb); // to CPU
|
||||
@ -44,33 +44,35 @@ module uart (
|
||||
logic [7:0] Din, Dout;
|
||||
|
||||
// rename processor interface signals to match PC16550D and provide one-byte interface
|
||||
assign MEMRb = ~MemRWuartM[1];
|
||||
assign MEMWb = ~MemRWuartM[0];
|
||||
assign A = AdrM[2:0];
|
||||
assign MEMRb = ~MemRWuart[1];
|
||||
assign MEMWb = ~MemRWuart[0];
|
||||
assign A = HADDR[2:0];
|
||||
assign HRESPUART = 0; // OK
|
||||
assign HREADYUART = 1; // Respond immediately
|
||||
|
||||
generate
|
||||
if (`XLEN == 64) begin
|
||||
always_comb begin
|
||||
RdUARTM = {Dout, Dout, Dout, Dout, Dout, Dout, Dout, Dout};
|
||||
case (AdrM[2:0])
|
||||
3'b000: Din = MaskedWriteDataM[7:0];
|
||||
3'b001: Din = MaskedWriteDataM[15:8];
|
||||
3'b010: Din = MaskedWriteDataM[23:16];
|
||||
3'b011: Din = MaskedWriteDataM[31:24];
|
||||
3'b100: Din = MaskedWriteDataM[39:32];
|
||||
3'b101: Din = MaskedWriteDataM[47:40];
|
||||
3'b110: Din = MaskedWriteDataM[55:48];
|
||||
3'b111: Din = MaskedWriteDataM[63:56];
|
||||
HREADUART = {Dout, Dout, Dout, Dout, Dout, Dout, Dout, Dout};
|
||||
case (HADDR)
|
||||
3'b000: Din = HWDATA[7:0];
|
||||
3'b001: Din = HWDATA[15:8];
|
||||
3'b010: Din = HWDATA[23:16];
|
||||
3'b011: Din = HWDATA[31:24];
|
||||
3'b100: Din = HWDATA[39:32];
|
||||
3'b101: Din = HWDATA[47:40];
|
||||
3'b110: Din = HWDATA[55:48];
|
||||
3'b111: Din = HWDATA[63:56];
|
||||
endcase
|
||||
end
|
||||
end else begin // 32-bit
|
||||
always_comb begin
|
||||
RdUARTM = {Dout, Dout, Dout, Dout};
|
||||
case (AdrM[1:0])
|
||||
2'b00: Din = MaskedWriteDataM[7:0];
|
||||
2'b01: Din = MaskedWriteDataM[15:8];
|
||||
2'b10: Din = MaskedWriteDataM[23:16];
|
||||
2'b11: Din = MaskedWriteDataM[31:24];
|
||||
HREADUART = {Dout, Dout, Dout, Dout};
|
||||
case (HADDR[1:0])
|
||||
2'b00: Din = HWDATA[7:0];
|
||||
2'b01: Din = HWDATA[15:8];
|
||||
2'b10: Din = HWDATA[23:16];
|
||||
2'b11: Din = HWDATA[31:24];
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
@ -30,11 +30,20 @@
|
||||
// *** and use memread signal to reduce power when reads aren't needed
|
||||
module uncore (
|
||||
input logic clk, reset,
|
||||
// AHB Bus Interface
|
||||
input logic [31:0] HADDR,
|
||||
input logic [`AHBW-1:0] HWDATAIN,
|
||||
input logic HWRITE,
|
||||
input logic [2:0] HSIZE,
|
||||
input logic [2:0] HBURST,
|
||||
input logic [3:0] HPROT,
|
||||
input logic [1:0] HTRANS,
|
||||
input logic HMASTLOCK,
|
||||
input logic [`AHBW-1:0] HRDATAEXT,
|
||||
input logic HREADYEXT, HRESPEXT,
|
||||
output logic [`AHBW-1:0] HRDATA,
|
||||
output logic HREADY, HRESP,
|
||||
// bus interface
|
||||
input logic [1:0] MemRWM,
|
||||
input logic [`XLEN-1:0] AdrM, WriteDataM,
|
||||
input logic [2:0] Funct3M,
|
||||
output logic [`XLEN-1:0] ReadDataM,
|
||||
output logic DataAccessFaultM,
|
||||
// peripheral pins
|
||||
output logic TimerIntM, SwIntM,
|
||||
@ -44,56 +53,53 @@ module uncore (
|
||||
output logic UARTSout
|
||||
);
|
||||
|
||||
logic [`XLEN-1:0] MaskedWriteDataM;
|
||||
logic [`XLEN-1:0] ReadDataUnmaskedM;
|
||||
logic [`XLEN-1:0] RdTimM, RdCLINTM, RdGPIOM, RdUARTM;
|
||||
logic TimEnM, CLINTEnM, GPIOEnM, UARTEnM;
|
||||
logic [1:0] MemRWdtimM, MemRWclintM, MemRWgpioM, MemRWuartM;
|
||||
logic [`XLEN-1:0] HWDATA;
|
||||
logic [`XLEN-1:0] HREADTim, HREADCLINT, HREADGPIO, HREADUART;
|
||||
logic HSELTim, HSELCLINT, HSELGPIO, PreHSELUART, HSELUART;
|
||||
logic HRESPTim, HRESPCLINT, HRESPGPIO, HRESPUART;
|
||||
logic HREADYTim, HREADYCLINT, HREADYGPIO, HREADYUART;
|
||||
logic MemRW;
|
||||
logic [1:0] MemRWtim, MemRWclint, MemRWgpio, MemRWuart;
|
||||
logic UARTIntr;// *** will need to tie INTR to an interrupt handler
|
||||
|
||||
// Address decoding
|
||||
adrdec timdec(AdrM, `TIMBASE, `TIMRANGE, TimEnM);
|
||||
adrdec clintdec(AdrM, `CLINTBASE, `CLINTRANGE, CLINTEnM);
|
||||
adrdec gpiodec(AdrM, `GPIOBASE, `GPIORANGE, GPIOEnM);
|
||||
adrdec uartdec(AdrM, `UARTBASE, `UARTRANGE, UARTEnM);
|
||||
|
||||
/*// *** generalize, use configurable
|
||||
generate
|
||||
if (`XLEN == 64)
|
||||
assign TimEnM = ~(|AdrM[`XLEN-1:32]) & AdrM[31] & ~(|AdrM[30:19]); // 0x000...80000000 - 0x000...8007FFFF
|
||||
else
|
||||
assign TimEnM = AdrM[31] & ~(|AdrM[30:19]); // 0x80000000 - 0x8007FFFF
|
||||
endgenerate
|
||||
assign CLINTEnM = ~(|AdrM[`XLEN-1:26]) & AdrM[25] & ~(|AdrM[24:16]); // 0x02000000-0x0200FFFF
|
||||
assign GPIOEnM = (AdrM[31:8] == 24'h10012); // 0x10012000-0x100120FF
|
||||
assign UARTEnM = ~(|AdrM[`XLEN-1:29]) & AdrM[28] & ~(|AdrM[27:3]); // 0x10000000-0x10000007
|
||||
*/
|
||||
|
||||
// Enable read or write based on decoded address.
|
||||
assign MemRWdtimM = MemRWM & {2{TimEnM}};
|
||||
assign MemRWclintM = MemRWM & {2{CLINTEnM}};
|
||||
assign MemRWgpioM = MemRWM & {2{GPIOEnM}};
|
||||
assign MemRWuartM = MemRWM & {2{UARTEnM}};
|
||||
// AHB Address decoder
|
||||
adrdec timdec(HADDR, `TIMBASE, `TIMRANGE, HSELTim);
|
||||
adrdec clintdec(HADDR, `CLINTBASE, `CLINTRANGE, HSELCLINT);
|
||||
adrdec gpiodec(HADDR, `GPIOBASE, `GPIORANGE, HSELGPIO);
|
||||
adrdec uartdec(HADDR, `UARTBASE, `UARTRANGE, PreHSELUART);
|
||||
assign HSELUART = PreHSELUART && (HSIZE == 3'b000); // only byte writes to UART are supported
|
||||
|
||||
// Enable read or write based on decoded address
|
||||
assign MemRW = {~HWRITE, HWRITE};
|
||||
assign MemRWtim = MemRW & {2{HSELTim}};
|
||||
assign MemRWclint = MemRW & {2{HSELCLINT}};
|
||||
assign MemRWgpio = MemRW & {2{HSELGPIO}};
|
||||
assign MemRWuart = MemRW & {2{HSELUART}};
|
||||
|
||||
// subword accesses: converts HWDATAIN to HWDATA
|
||||
subwordwrite sww(.*);
|
||||
|
||||
// tightly integrated memory
|
||||
dtim dtim(.AdrM(AdrM[18:0]), .*);
|
||||
dtim dtim(.HADDR(HADDR[18:0]), .*);
|
||||
|
||||
// memory-mapped I/O peripherals
|
||||
clint clint(.AdrM(AdrM[15:0]), .*);
|
||||
gpio gpio(.AdrM(AdrM[7:0]), .*); // *** may want to add GPIO interrupts
|
||||
uart uart(.TXRDYb(), .RXRDYb(), .INTR(UARTIntr), .SIN(UARTSin), .SOUT(UARTSout),
|
||||
clint clint(.HADDR(HADDR[15:0]), .*);
|
||||
gpio gpio(.HADDR(HADDR[7:0]), .*); // *** may want to add GPIO interrupts
|
||||
uart uart(.HADDR(HADDR[2:0]), .TXRDYb(), .RXRDYb(), .INTR(UARTIntr), .SIN(UARTSin), .SOUT(UARTSout),
|
||||
.DSRb(1'b1), .DCDb(1'b1), .CTSb(1'b0), .RIb(1'b1),
|
||||
.RTSb(), .DTRb(), .OUT1b(), .OUT2b(), .*);
|
||||
|
||||
// *** Interface to off-chip memory would appear as another peripheral
|
||||
|
||||
// merge reads
|
||||
assign ReadDataUnmaskedM = ({`XLEN{TimEnM}} & RdTimM) | ({`XLEN{CLINTEnM}} & RdCLINTM) |
|
||||
({`XLEN{GPIOEnM}} & RdGPIOM) | ({`XLEN{UARTEnM}} & RdUARTM);
|
||||
assign DataAccessFaultM = ~(TimEnM | CLINTEnM | GPIOEnM | UARTEnM);
|
||||
// mux could also include external memory
|
||||
// AHB Read Multiplexer
|
||||
assign HRDATA = ({`XLEN{HSELTim}} & HREADTim) | ({`XLEN{HSELCLINT}} & HREADCLINT) |
|
||||
({`XLEN{HSELGPIO}} & HREADGPIO) | ({`XLEN{HSELUART}} & HREADUART);
|
||||
assign HRESP = HSELTim & HRESPTim | HSELCLINT & HRESPCLINT | HSELGPIO & HRESPGPIO | HSELUART & HRESPUART;
|
||||
assign HREADY = HSELTim & HREADYTim | HSELCLINT & HREADYCLINT | HSELGPIO & HREADYGPIO | HSELUART & HREADYUART;
|
||||
|
||||
// Faults
|
||||
assign DataAccessFaultM = ~(HSELTim | HSELCLINT | HSELGPIO | HSELUART);
|
||||
|
||||
// subword accesses: converts ReadDataUnmaskedM to ReadDataM and WriteDataM to MaskedWriteDataM
|
||||
subword subword(.*);
|
||||
|
||||
endmodule
|
||||
|
||||
|
@ -30,12 +30,9 @@ module wallypipelinedhart (
|
||||
input logic clk, reset,
|
||||
output logic [`XLEN-1:0] PCF,
|
||||
input logic [31:0] InstrF,
|
||||
output logic [1:0] MemRWdcuoutM, // *** should be removed when EBU enabled
|
||||
output logic [2:0] Funct3M, // *** remove when EBU enabled
|
||||
output logic [`XLEN-1:0] DataAdrM, WriteDataM, // ***
|
||||
input logic [`XLEN-1:0] ReadDataM, // ***
|
||||
// Privileged
|
||||
input logic TimerIntM, ExtIntM, SwIntM,
|
||||
input logic InstrAccessFaultF,
|
||||
input logic InstrAccessFaultF,
|
||||
input logic DataAccessFaultM,
|
||||
// Bus Interface
|
||||
input logic [`AHBW-1:0] HRDATA,
|
||||
@ -83,6 +80,12 @@ module wallypipelinedhart (
|
||||
logic [4:0] SetFflagsM;
|
||||
logic [2:0] FRM_REGW;
|
||||
logic FloatRegWriteW;
|
||||
|
||||
// bus interface to dcu
|
||||
logic [1:0] MemRWdcuoutM;
|
||||
logic [2:0] Funct3M;
|
||||
logic [`XLEN-1:0] DataAdrM, WriteDataM;
|
||||
logic [`XLEN-1:0] ReadDataM;
|
||||
|
||||
ifu ifu(.*); // instruction fetch unit: PC, branch prediction, instruction cache
|
||||
|
||||
@ -91,8 +94,11 @@ module wallypipelinedhart (
|
||||
|
||||
ahblite ebu(
|
||||
.IPAdrD(zero), .IReadD(1'b0), .IRData(), .IReady(),
|
||||
.DPAdrM(DataAdrM), .DReadM(MemRWM[1]), .DWriteM(MemRWM[0]), .DWDataM(WriteDataM), .DSizeM(2'b11), .DRData(), .DReady(),
|
||||
.DPAdrM(DataAdrM), .DReadM(MemRWdcuoutM[1]), .DWriteM(MemRWdcuoutM[0]), .DWDataM(WriteDataM),
|
||||
.DSizeM(Funct3M[1:0]), .DRData(ReadDataM), .DReady(),
|
||||
.UnsignedLoadM(Funct3M[2]),
|
||||
.*);
|
||||
// assign UnsignedLoadM = Funct3M[2]; // *** maybe move read extension to dcu
|
||||
|
||||
/*
|
||||
mdu mdu(.*); // multiply and divide unit
|
||||
|
@ -34,8 +34,10 @@
|
||||
module wallypipelinedsoc (
|
||||
input logic clk, reset,
|
||||
// AHB Lite Interface
|
||||
input logic [`AHBW-1:0] HRDATA,
|
||||
input logic HREADY, HRESP,
|
||||
// inputs from external memory
|
||||
input logic [`AHBW-1:0] HRDATAEXT,
|
||||
input logic HREADYEXT, HRESPEXT,
|
||||
// outputs to external memory, shared with uncore memory
|
||||
output logic [31:0] HADDR,
|
||||
output logic [`AHBW-1:0] HWDATA,
|
||||
output logic HWRITE,
|
||||
@ -51,12 +53,14 @@ module wallypipelinedsoc (
|
||||
output logic UARTSout
|
||||
);
|
||||
|
||||
logic [1:0] MemRWM;
|
||||
logic [`XLEN-1:0] DataAdrM, WriteDataM;
|
||||
logic [`XLEN-1:0] PCF, ReadDataM;
|
||||
// to instruction memory *** remove later
|
||||
logic [`XLEN-1:0] PCF;
|
||||
logic [31:0] InstrF;
|
||||
logic [2:0] Funct3M;
|
||||
logic [1:0] MemRWdcuoutM;
|
||||
|
||||
// Uncore signals
|
||||
logic [`AHBW-1:0] HRDATA; // from AHB mux in uncore
|
||||
logic HREADY, HRESP;
|
||||
// logic UnsignedLoadM;
|
||||
logic InstrAccessFaultF, DataAccessFaultM;
|
||||
logic TimerIntM, SwIntM; // from CLINT
|
||||
logic ExtIntM = 0; // not yet connected
|
||||
@ -65,5 +69,5 @@ module wallypipelinedsoc (
|
||||
wallypipelinedhart hart(.*);
|
||||
|
||||
imem imem(.AdrF(PCF[`XLEN-1:1]), .*);
|
||||
uncore uncore(.AdrM(DataAdrM), .MemRWM(MemRWdcuoutM), .*);
|
||||
uncore uncore(.HWDATAIN(HWDATA), .*);
|
||||
endmodule
|
@ -220,8 +220,8 @@ string tests32i[] = {
|
||||
};
|
||||
string tests[];
|
||||
|
||||
logic [`AHBW-1:0] HRDATA;
|
||||
logic HREADY, HRESP;
|
||||
logic [`AHBW-1:0] HRDATAEXT;
|
||||
logic HREADYEXT, HRESPEXT;
|
||||
logic [31:0] HADDR;
|
||||
logic [`AHBW-1:0] HWDATA;
|
||||
logic HWRITE;
|
||||
@ -251,9 +251,9 @@ string tests32i[] = {
|
||||
// instantiate device to be tested
|
||||
assign GPIOPinsIn = 0;
|
||||
assign UARTSin = 1;
|
||||
assign HREADY = 1;
|
||||
assign HRESP = 0;
|
||||
assign HRDATA = 0;
|
||||
assign HREADYEXT = 1;
|
||||
assign HRESPEXT = 0;
|
||||
assign HRDATAEXT = 0;
|
||||
|
||||
wallypipelinedsoc dut(.*);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user