mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Uncore is now parameterized.
This commit is contained in:
parent
340aac0934
commit
b8474b208e
@ -25,31 +25,29 @@
|
||||
// and limitations under the License.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module ahbapbbridge #(PERIPHS = 2) (
|
||||
module ahbapbbridge import cvw::*; #(parameter cvw_t P, PERIPHS = 2) (
|
||||
input logic HCLK, HRESETn,
|
||||
input logic [PERIPHS-1:0] HSEL,
|
||||
input logic [`PA_BITS-1:0] HADDR,
|
||||
input logic [`XLEN-1:0] HWDATA,
|
||||
input logic [`XLEN/8-1:0] HWSTRB,
|
||||
input logic [P.PA_BITS-1:0] HADDR,
|
||||
input logic [P.XLEN-1:0] HWDATA,
|
||||
input logic [P.XLEN/8-1:0] HWSTRB,
|
||||
input logic HWRITE,
|
||||
input logic [1:0] HTRANS,
|
||||
input logic HREADY,
|
||||
// input logic [3:0] HPROT, // not used
|
||||
output logic [`XLEN-1:0] HRDATA,
|
||||
output logic [P.XLEN-1:0] HRDATA,
|
||||
output logic HRESP, HREADYOUT,
|
||||
output logic PCLK, PRESETn,
|
||||
output logic [PERIPHS-1:0] PSEL,
|
||||
output logic PWRITE,
|
||||
output logic PENABLE,
|
||||
output logic [31:0] PADDR,
|
||||
output logic [`XLEN-1:0] PWDATA,
|
||||
output logic [P.XLEN-1:0] PWDATA,
|
||||
// output logic [2:0] PPROT, // not used
|
||||
output logic [`XLEN/8-1:0] PSTRB,
|
||||
output logic [P.XLEN/8-1:0] PSTRB,
|
||||
// output logic PWAKEUP // not used
|
||||
input logic [PERIPHS-1:0] PREADY,
|
||||
input var [PERIPHS-1:0][`XLEN-1:0] PRDATA
|
||||
input var [PERIPHS-1:0][P.XLEN-1:0] PRDATA
|
||||
);
|
||||
|
||||
logic initTrans, initTransSel, initTransSelD;
|
||||
|
@ -27,17 +27,15 @@
|
||||
// and limitations under the License.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module clint_apb (
|
||||
module clint_apb import cvw::*; #(parameter cvw_t P) (
|
||||
input logic PCLK, PRESETn,
|
||||
input logic PSEL,
|
||||
input logic [15:0] PADDR,
|
||||
input logic [`XLEN-1:0] PWDATA,
|
||||
input logic [`XLEN/8-1:0] PSTRB,
|
||||
input logic [P.XLEN-1:0] PWDATA,
|
||||
input logic [P.XLEN/8-1:0] PSTRB,
|
||||
input logic PWRITE,
|
||||
input logic PENABLE,
|
||||
output logic [`XLEN-1:0] PRDATA,
|
||||
output logic [P.XLEN-1:0] PRDATA,
|
||||
output logic PREADY,
|
||||
output logic [63:0] MTIME,
|
||||
output logic MTimerInt, MSwInt
|
||||
@ -53,7 +51,7 @@ module clint_apb (
|
||||
assign PREADY = 1'b1; // CLINT never takes >1 cycle to respond
|
||||
|
||||
// word aligned reads
|
||||
if (`XLEN==64) assign #2 entry = {PADDR[15:3], 3'b000};
|
||||
if (P.XLEN==64) assign #2 entry = {PADDR[15:3], 3'b000};
|
||||
else assign #2 entry = {PADDR[15:2], 2'b00};
|
||||
|
||||
// DH 2/20/21: Eventually allow MTIME to run off a separate clock
|
||||
@ -63,7 +61,7 @@ module clint_apb (
|
||||
// Use req and ack signals synchronized across the clock domains.
|
||||
|
||||
// register access
|
||||
if (`XLEN==64) begin:clint // 64-bit
|
||||
if (P.XLEN==64) begin:clint // 64-bit
|
||||
always @(posedge PCLK) begin
|
||||
case(entry)
|
||||
16'h0000: PRDATA <= {63'b0, MSIP};
|
||||
@ -79,7 +77,7 @@ module clint_apb (
|
||||
end else if (memwrite) begin
|
||||
if (entry == 16'h0000) MSIP <= PWDATA[0];
|
||||
if (entry == 16'h4000) begin
|
||||
for(i=0;i<`XLEN/8;i++)
|
||||
for(i=0;i<P.XLEN/8;i++)
|
||||
if(PSTRB[i])
|
||||
MTIMECMP[i*8 +: 8] <= PWDATA[i*8 +: 8]; // ***dh: this notation isn't in book yet - maybe from Ross
|
||||
end
|
||||
@ -93,7 +91,7 @@ module clint_apb (
|
||||
MTIME <= 0;
|
||||
end else if (memwrite & entry == 16'hBFF8) begin
|
||||
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
|
||||
for(j=0;j<`XLEN/8;j++)
|
||||
for(j=0;j<P.XLEN/8;j++)
|
||||
if(PSTRB[j])
|
||||
MTIME[j*8 +: 8] <= PWDATA[j*8 +: 8];
|
||||
end else MTIME <= MTIME + 1;
|
||||
@ -116,11 +114,11 @@ module clint_apb (
|
||||
end else if (memwrite) begin
|
||||
if (entry == 16'h0000) MSIP <= PWDATA[0];
|
||||
if (entry == 16'h4000)
|
||||
for(j=0;j<`XLEN/8;j++)
|
||||
for(j=0;j<P.XLEN/8;j++)
|
||||
if(PSTRB[j])
|
||||
MTIMECMP[j*8 +: 8] <= PWDATA[j*8 +: 8];
|
||||
if (entry == 16'h4004)
|
||||
for(j=0;j<`XLEN/8;j++)
|
||||
for(j=0;j<P.XLEN/8;j++)
|
||||
if(PSTRB[j])
|
||||
MTIMECMP[32 + j*8 +: 8] <= PWDATA[j*8 +: 8];
|
||||
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
|
||||
@ -133,12 +131,12 @@ module clint_apb (
|
||||
MTIME <= 0;
|
||||
// MTIMECMP is not reset
|
||||
end else if (memwrite & (entry == 16'hBFF8)) begin
|
||||
for(i=0;i<`XLEN/8;i++)
|
||||
for(i=0;i<P.XLEN/8;i++)
|
||||
if(PSTRB[i])
|
||||
MTIME[i*8 +: 8] <= PWDATA[i*8 +: 8];
|
||||
end else if (memwrite & (entry == 16'hBFFC)) begin
|
||||
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
|
||||
for(i=0;i<`XLEN/8;i++)
|
||||
for(i=0;i<P.XLEN/8;i++)
|
||||
if(PSTRB[i])
|
||||
MTIME[32 + i*8 +: 8]<= PWDATA[i*8 +: 8];
|
||||
end else MTIME <= MTIME + 1;
|
||||
@ -151,13 +149,13 @@ module clint_apb (
|
||||
|
||||
endmodule
|
||||
|
||||
module timeregsync(
|
||||
module timeregsync import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk, resetn,
|
||||
input logic we0, we1,
|
||||
input logic [`XLEN-1:0] wd,
|
||||
input logic [P.XLEN-1:0] wd,
|
||||
output logic [63:0] q);
|
||||
|
||||
if (`XLEN==64)
|
||||
if (P.XLEN==64)
|
||||
always_ff @(posedge clk or negedge resetn)
|
||||
if (~resetn) q <= 0;
|
||||
else if (we0) q <= wd;
|
||||
@ -170,14 +168,14 @@ module timeregsync(
|
||||
else q <= q + 1;
|
||||
endmodule
|
||||
|
||||
module timereg(
|
||||
module timereg import cvw::*; #(parameter cvw_t P) (
|
||||
input logic PCLK, PRESETn, TIMECLK,
|
||||
input logic we0, we1,
|
||||
input logic [`XLEN-1:0] PWDATA,
|
||||
input logic [P.XLEN-1:0] PWDATA,
|
||||
output logic [63:0] MTIME,
|
||||
output logic done);
|
||||
|
||||
// if (`TIMEBASE_SYNC) begin:timereg // use PCLK for MTIME
|
||||
// if (P.TIMEBASE_SYNC) begin:timereg // use PCLK for MTIME
|
||||
if (1) begin:timereg // use PCLK for MTIME
|
||||
timregsync timeregsync(.clk(PCLK), .resetn(PRESETn), .we0, .we1, .wd(PWDATA), .q(MTIME));
|
||||
assign done = 1; // immediately completes
|
||||
@ -192,7 +190,7 @@ module timereg(
|
||||
// There is no back pressure on instructions, so if multiple counter writes occur ***
|
||||
|
||||
logic req, req_sync, ack, we0_stored, we1_stored, ack_stored, resetn_sync;
|
||||
logic [`XLEN-1:0] wd_stored;
|
||||
logic [P.XLEN-1:0] wd_stored;
|
||||
logic [63:0] time_int, time_int_gc, time_gc, MTIME_GC;
|
||||
|
||||
// When a write enable is asserted for a cycle, sample the enables and data and raise a request until it is acknowledged
|
||||
@ -216,7 +214,7 @@ module timereg(
|
||||
// synchronize the acknowledge back to the PCLK domain to indicate the request was handled and can be lowered
|
||||
sync async(PCLK, req_sync, ack);
|
||||
|
||||
timeregsync timeregsync(.clk(TIMECLK), .resetn(resetn_sync), .we0(we0_stored), .we1(we1_stored), .wd(wd_stored), .q(time_int));
|
||||
timeregsync #(P) timeregsync(.clk(TIMECLK), .resetn(resetn_sync), .we0(we0_stored), .we1(we1_stored), .wd(wd_stored), .q(time_int));
|
||||
binarytogray b2g(time_int, time_int_gc);
|
||||
flop gcreg(TIMECLK, time_int_gc, time_gc);
|
||||
|
||||
@ -225,7 +223,7 @@ module timereg(
|
||||
end
|
||||
endmodule
|
||||
|
||||
module binarytogray #(parameter N = `XLEN) (
|
||||
module binarytogray #(parameter N) (
|
||||
input logic [N-1:0] b,
|
||||
output logic [N-1:0] g);
|
||||
|
||||
@ -234,7 +232,7 @@ module binarytogray #(parameter N = `XLEN) (
|
||||
assign g = b ^ {1'b0, b[N-1:1]};
|
||||
endmodule
|
||||
|
||||
module graytobinary #(parameter N = `XLEN) (
|
||||
module graytobinary #(parameter N) (
|
||||
input logic [N-1:0] g,
|
||||
output logic [N-1:0] b);
|
||||
|
||||
|
@ -28,17 +28,15 @@
|
||||
// and limitations under the License.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module gpio_apb (
|
||||
module gpio_apb import cvw::*; #(parameter cvw_t P) (
|
||||
input logic PCLK, PRESETn,
|
||||
input logic PSEL,
|
||||
input logic [7:0] PADDR,
|
||||
input logic [`XLEN-1:0] PWDATA,
|
||||
input logic [`XLEN/8-1:0] PSTRB,
|
||||
input logic [P.XLEN-1:0] PWDATA,
|
||||
input logic [P.XLEN/8-1:0] PSTRB,
|
||||
input logic PWRITE,
|
||||
input logic PENABLE,
|
||||
output logic [`XLEN-1:0] PRDATA,
|
||||
output logic [P.XLEN-1:0] PRDATA,
|
||||
output logic PREADY,
|
||||
input logic [31:0] iof0, iof1,
|
||||
input logic [31:0] GPIOIN,
|
||||
@ -62,7 +60,7 @@ module gpio_apb (
|
||||
// account for subword read/write circuitry
|
||||
// -- Note GPIO registers are 32 bits no matter what; access them with LW SW.
|
||||
// (At least that's what I think when FE310 spec says "only naturally aligned 32-bit accesses are supported")
|
||||
if (`XLEN == 64) begin
|
||||
if (P.XLEN == 64) begin
|
||||
assign Din = entry[2] ? PWDATA[63:32] : PWDATA[31:0];
|
||||
assign PRDATA = entry[2] ? {Dout,32'b0} : {32'b0,Dout};
|
||||
end else begin // 32-bit
|
||||
@ -138,7 +136,7 @@ module gpio_apb (
|
||||
|
||||
// chip i/o
|
||||
// connect OUT to IN for loopback testing
|
||||
if (`GPIO_LOOPBACK_TEST) assign input0d = ((output_en & GPIOOUT) | (~output_en & GPIOIN)) & input_en;
|
||||
if (P.GPIO_LOOPBACK_TEST) assign input0d = ((output_en & GPIOOUT) | (~output_en & GPIOIN)) & input_en;
|
||||
else assign input0d = GPIOIN & input_en;
|
||||
|
||||
// synchroninzer for inputs
|
||||
|
@ -31,9 +31,7 @@
|
||||
// and limitations under the License.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
`define N `PLIC_NUM_SRC
|
||||
`define N P.PLIC_NUM_SRC
|
||||
// number of interrupt sources
|
||||
// does not include source 0, which does not connect to anything according to spec
|
||||
// up to 63 sources supported; in the future, allow up to 1023 sources
|
||||
@ -42,15 +40,15 @@
|
||||
// number of conexts
|
||||
// hardcoded to 2 contexts for now; later upgrade to arbitrary (up to 15872) contexts
|
||||
|
||||
module plic_apb (
|
||||
module plic_apb import cvw::*; #(parameter cvw_t P) (
|
||||
input logic PCLK, PRESETn,
|
||||
input logic PSEL,
|
||||
input logic [27:0] PADDR,
|
||||
input logic [`XLEN-1:0] PWDATA,
|
||||
input logic [`XLEN/8-1:0] PSTRB,
|
||||
input logic [P.XLEN-1:0] PWDATA,
|
||||
input logic [P.XLEN/8-1:0] PSTRB,
|
||||
input logic PWRITE,
|
||||
input logic PENABLE,
|
||||
output logic [`XLEN-1:0] PRDATA,
|
||||
output logic [P.XLEN-1:0] PRDATA,
|
||||
output logic PREADY,
|
||||
input logic UARTIntr,GPIOIntr,
|
||||
output logic MExtInt, SExtInt
|
||||
@ -86,7 +84,7 @@ module plic_apb (
|
||||
|
||||
// account for subword read/write circuitry
|
||||
// -- Note PLIC registers are 32 bits no matter what; access them with LW SW.
|
||||
if (`XLEN == 64) begin
|
||||
if (P.XLEN == 64) begin
|
||||
assign Din = entry[2] ? PWDATA[63:32] : PWDATA[31:0];
|
||||
assign PRDATA = entry[2] ? {Dout,32'b0} : {32'b0,Dout};
|
||||
end else begin // 32-bit
|
||||
@ -94,6 +92,8 @@ module plic_apb (
|
||||
assign Din = PWDATA[31:0];
|
||||
end
|
||||
|
||||
if (P.PLIC_NUM_SRC_LT_32) `define PLIC_NUM_SRC_LT_32
|
||||
|
||||
// ==================
|
||||
// Register Interface
|
||||
// ==================
|
||||
@ -101,9 +101,9 @@ module plic_apb (
|
||||
// resetting
|
||||
if (~PRESETn) begin
|
||||
intPriority <= #1 {`N{3'b0}};
|
||||
intEn <= #1 {2{`N'b0}};
|
||||
intEn <= #1 {2*`N{1'b0}};
|
||||
intThreshold <= #1 {2{3'b0}};
|
||||
intInProgress <= #1 `N'b0;
|
||||
intInProgress <= #1 {`N{1'b0}};
|
||||
// writing
|
||||
end else begin
|
||||
if (memwrite)
|
||||
@ -120,12 +120,12 @@ module plic_apb (
|
||||
24'h002084: intEn[1][`N:32] <= #1 Din[31:0];
|
||||
`endif
|
||||
24'h200000: intThreshold[0] <= #1 Din[2:0];
|
||||
24'h200004: intInProgress <= #1 intInProgress & ~(`N'b1 << (Din[5:0]-1)); // lower "InProgress" to signify completion
|
||||
24'h200004: intInProgress <= #1 intInProgress & ~({{`N-1{1'b0}}, 1'b1} << (Din[5:0]-1)); // lower "InProgress" to signify completion
|
||||
24'h201000: intThreshold[1] <= #1 Din[2:0];
|
||||
24'h201004: intInProgress <= #1 intInProgress & ~(`N'b1 << (Din[5:0]-1)); // lower "InProgress" to signify completion
|
||||
24'h201004: intInProgress <= #1 intInProgress & ~({{`N-1{1'b0}}, 1'b1} << (Din[5:0]-1)); // lower "InProgress" to signify completion
|
||||
endcase
|
||||
// Read synchronously because a read can have side effect of changing intInProgress
|
||||
if (memread)
|
||||
if (memread) begin
|
||||
casez(entry)
|
||||
24'h000000: Dout <= #1 32'b0; // there is no intPriority[0]
|
||||
24'h0000??: Dout <= #1 {29'b0,intPriority[entry[7:2]]};
|
||||
@ -145,31 +145,27 @@ module plic_apb (
|
||||
24'h200000: Dout <= #1 {29'b0,intThreshold[0]};
|
||||
24'h200004: begin
|
||||
Dout <= #1 {26'b0,intClaim[0]};
|
||||
intInProgress <= #1 intInProgress | (`N'b1 << (intClaim[0]-1)); // claimed requests are currently in progress of being serviced until they are completed
|
||||
intInProgress <= #1 intInProgress | ({{`N-1{1'b0}}, 1'b1} << (intClaim[0]-1)); // claimed requests are currently in progress of being serviced until they are completed
|
||||
end
|
||||
24'h201000: Dout <= #1 {29'b0,intThreshold[1]};
|
||||
24'h201004: begin
|
||||
Dout <= #1 {26'b0,intClaim[1]};
|
||||
intInProgress <= #1 intInProgress | (`N'b1 << (intClaim[1]-1)); // claimed requests are currently in progress of being serviced until they are completed
|
||||
intInProgress <= #1 intInProgress | ({{`N-1{1'b0}}, 1'b1} << (intClaim[1]-1)); // claimed requests are currently in progress of being serviced until they are completed
|
||||
end
|
||||
default: Dout <= #1 32'h0; // invalid access
|
||||
endcase
|
||||
else Dout <= #1 32'h0;
|
||||
end else Dout <= #1 32'h0;
|
||||
end
|
||||
end
|
||||
|
||||
// connect sources to requests
|
||||
always_comb begin
|
||||
requests = `N'b0;
|
||||
`ifdef PLIC_GPIO_ID
|
||||
requests[`PLIC_GPIO_ID] = GPIOIntr;
|
||||
`endif
|
||||
`ifdef PLIC_UART_ID
|
||||
requests[`PLIC_UART_ID] = UARTIntr;
|
||||
`endif
|
||||
requests = {`N{1'b0}};
|
||||
if(P.PLIC_GPIO_ID != 0) requests[P.PLIC_GPIO_ID] = GPIOIntr;
|
||||
if(P.PLIC_UART_ID != 0) requests[P.PLIC_UART_ID] = UARTIntr;
|
||||
end
|
||||
|
||||
// pending interrupt requests
|
||||
// pending interrupt request
|
||||
assign nextIntPending = (intPending | requests) & ~intInProgress;
|
||||
flopr #(`N) intPendingFlop(PCLK,~PRESETn,nextIntPending,intPending);
|
||||
|
||||
|
@ -26,27 +26,26 @@
|
||||
// and limitations under the License.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
`define RAM_LATENCY 0
|
||||
|
||||
module ram_ahb #(parameter BASE=0, RANGE = 65535) (
|
||||
module ram_ahb import cvw::*; #(parameter cvw_t P, BASE=0, RANGE = 65535) (
|
||||
input logic HCLK, HRESETn,
|
||||
input logic HSELRam,
|
||||
input logic [`PA_BITS-1:0] HADDR,
|
||||
input logic [P.PA_BITS-1:0] HADDR,
|
||||
input logic HWRITE,
|
||||
input logic HREADY,
|
||||
input logic [1:0] HTRANS,
|
||||
input logic [`XLEN-1:0] HWDATA,
|
||||
input logic [`XLEN/8-1:0] HWSTRB,
|
||||
output logic [`XLEN-1:0] HREADRam,
|
||||
input logic [P.XLEN-1:0] HWDATA,
|
||||
input logic [P.XLEN/8-1:0] HWSTRB,
|
||||
output logic [P.XLEN-1:0] HREADRam,
|
||||
output logic HRESPRam, HREADYRam
|
||||
);
|
||||
|
||||
localparam ADDR_WIDTH = $clog2(RANGE/8);
|
||||
localparam OFFSET = $clog2(`XLEN/8);
|
||||
localparam OFFSET = $clog2(P.XLEN/8);
|
||||
|
||||
logic [`XLEN/8-1:0] ByteMask;
|
||||
logic [`PA_BITS-1:0] HADDRD, RamAddr;
|
||||
logic [P.XLEN/8-1:0] ByteMask;
|
||||
logic [P.PA_BITS-1:0] HADDRD, RamAddr;
|
||||
logic initTrans;
|
||||
logic memwrite, memwriteD, memread;
|
||||
logic nextHREADYRam;
|
||||
@ -59,7 +58,7 @@ module ram_ahb #(parameter BASE=0, RANGE = 65535) (
|
||||
assign memread = initTrans & ~HWRITE;
|
||||
|
||||
flopenr #(1) memwritereg(HCLK, ~HRESETn, HREADY, memwrite, memwriteD);
|
||||
flopenr #(`PA_BITS) haddrreg(HCLK, ~HRESETn, HREADY, HADDR, HADDRD);
|
||||
flopenr #(P.PA_BITS) haddrreg(HCLK, ~HRESETn, HREADY, HADDR, HADDRD);
|
||||
|
||||
// Stall on a read after a write because the RAM can't take both adddresses on the same cycle
|
||||
assign nextHREADYRam = (~(memwriteD & memread)) & ~DelayReady;
|
||||
@ -68,10 +67,10 @@ module ram_ahb #(parameter BASE=0, RANGE = 65535) (
|
||||
assign HRESPRam = 0; // OK
|
||||
|
||||
// On writes or during a wait state, use address delayed by one cycle to sync RamAddr with HWDATA or hold stalled address
|
||||
mux2 #(`PA_BITS) adrmux(HADDR, HADDRD, memwriteD | ~HREADY, RamAddr);
|
||||
mux2 #(P.PA_BITS) adrmux(HADDR, HADDRD, memwriteD | ~HREADY, RamAddr);
|
||||
|
||||
// single-ported RAM
|
||||
ram1p1rwbe #(.DEPTH(RANGE/8), .WIDTH(`XLEN)) memory(.clk(HCLK), .ce(1'b1),
|
||||
ram1p1rwbe #(.DEPTH(RANGE/8), .WIDTH(P.XLEN)) memory(.clk(HCLK), .ce(1'b1),
|
||||
.addr(RamAddr[ADDR_WIDTH+OFFSET-1:OFFSET]), .we(memwriteD), .din(HWDATA), .bwe(HWSTRB), .dout(HREADRam));
|
||||
|
||||
|
||||
|
@ -26,27 +26,25 @@
|
||||
// and limitations under the License.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module rom_ahb #(parameter BASE=0, RANGE = 65535) (
|
||||
module rom_ahb import cvw::*; #(parameter cvw_t P, BASE=0, RANGE = 65535) (
|
||||
input logic HCLK, HRESETn,
|
||||
input logic HSELRom,
|
||||
input logic [`PA_BITS-1:0] HADDR,
|
||||
input logic [P.PA_BITS-1:0] HADDR,
|
||||
input logic HREADY,
|
||||
input logic [1:0] HTRANS,
|
||||
output logic [`XLEN-1:0] HREADRom,
|
||||
output logic [P.XLEN-1:0] HREADRom,
|
||||
output logic HRESPRom, HREADYRom
|
||||
);
|
||||
|
||||
localparam ADDR_WIDTH = $clog2(RANGE/8);
|
||||
localparam OFFSET = $clog2(`XLEN/8);
|
||||
localparam OFFSET = $clog2(P.XLEN/8);
|
||||
|
||||
// Never stalls
|
||||
assign HREADYRom = 1'b1;
|
||||
assign HRESPRom = 0; // OK
|
||||
|
||||
// single-ported ROM
|
||||
rom1p1r #(ADDR_WIDTH, `XLEN, `FPGA)
|
||||
rom1p1r #(ADDR_WIDTH, P.XLEN, P.FPGA)
|
||||
memory(.clk(HCLK), .ce(1'b1), .addr(HADDR[ADDR_WIDTH+OFFSET-1:OFFSET]), .dout(HREADRom));
|
||||
endmodule
|
||||
|
||||
|
@ -33,10 +33,9 @@
|
||||
// and limitations under the License.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
/* verilator lint_off UNOPTFLAT */
|
||||
|
||||
module uartPC16550D(
|
||||
module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
||||
// Processor Interface
|
||||
input logic PCLK, PRESETn, // UART clock and active low reset
|
||||
input logic [2:0] A, // address input (8 registers)
|
||||
@ -73,7 +72,7 @@ module uartPC16550D(
|
||||
|
||||
// Baud and rx/tx timing
|
||||
logic baudpulse, txbaudpulse, rxbaudpulse; // high one system clk cycle each baud/16 period
|
||||
logic [16+`UART_PRESCALE-1:0] baudcount;
|
||||
logic [16+UART_PRESCALE-1:0] baudcount;
|
||||
logic [3:0] rxoversampledcnt, txoversampledcnt; // count oversampled-by-16
|
||||
logic [3:0] rxbitsreceived, txbitssent;
|
||||
statetype rxstate, txstate;
|
||||
@ -137,7 +136,7 @@ module uartPC16550D(
|
||||
if (~PRESETn) begin // Table 3 Reset Configuration
|
||||
IER <= #1 4'b0;
|
||||
FCR <= #1 8'b0;
|
||||
if (`QEMU) LCR <= #1 8'b0; else LCR <= #1 8'b11; // fpga only **** BUG
|
||||
if (QEMU) LCR <= #1 8'b0; else LCR <= #1 8'b11; // fpga only **** BUG
|
||||
MCR <= #1 5'b0;
|
||||
LSR <= #1 8'b01100000;
|
||||
MSR <= #1 4'b0;
|
||||
@ -225,7 +224,7 @@ module uartPC16550D(
|
||||
baudcount <= #1 baudpulseComb ? 1 : baudcount +1;
|
||||
end
|
||||
|
||||
assign baudpulseComb = (baudcount == {DLM, DLL, {(`UART_PRESCALE){1'b0}}});
|
||||
assign baudpulseComb = (baudcount == {DLM, DLL, {(UART_PRESCALE){1'b0}}});
|
||||
|
||||
assign txbaudpulse = baudpulse;
|
||||
assign BAUDOUTb = ~baudpulse;
|
||||
@ -260,7 +259,7 @@ module uartPC16550D(
|
||||
end
|
||||
|
||||
// ***explain why
|
||||
if(`QEMU) assign rxcentered = rxbaudpulse & (rxoversampledcnt[1:0] == 2'b10); // implies rxstate = UART_ACTIVE
|
||||
if(QEMU) assign rxcentered = rxbaudpulse & (rxoversampledcnt[1:0] == 2'b10); // implies rxstate = UART_ACTIVE
|
||||
else assign rxcentered = rxbaudpulse & (rxoversampledcnt == 4'b1000); // implies rxstate = UART_ACTIVE
|
||||
|
||||
assign rxbitsexpected = 4'd1 + (4'd5 + {2'b00, LCR[1:0]}) + {3'b000, LCR[3]} + 4'd1; // start bit + data bits + (parity bit) + stop bit
|
||||
@ -390,7 +389,7 @@ module uartPC16550D(
|
||||
|
||||
assign txbitsexpected = 4'd1 + (4'd5 + {2'b00, LCR[1:0]}) + {3'b000, LCR[3]} + 4'd1 + {3'b000, LCR[2]} - 4'd1; // start bit + data bits + (parity bit) + stop bit(s) - 1
|
||||
// *** explain; is this necessary?
|
||||
if (`QEMU) assign txnextbit = txbaudpulse & (txoversampledcnt[1:0] == 2'b00); // implies txstate = UART_ACTIVE
|
||||
if (QEMU) assign txnextbit = txbaudpulse & (txoversampledcnt[1:0] == 2'b00); // implies txstate = UART_ACTIVE
|
||||
else assign txnextbit = txbaudpulse & (txoversampledcnt == 4'b0000); // implies txstate = UART_ACTIVE
|
||||
|
||||
///////////////////////////////////////////
|
||||
|
@ -28,17 +28,15 @@
|
||||
// and limitations under the License.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module uart_apb (
|
||||
module uart_apb import cvw::*; #(parameter cvw_t P) (
|
||||
input logic PCLK, PRESETn,
|
||||
input logic PSEL,
|
||||
input logic [2:0] PADDR,
|
||||
input logic [`XLEN-1:0] PWDATA,
|
||||
input logic [`XLEN/8-1:0] PSTRB,
|
||||
input logic [P.XLEN-1:0] PWDATA,
|
||||
input logic [P.XLEN/8-1:0] PSTRB,
|
||||
input logic PWRITE,
|
||||
input logic PENABLE,
|
||||
output logic [`XLEN-1:0] PRDATA,
|
||||
output logic [P.XLEN-1:0] PRDATA,
|
||||
output logic PREADY,
|
||||
input logic SIN, DSRb, DCDb, CTSb, RIb, // from E1A driver from RS232 interface
|
||||
output logic SOUT, RTSb, DTRb, // to E1A driver to RS232 interface
|
||||
@ -56,7 +54,7 @@ module uart_apb (
|
||||
assign MEMRb = ~memread;
|
||||
assign MEMWb = ~memwrite;
|
||||
|
||||
if (`XLEN == 64) begin:uart
|
||||
if (P.XLEN == 64) begin:uart
|
||||
always_comb begin
|
||||
PRDATA = {Dout, Dout, Dout, Dout, Dout, Dout, Dout, Dout};
|
||||
case (entry)
|
||||
@ -84,7 +82,7 @@ module uart_apb (
|
||||
|
||||
logic BAUDOUTb; // loop tx clock BAUDOUTb back to rx clock RCLK
|
||||
// *** make sure reads don't occur on UART unless fully selected because they could change state. This applies to all peripherals
|
||||
uartPC16550D u(
|
||||
uartPC16550D #(P.UART_PRESCALE, P.QEMU) u(
|
||||
// Processor Interface
|
||||
.PCLK, .PRESETn,
|
||||
.A(entry), .Din,
|
||||
|
@ -27,24 +27,22 @@
|
||||
// and limitations under the License.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module uncore import cvw::*; #(parameter cvw_t P)(
|
||||
// AHB Bus Interface
|
||||
input logic HCLK, HRESETn,
|
||||
input logic TIMECLK,
|
||||
input logic [`PA_BITS-1:0] HADDR,
|
||||
input logic [`AHBW-1:0] HWDATA,
|
||||
input logic [`XLEN/8-1:0] HWSTRB,
|
||||
input logic [P.PA_BITS-1:0] HADDR,
|
||||
input logic [P.AHBW-1:0] HWDATA,
|
||||
input logic [P.XLEN/8-1:0] HWSTRB,
|
||||
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 [P.AHBW-1:0] HRDATAEXT,
|
||||
input logic HREADYEXT, HRESPEXT,
|
||||
output logic [`AHBW-1:0] HRDATA,
|
||||
output logic [P.AHBW-1:0] HRDATA,
|
||||
output logic HREADY, HRESP,
|
||||
output logic HSELEXT,
|
||||
// peripheral pins
|
||||
@ -62,14 +60,14 @@ module uncore import cvw::*; #(parameter cvw_t P)(
|
||||
output logic SDCCLK // SD Card clock
|
||||
);
|
||||
|
||||
logic [`XLEN-1:0] HREADRam, HREADSDC;
|
||||
logic [P.XLEN-1:0] HREADRam, HREADSDC;
|
||||
|
||||
logic [10:0] HSELRegions;
|
||||
logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART, HSELSDC;
|
||||
logic HSELDTIMD, HSELIROMD, HSELEXTD, HSELRamD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD, HSELSDCD;
|
||||
logic HRESPRam, HRESPSDC;
|
||||
logic HREADYRam, HRESPSDCD;
|
||||
logic [`XLEN-1:0] HREADBootRom;
|
||||
logic [P.XLEN-1:0] HREADBootRom;
|
||||
logic HSELBootRom, HSELBootRomD, HRESPBootRom, HREADYBootRom, HREADYSDC;
|
||||
logic HSELNoneD;
|
||||
logic UARTIntr,GPIOIntr;
|
||||
@ -78,10 +76,10 @@ module uncore import cvw::*; #(parameter cvw_t P)(
|
||||
logic PCLK, PRESETn, PWRITE, PENABLE;
|
||||
logic [3:0] PSEL, PREADY;
|
||||
logic [31:0] PADDR;
|
||||
logic [`XLEN-1:0] PWDATA;
|
||||
logic [`XLEN/8-1:0] PSTRB;
|
||||
logic [3:0][`XLEN-1:0] PRDATA;
|
||||
logic [`XLEN-1:0] HREADBRIDGE;
|
||||
logic [P.XLEN-1:0] PWDATA;
|
||||
logic [P.XLEN/8-1:0] PSTRB;
|
||||
logic [3:0][P.XLEN-1:0] PRDATA;
|
||||
logic [P.XLEN-1:0] HREADBRIDGE;
|
||||
logic HRESPBRIDGE, HREADYBRIDGE, HSELBRIDGE, HSELBRIDGED;
|
||||
|
||||
// Determine which region of physical memory (if any) is being accessed
|
||||
@ -93,52 +91,52 @@ module uncore import cvw::*; #(parameter cvw_t P)(
|
||||
assign {HSELDTIM, HSELIROM, HSELEXT, HSELBootRom, HSELRam, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC, HSELSDC} = HSELRegions[10:1];
|
||||
|
||||
// AHB -> APB bridge
|
||||
ahbapbbridge #(4) ahbapbbridge (
|
||||
ahbapbbridge #(P, 4) ahbapbbridge (
|
||||
.HCLK, .HRESETn, .HSEL({HSELUART, HSELPLIC, HSELCLINT, HSELGPIO}), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY,
|
||||
.HRDATA(HREADBRIDGE), .HRESP(HRESPBRIDGE), .HREADYOUT(HREADYBRIDGE),
|
||||
.PCLK, .PRESETn, .PSEL, .PWRITE, .PENABLE, .PADDR, .PWDATA, .PSTRB, .PREADY, .PRDATA);
|
||||
assign HSELBRIDGE = HSELGPIO | HSELCLINT | HSELPLIC | HSELUART; // if any of the bridge signals are selected
|
||||
|
||||
// on-chip RAM
|
||||
if (`UNCORE_RAM_SUPPORTED) begin : ram
|
||||
ram_ahb #(.BASE(`UNCORE_RAM_BASE), .RANGE(`UNCORE_RAM_RANGE)) ram (
|
||||
if (P.UNCORE_RAM_SUPPORTED) begin : ram
|
||||
ram_ahb #(.P(P), .BASE(P.UNCORE_RAM_BASE), .RANGE(P.UNCORE_RAM_RANGE)) ram (
|
||||
.HCLK, .HRESETn, .HSELRam, .HADDR, .HWRITE, .HREADY,
|
||||
.HTRANS, .HWDATA, .HWSTRB, .HREADRam, .HRESPRam, .HREADYRam);
|
||||
end
|
||||
|
||||
if (`BOOTROM_SUPPORTED) begin : bootrom
|
||||
rom_ahb #(.BASE(`BOOTROM_BASE), .RANGE(`BOOTROM_RANGE))
|
||||
if (P.BOOTROM_SUPPORTED) begin : bootrom
|
||||
rom_ahb #(.P(P), .BASE(P.BOOTROM_BASE), .RANGE(P.BOOTROM_RANGE))
|
||||
bootrom(.HCLK, .HRESETn, .HSELRom(HSELBootRom), .HADDR, .HREADY, .HTRANS,
|
||||
.HREADRom(HREADBootRom), .HRESPRom(HRESPBootRom), .HREADYRom(HREADYBootRom));
|
||||
end
|
||||
|
||||
// memory-mapped I/O peripherals
|
||||
if (`CLINT_SUPPORTED == 1) begin : clint
|
||||
clint_apb clint(.PCLK, .PRESETn, .PSEL(PSEL[1]), .PADDR(PADDR[15:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE,
|
||||
if (P.CLINT_SUPPORTED == 1) begin : clint
|
||||
clint_apb #(P) clint(.PCLK, .PRESETn, .PSEL(PSEL[1]), .PADDR(PADDR[15:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE,
|
||||
.PRDATA(PRDATA[1]), .PREADY(PREADY[1]), .MTIME(MTIME_CLINT), .MTimerInt, .MSwInt);
|
||||
end else begin : clint
|
||||
assign MTIME_CLINT = 0;
|
||||
assign MTimerInt = 0; assign MSwInt = 0;
|
||||
end
|
||||
|
||||
if (`PLIC_SUPPORTED == 1) begin : plic
|
||||
plic_apb plic(.PCLK, .PRESETn, .PSEL(PSEL[2]), .PADDR(PADDR[27:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE,
|
||||
if (P.PLIC_SUPPORTED == 1) begin : plic
|
||||
plic_apb #(P) plic(.PCLK, .PRESETn, .PSEL(PSEL[2]), .PADDR(PADDR[27:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE,
|
||||
.PRDATA(PRDATA[2]), .PREADY(PREADY[2]), .UARTIntr, .GPIOIntr, .MExtInt, .SExtInt);
|
||||
end else begin : plic
|
||||
assign MExtInt = 0;
|
||||
assign SExtInt = 0;
|
||||
end
|
||||
|
||||
if (`GPIO_SUPPORTED == 1) begin : gpio
|
||||
gpio_apb gpio(
|
||||
if (P.GPIO_SUPPORTED == 1) begin : gpio
|
||||
gpio_apb #(P) gpio(
|
||||
.PCLK, .PRESETn, .PSEL(PSEL[0]), .PADDR(PADDR[7:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE,
|
||||
.PRDATA(PRDATA[0]), .PREADY(PREADY[0]),
|
||||
.iof0(), .iof1(), .GPIOIN, .GPIOOUT, .GPIOEN, .GPIOIntr);
|
||||
end else begin : gpio
|
||||
assign GPIOOUT = 0; assign GPIOEN = 0; assign GPIOIntr = 0;
|
||||
end
|
||||
if (`UART_SUPPORTED == 1) begin : uart
|
||||
uart_apb uart(
|
||||
if (P.UART_SUPPORTED == 1) begin : uart
|
||||
uart_apb #(P) uart(
|
||||
.PCLK, .PRESETn, .PSEL(PSEL[3]), .PADDR(PADDR[2:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE,
|
||||
.PRDATA(PRDATA[3]), .PREADY(PREADY[3]),
|
||||
.SIN(UARTSin), .DSRb(1'b1), .DCDb(1'b1), .CTSb(1'b0), .RIb(1'b1), // from E1A driver from RS232 interface
|
||||
@ -147,7 +145,7 @@ module uncore import cvw::*; #(parameter cvw_t P)(
|
||||
end else begin : uart
|
||||
assign UARTSout = 0; assign UARTIntr = 0;
|
||||
end
|
||||
if (`SDC_SUPPORTED == 1) begin : sdc
|
||||
if (P.SDC_SUPPORTED == 1) begin : sdc
|
||||
SDC SDC(.HCLK, .HRESETn, .HSELSDC, .HADDR(HADDR[4:0]), .HWRITE, .HREADY, .HTRANS,
|
||||
.HWDATA, .HREADSDC, .HRESPSDC, .HREADYSDC,
|
||||
// sdc interface
|
||||
@ -162,11 +160,11 @@ module uncore import cvw::*; #(parameter cvw_t P)(
|
||||
end
|
||||
|
||||
// AHB Read Multiplexer
|
||||
assign HRDATA = ({`XLEN{HSELRamD}} & HREADRam) |
|
||||
({`XLEN{HSELEXTD}} & HRDATAEXT) |
|
||||
({`XLEN{HSELBRIDGED}} & HREADBRIDGE) |
|
||||
({`XLEN{HSELBootRomD}} & HREADBootRom) |
|
||||
({`XLEN{HSELSDCD}} & HREADSDC);
|
||||
assign HRDATA = ({P.XLEN{HSELRamD}} & HREADRam) |
|
||||
({P.XLEN{HSELEXTD}} & HRDATAEXT) |
|
||||
({P.XLEN{HSELBRIDGED}} & HREADBRIDGE) |
|
||||
({P.XLEN{HSELBootRomD}} & HREADBootRom) |
|
||||
({P.XLEN{HSELSDCD}} & HREADSDC);
|
||||
|
||||
assign HRESP = HSELRamD & HRESPRam |
|
||||
HSELEXTD & HRESPEXT |
|
||||
|
Loading…
Reference in New Issue
Block a user