mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Partially solved fpga boot.
This commit is contained in:
parent
4b3b590f21
commit
c0fdd3fbca
@ -31,7 +31,6 @@
|
|||||||
// and limitations under the License.
|
// and limitations under the License.
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
`define N P.PLIC_NUM_SRC
|
|
||||||
// number of interrupt sources
|
// number of interrupt sources
|
||||||
// does not include source 0, which does not connect to anything according to spec
|
// 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
|
// up to 63 sources supported; in the future, allow up to 1023 sources
|
||||||
@ -59,19 +58,20 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [31:0] Din, Dout;
|
logic [31:0] Din, Dout;
|
||||||
|
|
||||||
// context-independent signals
|
// context-independent signals
|
||||||
logic [`N:1] requests;
|
logic [P.PLIC_NUM_SRC:1] requests;
|
||||||
logic [`N:1][2:0] intPriority;
|
logic [P.PLIC_NUM_SRC:1][2:0] intPriority;
|
||||||
logic [`N:1] intInProgress, intPending, nextIntPending;
|
logic [P.PLIC_NUM_SRC:1] intInProgress, intPending, nextIntPending;
|
||||||
|
|
||||||
// context-dependent signals
|
// context-dependent signals
|
||||||
logic [`C-1:0][2:0] intThreshold;
|
logic [`C-1:0][2:0] intThreshold;
|
||||||
logic [`C-1:0][`N:1] intEn;
|
logic [`C-1:0][P.PLIC_NUM_SRC:1] intEn;
|
||||||
logic [`C-1:0][5:0] intClaim; // ID's are 6 bits if we stay within 63 sources
|
logic [`C-1:0][5:0] intClaim; // ID's are 6 bits if we stay within 63 sources
|
||||||
logic [`C-1:0][7:1][`N:1] irqMatrix;
|
logic [`C-1:0][7:1][P.PLIC_NUM_SRC:1] irqMatrix;
|
||||||
logic [`C-1:0][7:1] priorities_with_irqs;
|
logic [`C-1:0][7:1] priorities_with_irqs;
|
||||||
logic [`C-1:0][7:1] max_priority_with_irqs;
|
logic [`C-1:0][7:1] max_priority_with_irqs;
|
||||||
logic [`C-1:0][`N:1] irqs_at_max_priority;
|
logic [`C-1:0][P.PLIC_NUM_SRC:1] irqs_at_max_priority;
|
||||||
logic [`C-1:0][7:1] threshMask;
|
logic [`C-1:0][7:1] threshMask;
|
||||||
|
logic [P.PLIC_NUM_SRC-1:0] One;
|
||||||
|
|
||||||
// =======
|
// =======
|
||||||
// AHB I/O
|
// AHB I/O
|
||||||
@ -81,6 +81,7 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign memread = ~PWRITE & PSEL; // read at start of access phase. PENABLE hasn't set up before this
|
assign memread = ~PWRITE & PSEL; // read at start of access phase. PENABLE hasn't set up before this
|
||||||
assign PREADY = 1'b1; // PLIC never takes >1 cycle to respond
|
assign PREADY = 1'b1; // PLIC never takes >1 cycle to respond
|
||||||
assign entry = {PADDR[23:2],2'b0};
|
assign entry = {PADDR[23:2],2'b0};
|
||||||
|
assign One[P.PLIC_NUM_SRC-1:1] = '0; assign One[0] = 1'b1; // Vivado does not like this as a single assignment.
|
||||||
|
|
||||||
// account for subword read/write circuitry
|
// account for subword read/write circuitry
|
||||||
// -- Note PLIC registers are 32 bits no matter what; access them with LW SW.
|
// -- Note PLIC registers are 32 bits no matter what; access them with LW SW.
|
||||||
@ -92,7 +93,12 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign Din = PWDATA[31:0];
|
assign Din = PWDATA[31:0];
|
||||||
end
|
end
|
||||||
|
|
||||||
if (P.PLIC_NUM_SRC_LT_32) `define PLIC_NUM_SRC_LT_32
|
// *** RT: 05 July 2023: BUG BUG BUG. PLIC_NUM_SRC_LT_32 is undefined after parameterization
|
||||||
|
// the FPGA does work the following code. For now I'm leaving the `define undefined but this
|
||||||
|
// means the code is only valid for 33 to 64 interrupt sources. In general this needs to be
|
||||||
|
// rethought for a more generalized implementation.
|
||||||
|
//if (P.PLIC_NUM_SRC_LT_32) `define PLIC_NUM_SRC_LT_32
|
||||||
|
//`define PLIC_NUM_SRC_LT_32
|
||||||
|
|
||||||
// ==================
|
// ==================
|
||||||
// Register Interface
|
// Register Interface
|
||||||
@ -101,29 +107,29 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
always @(posedge PCLK) begin
|
always @(posedge PCLK) begin
|
||||||
// resetting
|
// resetting
|
||||||
if (~PRESETn) begin
|
if (~PRESETn) begin
|
||||||
intPriority <= #1 {`N{3'b0}};
|
intPriority <= #1 '0;
|
||||||
intEn <= #1 {2*`N{1'b0}};
|
intEn <= #1 '0;
|
||||||
intThreshold <= #1 {2{3'b0}};
|
intThreshold <= #1 '0;
|
||||||
intInProgress <= #1 {`N{1'b0}};
|
intInProgress <= #1 '0;
|
||||||
// writing
|
// writing
|
||||||
end else begin
|
end else begin
|
||||||
if (memwrite)
|
if (memwrite)
|
||||||
casez(entry)
|
casez(entry)
|
||||||
24'h0000??: intPriority[entry[7:2]] <= #1 Din[2:0];
|
24'h0000??: intPriority[entry[7:2]] <= #1 Din[2:0];
|
||||||
`ifdef PLIC_NUM_SRC_LT_32 // eventually switch to a generate for loop so as to deprecate PLIC_NUM_SRC_LT_32 and allow up to 1023 sources
|
`ifdef PLIC_NUM_SRC_LT_32 // eventually switch to a generate for loop so as to deprecate PLIC_NUM_SRC_LT_32 and allow up to 1023 sources
|
||||||
24'h002000: intEn[0][`N:1] <= #1 Din[`N:1];
|
24'h002000: intEn[0][P.PLIC_NUM_SRC:1] <= #1 Din[P.PLIC_NUM_SRC:1];
|
||||||
24'h002080: intEn[1][`N:1] <= #1 Din[`N:1];
|
24'h002080: intEn[1][P.PLIC_NUM_SRC:1] <= #1 Din[P.PLIC_NUM_SRC:1];
|
||||||
`endif
|
`endif
|
||||||
`ifndef PLIC_NUM_SRC_LT_32
|
`ifndef PLIC_NUM_SRC_LT_32
|
||||||
24'h002000: intEn[0][31:1] <= #1 Din[31:1];
|
24'h002000: intEn[0][31:1] <= #1 Din[31:1];
|
||||||
24'h002004: intEn[0][`N:32] <= #1 Din[31:0];
|
24'h002004: intEn[0][P.PLIC_NUM_SRC:32] <= #1 Din[P.PLIC_NUM_SRC-32:0];
|
||||||
24'h002080: intEn[1][31:1] <= #1 Din[31:1];
|
24'h002080: intEn[1][31:1] <= #1 Din[31:1];
|
||||||
24'h002084: intEn[1][`N:32] <= #1 Din[31:0];
|
24'h002084: intEn[1][P.PLIC_NUM_SRC:32] <= #1 Din[P.PLIC_NUM_SRC-32:0];
|
||||||
`endif
|
`endif
|
||||||
24'h200000: intThreshold[0] <= #1 Din[2:0];
|
24'h200000: intThreshold[0] <= #1 Din[2:0];
|
||||||
24'h200004: intInProgress <= #1 intInProgress & ~({{`N-1{1'b0}}, 1'b1} << (Din[5:0]-1)); // lower "InProgress" to signify completion
|
24'h200004: intInProgress <= #1 intInProgress & ~(One << (Din[5:0]-1)); // lower "InProgress" to signify completion
|
||||||
24'h201000: intThreshold[1] <= #1 Din[2:0];
|
24'h201000: intThreshold[1] <= #1 Din[2:0];
|
||||||
24'h201004: intInProgress <= #1 intInProgress & ~({{`N-1{1'b0}}, 1'b1} << (Din[5:0]-1)); // lower "InProgress" to signify completion
|
24'h201004: intInProgress <= #1 intInProgress & ~(One << (Din[5:0]-1)); // lower "InProgress" to signify completion
|
||||||
endcase
|
endcase
|
||||||
// Read synchronously because a read can have side effect of changing intInProgress
|
// Read synchronously because a read can have side effect of changing intInProgress
|
||||||
if (memread) begin
|
if (memread) begin
|
||||||
@ -131,27 +137,27 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
24'h000000: Dout <= #1 32'b0; // there is no intPriority[0]
|
24'h000000: Dout <= #1 32'b0; // there is no intPriority[0]
|
||||||
24'h0000??: Dout <= #1 {29'b0,intPriority[entry[7:2]]};
|
24'h0000??: Dout <= #1 {29'b0,intPriority[entry[7:2]]};
|
||||||
`ifdef PLIC_NUM_SRC_LT_32
|
`ifdef PLIC_NUM_SRC_LT_32
|
||||||
24'h001000: Dout <= #1 {{(31-`N){1'b0}},intPending,1'b0};
|
24'h001000: Dout <= #1 {{(31-P.PLIC_NUM_SRC){1'b0}},intPending,1'b0};
|
||||||
24'h002000: Dout <= #1 {{(31-`N){1'b0}},intEn[0],1'b0};
|
24'h002000: Dout <= #1 {{(31-P.PLIC_NUM_SRC){1'b0}},intEn[0],1'b0};
|
||||||
24'h002080: Dout <= #1 {{(31-`N){1'b0}},intEn[1],1'b0};
|
24'h002080: Dout <= #1 {{(31-P.PLIC_NUM_SRC){1'b0}},intEn[1],1'b0};
|
||||||
`endif
|
`endif
|
||||||
`ifndef PLIC_NUM_SRC_LT_32
|
`ifndef PLIC_NUM_SRC_LT_32
|
||||||
24'h001000: Dout <= #1 {intPending[31:1],1'b0};
|
24'h001000: Dout <= #1 {intPending[31:1],1'b0};
|
||||||
24'h001004: Dout <= #1 {{(63-`N){1'b0}},intPending[`N:32]};
|
24'h001004: Dout <= #1 {{(63-P.PLIC_NUM_SRC){1'b0}},intPending[P.PLIC_NUM_SRC:32]};
|
||||||
24'h002000: Dout <= #1 {intEn[0][31:1],1'b0};
|
24'h002000: Dout <= #1 {intEn[0][31:1],1'b0};
|
||||||
24'h002004: Dout <= #1 {{(63-`N){1'b0}},intEn[0][`N:32]};
|
24'h002004: Dout <= #1 {{(63-P.PLIC_NUM_SRC){1'b0}},intEn[0][P.PLIC_NUM_SRC:32]};
|
||||||
24'h002080: Dout <= #1 {intEn[0][31:1],1'b0};
|
24'h002080: Dout <= #1 {intEn[0][31:1],1'b0};
|
||||||
24'h002084: Dout <= #1 {{(63-`N){1'b0}},intEn[1][`N:32]};
|
24'h002084: Dout <= #1 {{(63-P.PLIC_NUM_SRC){1'b0}},intEn[1][P.PLIC_NUM_SRC:32]};
|
||||||
`endif
|
`endif
|
||||||
24'h200000: Dout <= #1 {29'b0,intThreshold[0]};
|
24'h200000: Dout <= #1 {29'b0,intThreshold[0]};
|
||||||
24'h200004: begin
|
24'h200004: begin
|
||||||
Dout <= #1 {26'b0,intClaim[0]};
|
Dout <= #1 {26'b0,intClaim[0]};
|
||||||
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
|
intInProgress <= #1 intInProgress | (One << (intClaim[0]-1)); // claimed requests are currently in progress of being serviced until they are completed
|
||||||
end
|
end
|
||||||
24'h201000: Dout <= #1 {29'b0,intThreshold[1]};
|
24'h201000: Dout <= #1 {29'b0,intThreshold[1]};
|
||||||
24'h201004: begin
|
24'h201004: begin
|
||||||
Dout <= #1 {26'b0,intClaim[1]};
|
Dout <= #1 {26'b0,intClaim[1]};
|
||||||
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
|
intInProgress <= #1 intInProgress | (One << (intClaim[1]-1)); // claimed requests are currently in progress of being serviced until they are completed
|
||||||
end
|
end
|
||||||
default: Dout <= #1 32'h0; // invalid access
|
default: Dout <= #1 32'h0; // invalid access
|
||||||
endcase
|
endcase
|
||||||
@ -161,14 +167,14 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
// connect sources to requests
|
// connect sources to requests
|
||||||
always_comb begin
|
always_comb begin
|
||||||
requests = {`N{1'b0}};
|
requests = {P.PLIC_NUM_SRC{1'b0}};
|
||||||
if(P.PLIC_GPIO_ID != 0) requests[P.PLIC_GPIO_ID] = GPIOIntr;
|
if(P.PLIC_GPIO_ID != 0) requests[P.PLIC_GPIO_ID] = GPIOIntr;
|
||||||
if(P.PLIC_UART_ID != 0) requests[P.PLIC_UART_ID] = UARTIntr;
|
if(P.PLIC_UART_ID != 0) requests[P.PLIC_UART_ID] = UARTIntr;
|
||||||
end
|
end
|
||||||
|
|
||||||
// pending interrupt request
|
// pending interrupt request
|
||||||
assign nextIntPending = (intPending | requests) & ~intInProgress;
|
assign nextIntPending = (intPending | requests) & ~intInProgress;
|
||||||
flopr #(`N) intPendingFlop(PCLK,~PRESETn,nextIntPending,intPending);
|
flopr #(P.PLIC_NUM_SRC) intPendingFlop(PCLK,~PRESETn,nextIntPending,intPending);
|
||||||
|
|
||||||
// context-dependent signals
|
// context-dependent signals
|
||||||
genvar ctx;
|
genvar ctx;
|
||||||
@ -181,7 +187,7 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
// ("active" meaning it is enabled in context <ctx> and is pending)
|
// ("active" meaning it is enabled in context <ctx> and is pending)
|
||||||
genvar src, pri;
|
genvar src, pri;
|
||||||
for (pri=1; pri<=7; pri++) begin
|
for (pri=1; pri<=7; pri++) begin
|
||||||
for (src=1; src<=`N; src++) begin
|
for (src=1; src<=P.PLIC_NUM_SRC; src++) begin
|
||||||
assign irqMatrix[ctx][pri][src] = (intPriority[src]==pri) & intPending[src] & intEn[ctx][src];
|
assign irqMatrix[ctx][pri][src] = (intPriority[src]==pri) & intPending[src] & intEn[ctx][src];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -210,14 +216,14 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
// of the sources at the highest priority level that has active requests,
|
// of the sources at the highest priority level that has active requests,
|
||||||
// which sources have active requests?
|
// which sources have active requests?
|
||||||
assign irqs_at_max_priority[ctx][`N:1] =
|
assign irqs_at_max_priority[ctx][P.PLIC_NUM_SRC:1] =
|
||||||
({`N{max_priority_with_irqs[ctx][7]}} & irqMatrix[ctx][7]) |
|
({P.PLIC_NUM_SRC{max_priority_with_irqs[ctx][7]}} & irqMatrix[ctx][7]) |
|
||||||
({`N{max_priority_with_irqs[ctx][6]}} & irqMatrix[ctx][6]) |
|
({P.PLIC_NUM_SRC{max_priority_with_irqs[ctx][6]}} & irqMatrix[ctx][6]) |
|
||||||
({`N{max_priority_with_irqs[ctx][5]}} & irqMatrix[ctx][5]) |
|
({P.PLIC_NUM_SRC{max_priority_with_irqs[ctx][5]}} & irqMatrix[ctx][5]) |
|
||||||
({`N{max_priority_with_irqs[ctx][4]}} & irqMatrix[ctx][4]) |
|
({P.PLIC_NUM_SRC{max_priority_with_irqs[ctx][4]}} & irqMatrix[ctx][4]) |
|
||||||
({`N{max_priority_with_irqs[ctx][3]}} & irqMatrix[ctx][3]) |
|
({P.PLIC_NUM_SRC{max_priority_with_irqs[ctx][3]}} & irqMatrix[ctx][3]) |
|
||||||
({`N{max_priority_with_irqs[ctx][2]}} & irqMatrix[ctx][2]) |
|
({P.PLIC_NUM_SRC{max_priority_with_irqs[ctx][2]}} & irqMatrix[ctx][2]) |
|
||||||
({`N{max_priority_with_irqs[ctx][1]}} & irqMatrix[ctx][1]);
|
({P.PLIC_NUM_SRC{max_priority_with_irqs[ctx][1]}} & irqMatrix[ctx][1]);
|
||||||
|
|
||||||
// of the sources at the highest priority level that has active requests,
|
// of the sources at the highest priority level that has active requests,
|
||||||
// choose the source with the lowest source ID to be the most urgent
|
// choose the source with the lowest source ID to be the most urgent
|
||||||
@ -225,7 +231,7 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
integer k;
|
integer k;
|
||||||
always_comb begin
|
always_comb begin
|
||||||
intClaim[ctx] = 6'b0;
|
intClaim[ctx] = 6'b0;
|
||||||
for (k=`N; k>0; k--) begin
|
for (k=P.PLIC_NUM_SRC; k>0; k--) begin
|
||||||
if (irqs_at_max_priority[ctx][k]) intClaim[ctx] = k[5:0];
|
if (irqs_at_max_priority[ctx][k]) intClaim[ctx] = k[5:0];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user