mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Removed generate statements
This commit is contained in:
parent
98be8201b2
commit
d66f7c841b
@ -3,11 +3,14 @@ make all:
|
|||||||
make -C ../../addins/riscv-arch-test
|
make -C ../../addins/riscv-arch-test
|
||||||
make -C ../../addins/riscv-arch-test XLEN=32
|
make -C ../../addins/riscv-arch-test XLEN=32
|
||||||
exe2memfile.pl ../../addins/riscv-arch-test/work/*/*/*.elf
|
exe2memfile.pl ../../addins/riscv-arch-test/work/*/*/*.elf
|
||||||
|
# extractFunctionRadix. ***
|
||||||
|
|
||||||
# Build wally-riscv-arch-test
|
# Build wally-riscv-arch-test
|
||||||
make -C ../../tests/wally-riscv-arch-test/
|
make -C ../../tests/wally-riscv-arch-test/
|
||||||
make -C ../../tests/wally-riscv-arch-test/ XLEN=32
|
make -C ../../tests/wally-riscv-arch-test/ XLEN=32
|
||||||
exe2memfile.pl ../../tests/wally-riscv-arch-test/work/*/*/*.elf
|
exe2memfile.pl ../../tests/wally-riscv-arch-test/work/*/*/*.elf
|
||||||
|
# ***extractFunctionRadix
|
||||||
|
# *** use elf2hex
|
||||||
|
|
||||||
# *** add optional imperas tests
|
# *** add optional imperas tests
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
vsim -c <<!
|
vsim -c <<!
|
||||||
do wally-pipelined-batch.do rv64gc imperas64i
|
do wally-pipelined-batch.do rv32gc wally32priv
|
||||||
!
|
!
|
||||||
|
@ -174,3 +174,22 @@ module divconv_pipe (q1, qm1, qp1, q0, qm0, qp0, rega_out, regb_out, regc_out, r
|
|||||||
flopenr #(60) regk (clk, reset, regs_pipe2, {qp_out0[59:35], (qp_out0[34:6] & {29{~P_pipe}}), 6'h0}, qp0);
|
flopenr #(60) regk (clk, reset, regs_pipe2, {qp_out0[59:35], (qp_out0[34:6] & {29{~P_pipe}}), 6'h0}, qp0);
|
||||||
|
|
||||||
endmodule // divconv
|
endmodule // divconv
|
||||||
|
|
||||||
|
// *** rewrote behaviorally dh 5 Jan 2021 for speed
|
||||||
|
module csa #(parameter WIDTH=8) (
|
||||||
|
input logic [WIDTH-1:0] a, b, c,
|
||||||
|
output logic [WIDTH-1:0] sum, carry);
|
||||||
|
|
||||||
|
assign sum = a ^ b ^ c;
|
||||||
|
assign carry = (a & (b | c)) | (b & c);
|
||||||
|
/*
|
||||||
|
logic [WIDTH:0] carry_temp;
|
||||||
|
genvar i;
|
||||||
|
generate
|
||||||
|
for (i=0;i<WIDTH;i=i+1) begin : genbit
|
||||||
|
fa fa_inst (a[i], b[i], c[i], sum[i], carry_temp[i+1]);
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
assign carry = {carry_temp[WIDTH-1:1], 1'b0};
|
||||||
|
*/
|
||||||
|
endmodule // csa
|
||||||
|
@ -37,22 +37,17 @@ module redundantmul #(parameter WIDTH =8)(
|
|||||||
input logic [WIDTH-1:0] a,b,
|
input logic [WIDTH-1:0] a,b,
|
||||||
output logic [2*WIDTH-1:0] out0, out1);
|
output logic [2*WIDTH-1:0] out0, out1);
|
||||||
|
|
||||||
//
|
if (`DESIGN_COMPILER == 1) begin:mul
|
||||||
|
logic [2*WIDTH-1+2:0] tmp_out0;
|
||||||
generate
|
logic [2*WIDTH-1+2:0] tmp_out1;
|
||||||
if (`DESIGN_COMPILER == 1) begin:mul
|
|
||||||
logic [2*WIDTH-1+2:0] tmp_out0;
|
|
||||||
logic [2*WIDTH-1+2:0] tmp_out1;
|
|
||||||
|
|
||||||
DW02_multp #(WIDTH, WIDTH, 2*WIDTH+2) mul(.a, .b, .tc(1'b0), .out0(tmp_out0), .out1(tmp_out1));
|
|
||||||
assign out0 = tmp_out0[2*WIDTH-1:0];
|
|
||||||
assign out1 = tmp_out1[2*WIDTH-1:0];
|
|
||||||
end else begin:mul // force a nonredunant multipler. This will simulate properly and also is appropriate for FPGAs.
|
|
||||||
assign out0 = a * b;
|
|
||||||
assign out1 = 0;
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
|
DW02_multp #(WIDTH, WIDTH, 2*WIDTH+2) mul(.a, .b, .tc(1'b0), .out0(tmp_out0), .out1(tmp_out1));
|
||||||
|
assign out0 = tmp_out0[2*WIDTH-1:0];
|
||||||
|
assign out1 = tmp_out1[2*WIDTH-1:0];
|
||||||
|
end else begin:mul // force a nonredunant multipler. This will simulate properly and also is appropriate for FPGAs.
|
||||||
|
assign out0 = a * b;
|
||||||
|
assign out1 = 0;
|
||||||
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
@ -1,195 +0,0 @@
|
|||||||
///////////////////////////////////////////
|
|
||||||
// lzd.sv
|
|
||||||
//
|
|
||||||
// Written: James.Stine@okstate.edu 1 February 2021
|
|
||||||
// Modified:
|
|
||||||
//
|
|
||||||
// Purpose: Integer Divide instructions
|
|
||||||
//
|
|
||||||
// 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"
|
|
||||||
/* verilator lint_off DECLFILENAME */
|
|
||||||
|
|
||||||
// Original idea came from V. G. Oklobdzija, "An algorithmic and novel
|
|
||||||
// design of a leading zero detector circuit: comparison with logic
|
|
||||||
// synthesis," in IEEE Transactions on Very Large Scale Integration
|
|
||||||
// (VLSI) Systems, vol. 2, no. 1, pp. 124-128, March 1994, doi:
|
|
||||||
// 10.1109/92.273153.
|
|
||||||
|
|
||||||
// Modified to be more hierarchical
|
|
||||||
|
|
||||||
module lzd2 (P, V, B);
|
|
||||||
|
|
||||||
input logic [1:0] B;
|
|
||||||
|
|
||||||
output logic P;
|
|
||||||
output logic V;
|
|
||||||
|
|
||||||
assign V = B[0] | B[1];
|
|
||||||
assign P = B[0] & ~B[1];
|
|
||||||
|
|
||||||
endmodule // lzd2
|
|
||||||
|
|
||||||
module lzd_hier #(parameter WIDTH=8)
|
|
||||||
(input logic [WIDTH-1:0] B,
|
|
||||||
output logic [$clog2(WIDTH)-1:0] ZP,
|
|
||||||
output logic ZV);
|
|
||||||
|
|
||||||
if (WIDTH == 128)
|
|
||||||
lzd128 lz127 (ZP, ZV, B);
|
|
||||||
else if (WIDTH == 64)
|
|
||||||
lzd64 lz64 (ZP, ZV, B);
|
|
||||||
else if (WIDTH == 32)
|
|
||||||
lzd32 lz32 (ZP, ZV, B);
|
|
||||||
else if (WIDTH == 16)
|
|
||||||
lzd16 lz16 (ZP, ZV, B);
|
|
||||||
else if (WIDTH == 8)
|
|
||||||
lzd8 lz8 (ZP, ZV, B);
|
|
||||||
else if (WIDTH == 4)
|
|
||||||
lzd4 lz4 (ZP, ZV, B);
|
|
||||||
|
|
||||||
endmodule // lzd_hier
|
|
||||||
|
|
||||||
module lzd4 (ZP, ZV, B);
|
|
||||||
|
|
||||||
input logic [3:0] B;
|
|
||||||
|
|
||||||
logic ZPa;
|
|
||||||
logic ZPb;
|
|
||||||
logic ZVa;
|
|
||||||
logic ZVb;
|
|
||||||
|
|
||||||
output logic [1:0] ZP;
|
|
||||||
output logic ZV;
|
|
||||||
|
|
||||||
lzd2 l1(ZPa, ZVa, B[1:0]);
|
|
||||||
lzd2 l2(ZPb, ZVb, B[3:2]);
|
|
||||||
|
|
||||||
assign ZP[0] = ZVb ? ZPb : ZPa;
|
|
||||||
assign ZP[1] = ~ZVb;
|
|
||||||
assign ZV = ZVa | ZVb;
|
|
||||||
|
|
||||||
endmodule // lzd4
|
|
||||||
|
|
||||||
module lzd8 (ZP, ZV, B);
|
|
||||||
|
|
||||||
input logic [7:0] B;
|
|
||||||
|
|
||||||
logic [1:0] ZPa;
|
|
||||||
logic [1:0] ZPb;
|
|
||||||
logic ZVa;
|
|
||||||
logic ZVb;
|
|
||||||
|
|
||||||
output logic [2:0] ZP;
|
|
||||||
output logic ZV;
|
|
||||||
|
|
||||||
lzd4 l1(ZPa, ZVa, B[3:0]);
|
|
||||||
lzd4 l2(ZPb, ZVb, B[7:4]);
|
|
||||||
|
|
||||||
assign ZP[1:0] = ZVb ? ZPb : ZPa;
|
|
||||||
assign ZP[2] = ~ZVb;
|
|
||||||
assign ZV = ZVa | ZVb;
|
|
||||||
|
|
||||||
endmodule // lzd8
|
|
||||||
|
|
||||||
module lzd16 (ZP, ZV, B);
|
|
||||||
|
|
||||||
input logic [15:0] B;
|
|
||||||
|
|
||||||
logic [2:0] ZPa;
|
|
||||||
logic [2:0] ZPb;
|
|
||||||
logic ZVa;
|
|
||||||
logic ZVb;
|
|
||||||
|
|
||||||
output logic [3:0] ZP;
|
|
||||||
output logic ZV;
|
|
||||||
|
|
||||||
lzd8 l1(ZPa, ZVa, B[7:0]);
|
|
||||||
lzd8 l2(ZPb, ZVb, B[15:8]);
|
|
||||||
|
|
||||||
assign ZP[2:0] = ZVb ? ZPb : ZPa;
|
|
||||||
assign ZP[3] = ~ZVb;
|
|
||||||
assign ZV = ZVa | ZVb;
|
|
||||||
|
|
||||||
endmodule // lzd16
|
|
||||||
|
|
||||||
module lzd32 (ZP, ZV, B);
|
|
||||||
|
|
||||||
input logic [31:0] B;
|
|
||||||
|
|
||||||
logic [3:0] ZPa;
|
|
||||||
logic [3:0] ZPb;
|
|
||||||
logic ZVa;
|
|
||||||
logic ZVb;
|
|
||||||
|
|
||||||
output logic [4:0] ZP;
|
|
||||||
output logic ZV;
|
|
||||||
|
|
||||||
lzd16 l1(ZPa, ZVa, B[15:0]);
|
|
||||||
lzd16 l2(ZPb, ZVb, B[31:16]);
|
|
||||||
|
|
||||||
assign ZP[3:0] = ZVb ? ZPb : ZPa;
|
|
||||||
assign ZP[4] = ~ZVb;
|
|
||||||
assign ZV = ZVa | ZVb;
|
|
||||||
|
|
||||||
endmodule // lzd32
|
|
||||||
|
|
||||||
module lzd64 (ZP, ZV, B);
|
|
||||||
|
|
||||||
input logic [63:0] B;
|
|
||||||
|
|
||||||
logic [4:0] ZPa;
|
|
||||||
logic [4:0] ZPb;
|
|
||||||
logic ZVa;
|
|
||||||
logic ZVb;
|
|
||||||
|
|
||||||
output logic [5:0] ZP;
|
|
||||||
output logic ZV;
|
|
||||||
|
|
||||||
lzd32 l1(ZPa, ZVa, B[31:0]);
|
|
||||||
lzd32 l2(ZPb, ZVb, B[63:32]);
|
|
||||||
|
|
||||||
assign ZP[4:0] = ZVb ? ZPb : ZPa;
|
|
||||||
assign ZP[5] = ~ZVb;
|
|
||||||
assign ZV = ZVa | ZVb;
|
|
||||||
|
|
||||||
endmodule // lzd64
|
|
||||||
|
|
||||||
module lzd128 (ZP, ZV, B);
|
|
||||||
|
|
||||||
input logic [127:0] B;
|
|
||||||
|
|
||||||
logic [5:0] ZPa;
|
|
||||||
logic [5:0] ZPb;
|
|
||||||
logic ZVa;
|
|
||||||
logic ZVb;
|
|
||||||
|
|
||||||
output logic [6:0] ZP;
|
|
||||||
output logic ZV;
|
|
||||||
|
|
||||||
lzd64 l1(ZPa, ZVa, B[64:0]);
|
|
||||||
lzd64 l2(ZPb, ZVb, B[127:63]);
|
|
||||||
|
|
||||||
assign ZP[5:0] = ZVb ? ZPb : ZPa;
|
|
||||||
assign ZP[6] = ~ZVb;
|
|
||||||
assign ZV = ZVa | ZVb;
|
|
||||||
|
|
||||||
endmodule // lzd128
|
|
||||||
|
|
||||||
/* verilator lint_on DECLFILENAME */
|
|
@ -33,18 +33,16 @@ module or_rows #(parameter ROWS = 8, COLS=2) (
|
|||||||
input var logic [COLS-1:0] a[ROWS-1:0],
|
input var logic [COLS-1:0] a[ROWS-1:0],
|
||||||
output logic [COLS-1:0] y);
|
output logic [COLS-1:0] y);
|
||||||
|
|
||||||
logic [COLS-1:0] mid[ROWS-1:1];
|
genvar row;
|
||||||
genvar row, col;
|
if(ROWS == 1)
|
||||||
generate
|
assign y = a[0];
|
||||||
if(ROWS == 1)
|
else begin
|
||||||
assign y = a[0];
|
logic [COLS-1:0] mid[ROWS-1:1];
|
||||||
else begin
|
assign mid[1] = a[0] | a[1];
|
||||||
assign mid[1] = a[0] | a[1];
|
for (row=2; row < ROWS; row++)
|
||||||
for (row=2; row < ROWS; row++)
|
assign mid[row] = mid[row-1] | a[row];
|
||||||
assign mid[row] = mid[row-1] | a[row];
|
assign y = mid[ROWS-1];
|
||||||
assign y = mid[ROWS-1];
|
end
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
/* verilator lint_on UNOPTFLAT */
|
/* verilator lint_on UNOPTFLAT */
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
///////////////////////////////////////////
|
|
||||||
// shifters.sv
|
|
||||||
//
|
|
||||||
// Written: James.Stine@okstate.edu 1 February 2021
|
|
||||||
// Modified:
|
|
||||||
//
|
|
||||||
// Purpose: Integer Divide instructions
|
|
||||||
//
|
|
||||||
// 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"
|
|
||||||
/* verilator lint_off DECLFILENAME */
|
|
||||||
/* verilator lint_off UNOPTFLAT */
|
|
||||||
|
|
||||||
module shift_right #(parameter WIDTH=8)
|
|
||||||
(input logic [WIDTH-1:0] A,
|
|
||||||
input logic [$clog2(WIDTH)-1:0] Shift,
|
|
||||||
output logic [WIDTH-1:0] Z);
|
|
||||||
|
|
||||||
logic [WIDTH-1:0] stage [$clog2(WIDTH):0];
|
|
||||||
logic sign;
|
|
||||||
genvar i;
|
|
||||||
|
|
||||||
assign stage[0] = A;
|
|
||||||
generate
|
|
||||||
for (i=0;i<$clog2(WIDTH);i=i+1) begin : genbit
|
|
||||||
mux2 #(WIDTH) mux_inst (stage[i],
|
|
||||||
{{(WIDTH/(2**(i+1))){1'b0}}, stage[i][WIDTH-1:WIDTH/(2**(i+1))]},
|
|
||||||
Shift[$clog2(WIDTH)-i-1],
|
|
||||||
stage[i+1]);
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
assign Z = stage[$clog2(WIDTH)];
|
|
||||||
|
|
||||||
endmodule // shift_right
|
|
||||||
|
|
||||||
module shift_left #(parameter WIDTH=8)
|
|
||||||
(input logic [WIDTH-1:0] A,
|
|
||||||
input logic [$clog2(WIDTH)-1:0] Shift,
|
|
||||||
output logic [WIDTH-1:0] Z);
|
|
||||||
|
|
||||||
logic [WIDTH-1:0] stage [$clog2(WIDTH):0];
|
|
||||||
genvar i;
|
|
||||||
|
|
||||||
assign stage[0] = A;
|
|
||||||
generate
|
|
||||||
for (i=0;i<$clog2(WIDTH);i=i+1) begin : genbit
|
|
||||||
mux2 #(WIDTH) mux_inst (stage[i],
|
|
||||||
{stage[i][WIDTH-1-WIDTH/(2**(i+1)):0], {(WIDTH/(2**(i+1))){1'b0}}},
|
|
||||||
Shift[$clog2(WIDTH)-i-1],
|
|
||||||
stage[i+1]);
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
assign Z = stage[$clog2(WIDTH)];
|
|
||||||
|
|
||||||
endmodule // shift_left
|
|
||||||
|
|
||||||
/* verilator lint_on DECLFILENAME */
|
|
||||||
/* verilator lint_on UNOPTFLAT */
|
|
@ -78,9 +78,7 @@ module alu #(parameter WIDTH=32) (
|
|||||||
endcase
|
endcase
|
||||||
|
|
||||||
// support W-type RV64I ADDW/SUBW/ADDIW/Shifts that sign-extend 32-bit result to 64 bits
|
// support W-type RV64I ADDW/SUBW/ADDIW/Shifts that sign-extend 32-bit result to 64 bits
|
||||||
generate
|
if (WIDTH==64) assign Result = W64 ? {{32{FullResult[31]}}, FullResult[31:0]} : FullResult;
|
||||||
if (WIDTH==64) assign Result = W64 ? {{32{FullResult[31]}}, FullResult[31:0]} : FullResult;
|
else assign Result = FullResult;
|
||||||
else assign Result = FullResult;
|
|
||||||
endgenerate
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -109,55 +109,53 @@ module controller(
|
|||||||
assign Rs1D = InstrD[19:15];
|
assign Rs1D = InstrD[19:15];
|
||||||
|
|
||||||
// Main Instruction Decoder
|
// Main Instruction Decoder
|
||||||
generate
|
always_comb
|
||||||
always_comb
|
case(OpD)
|
||||||
case(OpD)
|
// RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_ALUResultSrc_W64_CSRRead_Privileged_Fence_MulDiv_Atomic_Illegal
|
||||||
// RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_ALUResultSrc_W64_CSRRead_Privileged_Fence_MulDiv_Atomic_Illegal
|
7'b0000000: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // illegal instruction
|
||||||
7'b0000000: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // illegal instruction
|
7'b0000011: ControlsD = `CTRLW'b1_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // lw
|
||||||
7'b0000011: ControlsD = `CTRLW'b1_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // lw
|
7'b0000111: ControlsD = `CTRLW'b0_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // flw
|
||||||
7'b0000111: ControlsD = `CTRLW'b0_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // flw
|
7'b0001111: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_1_0_00_0; // fence
|
||||||
7'b0001111: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_1_0_00_0; // fence
|
7'b0010011: ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_0_0_0_0_0_00_0; // I-type ALU
|
||||||
7'b0010011: ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_0_0_0_0_0_00_0; // I-type ALU
|
7'b0010111: ControlsD = `CTRLW'b1_100_11_00_000_0_0_0_0_0_0_0_0_0_00_0; // auipc
|
||||||
7'b0010111: ControlsD = `CTRLW'b1_100_11_00_000_0_0_0_0_0_0_0_0_0_00_0; // auipc
|
7'b0011011: if (`XLEN == 64)
|
||||||
7'b0011011: if (`XLEN == 64)
|
ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_1_0_0_0_0_00_0; // IW-type ALU for RV64i
|
||||||
ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_1_0_0_0_0_00_0; // IW-type ALU for RV64i
|
else
|
||||||
|
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
|
||||||
|
7'b0100011: ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // sw
|
||||||
|
7'b0100111: ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // fsw
|
||||||
|
7'b0101111: if (`A_SUPPORTED) begin
|
||||||
|
if (InstrD[31:27] == 5'b00010)
|
||||||
|
ControlsD = `CTRLW'b1_000_00_10_001_0_0_0_0_0_0_0_0_0_01_0; // lr
|
||||||
|
else if (InstrD[31:27] == 5'b00011)
|
||||||
|
ControlsD = `CTRLW'b1_101_01_01_100_0_0_0_0_0_0_0_0_0_01_0; // sc
|
||||||
else
|
else
|
||||||
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
|
ControlsD = `CTRLW'b1_101_01_11_001_0_0_0_0_0_0_0_0_0_10_0;; // amo
|
||||||
7'b0100011: ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // sw
|
end else
|
||||||
7'b0100111: ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // fsw
|
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
|
||||||
7'b0101111: if (`A_SUPPORTED) begin
|
7'b0110011: if (Funct7D == 7'b0000000 | Funct7D == 7'b0100000)
|
||||||
if (InstrD[31:27] == 5'b00010)
|
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_0_0_0_0_0_00_0; // R-type
|
||||||
ControlsD = `CTRLW'b1_000_00_10_001_0_0_0_0_0_0_0_0_0_01_0; // lr
|
else if (Funct7D == 7'b0000001 & `M_SUPPORTED)
|
||||||
else if (InstrD[31:27] == 5'b00011)
|
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0; // Multiply/Divide
|
||||||
ControlsD = `CTRLW'b1_101_01_01_100_0_0_0_0_0_0_0_0_0_01_0; // sc
|
else
|
||||||
else
|
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
|
||||||
ControlsD = `CTRLW'b1_101_01_11_001_0_0_0_0_0_0_0_0_0_10_0;; // amo
|
7'b0110111: ControlsD = `CTRLW'b1_100_01_00_000_0_0_0_1_0_0_0_0_0_00_0; // lui
|
||||||
end else
|
7'b0111011: if ((Funct7D == 7'b0000000 | Funct7D == 7'b0100000) & `XLEN == 64)
|
||||||
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
|
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0; // R-type W instructions for RV64i
|
||||||
7'b0110011: if (Funct7D == 7'b0000000 | Funct7D == 7'b0100000)
|
else if (Funct7D == 7'b0000001 & `M_SUPPORTED & `XLEN == 64)
|
||||||
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_0_0_0_0_0_00_0; // R-type
|
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_1_0_0_0_1_00_0; // W-type Multiply/Divide
|
||||||
else if (Funct7D == 7'b0000001 & `M_SUPPORTED)
|
else
|
||||||
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0; // Multiply/Divide
|
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
|
||||||
else
|
//7'b1010011: ControlsD = `CTRLW'b0_000_00_00_101_0_00_0_0_0_0_0_0_0_00_1; // FP
|
||||||
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
|
7'b1100011: ControlsD = `CTRLW'b0_010_11_00_000_1_0_0_0_0_0_0_0_0_00_0; // branches
|
||||||
7'b0110111: ControlsD = `CTRLW'b1_100_01_00_000_0_0_0_1_0_0_0_0_0_00_0; // lui
|
7'b1100111: ControlsD = `CTRLW'b1_000_01_00_000_0_0_1_1_0_0_0_0_0_00_0; // jalr
|
||||||
7'b0111011: if ((Funct7D == 7'b0000000 | Funct7D == 7'b0100000) & `XLEN == 64)
|
7'b1101111: ControlsD = `CTRLW'b1_011_11_00_000_0_0_1_1_0_0_0_0_0_00_0; // jal
|
||||||
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0; // R-type W instructions for RV64i
|
7'b1110011: if (Funct3D == 3'b000)
|
||||||
else if (Funct7D == 7'b0000001 & `M_SUPPORTED & `XLEN == 64)
|
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_1_0_0_00_0; // privileged; decoded further in priveleged modules
|
||||||
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_1_0_0_0_1_00_0; // W-type Multiply/Divide
|
else
|
||||||
else
|
ControlsD = `CTRLW'b1_000_00_00_010_0_0_0_0_0_1_0_0_0_00_0; // csrs
|
||||||
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
|
default: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
|
||||||
//7'b1010011: ControlsD = `CTRLW'b0_000_00_00_101_0_00_0_0_0_0_0_0_0_00_1; // FP
|
endcase
|
||||||
7'b1100011: ControlsD = `CTRLW'b0_010_11_00_000_1_0_0_0_0_0_0_0_0_00_0; // branches
|
|
||||||
7'b1100111: ControlsD = `CTRLW'b1_000_01_00_000_0_0_1_1_0_0_0_0_0_00_0; // jalr
|
|
||||||
7'b1101111: ControlsD = `CTRLW'b1_011_11_00_000_0_0_1_1_0_0_0_0_0_00_0; // jal
|
|
||||||
7'b1110011: if (Funct3D == 3'b000)
|
|
||||||
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_1_0_0_00_0; // privileged; decoded further in priveleged modules
|
|
||||||
else
|
|
||||||
ControlsD = `CTRLW'b1_000_00_00_010_0_0_0_0_0_1_0_0_0_00_0; // csrs
|
|
||||||
default: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
|
|
||||||
endcase
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
// unswizzle control bits
|
// unswizzle control bits
|
||||||
// squash control signals if coming from an illegal compressed instruction
|
// squash control signals if coming from an illegal compressed instruction
|
||||||
@ -181,17 +179,15 @@ module controller(
|
|||||||
// Fences
|
// Fences
|
||||||
// Ordinary fence is presently a nop
|
// Ordinary fence is presently a nop
|
||||||
// FENCE.I flushes the D$ and invalidates the I$ if Zifencei is supported and I$ is implemented
|
// FENCE.I flushes the D$ and invalidates the I$ if Zifencei is supported and I$ is implemented
|
||||||
generate
|
if (`ZIFENCEI_SUPPORTED & `MEM_ICACHE) begin:fencei
|
||||||
if (`ZIFENCEI_SUPPORTED & `MEM_ICACHE) begin:fencei
|
logic FenceID;
|
||||||
logic FenceID;
|
assign FenceID = FenceD & (Funct3D == 3'b001); // is it a FENCE.I instruction?
|
||||||
assign FenceID = FenceD & (Funct3D == 3'b001); // is it a FENCE.I instruction?
|
assign InvalidateICacheD = FenceID;
|
||||||
assign InvalidateICacheD = FenceID;
|
assign FlushDCacheD = FenceID;
|
||||||
assign FlushDCacheD = FenceID;
|
end else begin:fencei
|
||||||
end else begin:fencei
|
assign InvalidateICacheD = 0;
|
||||||
assign InvalidateICacheD = 0;
|
assign FlushDCacheD = 0;
|
||||||
assign FlushDCacheD = 0;
|
end
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
// Decocde stage pipeline control register
|
// Decocde stage pipeline control register
|
||||||
flopenrc #(1) controlregD(clk, reset, FlushD, ~StallD, 1'b1, InstrValidD);
|
flopenrc #(1) controlregD(clk, reset, FlushD, ~StallD, 1'b1, InstrValidD);
|
||||||
|
@ -124,19 +124,15 @@ module datapath (
|
|||||||
mux5 #(`XLEN) resultmuxW(ResultW, ReadDataW, CSRReadValW, MulDivResultW, SCResultW, ResultSrcW, WriteDataW);
|
mux5 #(`XLEN) resultmuxW(ResultW, ReadDataW, CSRReadValW, MulDivResultW, SCResultW, ResultSrcW, WriteDataW);
|
||||||
|
|
||||||
// floating point interactions: fcvt, fp stores
|
// floating point interactions: fcvt, fp stores
|
||||||
generate
|
if (`F_SUPPORTED) begin:fpmux
|
||||||
if (`F_SUPPORTED) begin:fpmux
|
mux2 #(`XLEN) resultmuxM(IEUResultM, FIntResM, FWriteIntM, ResultM);
|
||||||
mux2 #(`XLEN) resultmuxM(IEUResultM, FIntResM, FWriteIntM, ResultM);
|
mux2 #(`XLEN) writedatamux(ForwardedSrcBE, FWriteDataE, ~IllegalFPUInstrE, WriteDataE);
|
||||||
mux2 #(`XLEN) writedatamux(ForwardedSrcBE, FWriteDataE, ~IllegalFPUInstrE, WriteDataE);
|
end else begin:fpmux
|
||||||
end else begin:fpmux
|
assign ResultM = IEUResultM;
|
||||||
assign ResultM = IEUResultM;
|
assign WriteDataE = ForwardedSrcBE;
|
||||||
assign WriteDataE = ForwardedSrcBE;
|
end
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
// handle Store Conditional result if atomic extension supported
|
// handle Store Conditional result if atomic extension supported
|
||||||
generate
|
if (`A_SUPPORTED) assign SCResultW = {{(`XLEN-1){1'b0}}, SquashSCW};
|
||||||
if (`A_SUPPORTED) assign SCResultW = {{(`XLEN-1){1'b0}}, SquashSCW};
|
else assign SCResultW = 0;
|
||||||
else assign SCResultW = 0;
|
|
||||||
endgenerate
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -32,23 +32,24 @@ module extend (
|
|||||||
|
|
||||||
localparam [`XLEN-1:0] undefined = {(`XLEN){1'bx}}; // could change to 0 after debug
|
localparam [`XLEN-1:0] undefined = {(`XLEN){1'bx}}; // could change to 0 after debug
|
||||||
|
|
||||||
// generate
|
always_comb
|
||||||
always_comb
|
case(ImmSrcD)
|
||||||
case(ImmSrcD)
|
// I-type
|
||||||
// I-type
|
3'b000: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[31:20]};
|
||||||
3'b000: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[31:20]};
|
// S-type (stores)
|
||||||
// S-type (stores)
|
3'b001: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[31:25], InstrD[11:7]};
|
||||||
3'b001: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[31:25], InstrD[11:7]};
|
// B-type (branches)
|
||||||
// B-type (branches)
|
3'b010: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[7], InstrD[30:25], InstrD[11:8], 1'b0};
|
||||||
3'b010: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[7], InstrD[30:25], InstrD[11:8], 1'b0};
|
// J-type (jal)
|
||||||
// J-type (jal)
|
3'b011: ExtImmD = {{(`XLEN-20){InstrD[31]}}, InstrD[19:12], InstrD[20], InstrD[30:21], 1'b0};
|
||||||
3'b011: ExtImmD = {{(`XLEN-20){InstrD[31]}}, InstrD[19:12], InstrD[20], InstrD[30:21], 1'b0};
|
// U-type (lui, auipc)
|
||||||
// U-type (lui, auipc)
|
3'b100: ExtImmD = {{(`XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0};
|
||||||
3'b100: ExtImmD = {{(`XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0};
|
// Store Conditional: zero offset
|
||||||
// Store Conditional: zero offset
|
3'b101: if (`A_SUPPORTED) ExtImmD = 0;
|
||||||
3'b101: if (`A_SUPPORTED) ExtImmD = 0;
|
else ExtImmD = undefined;
|
||||||
else ExtImmD = undefined;
|
default: begin
|
||||||
default: ExtImmD = undefined; // undefined
|
ExtImmD = undefined; // undefined
|
||||||
endcase
|
$error("Invalid ImmSrcD in extend");
|
||||||
// endgenerate
|
end
|
||||||
|
endcase
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -39,7 +39,7 @@ module shifter (
|
|||||||
// For RV64, 32 and 64-bit shifts are needed, with sign extension.
|
// For RV64, 32 and 64-bit shifts are needed, with sign extension.
|
||||||
|
|
||||||
// funnel shifter input (see CMOS VLSI Design 4e Section 11.8.1, note Table 11.11 shift types wrong)
|
// funnel shifter input (see CMOS VLSI Design 4e Section 11.8.1, note Table 11.11 shift types wrong)
|
||||||
generate
|
// generate
|
||||||
if (`XLEN==32) begin:shifter // RV32
|
if (`XLEN==32) begin:shifter // RV32
|
||||||
always_comb // funnel mux
|
always_comb // funnel mux
|
||||||
if (Right)
|
if (Right)
|
||||||
@ -62,7 +62,7 @@ module shifter (
|
|||||||
end
|
end
|
||||||
assign amttrunc = W64 ? {1'b0, Amt[4:0]} : Amt; // 32 or 64-bit shift
|
assign amttrunc = W64 ? {1'b0, Amt[4:0]} : Amt; // 32 or 64-bit shift
|
||||||
end
|
end
|
||||||
endgenerate
|
// endgenerate
|
||||||
|
|
||||||
// opposite offset for right shfits
|
// opposite offset for right shfits
|
||||||
assign offset = Right ? amttrunc : ~amttrunc;
|
assign offset = Right ? amttrunc : ~amttrunc;
|
||||||
|
@ -93,18 +93,15 @@ module SRAM2P1R1W
|
|||||||
// read port
|
// read port
|
||||||
assign RD1 = mem[RA1Q];
|
assign RD1 = mem[RA1Q];
|
||||||
|
|
||||||
genvar index;
|
|
||||||
|
|
||||||
// write port
|
// write port
|
||||||
generate
|
genvar index;
|
||||||
for (index = 0; index < WIDTH; index = index + 1) begin:bitwrite
|
for (index = 0; index < WIDTH; index = index + 1) begin:bitwrite
|
||||||
always_ff @ (posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (WEN1Q & BitWEN1[index]) begin
|
if (WEN1Q & BitWEN1[index]) begin
|
||||||
mem[WA1Q][index] <= WD1Q[index];
|
mem[WA1Q][index] <= WD1Q[index];
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endgenerate
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -38,36 +38,35 @@ module decompress (
|
|||||||
logic [1:0] op;
|
logic [1:0] op;
|
||||||
|
|
||||||
// if the system handles compressed instructions, decode appropriately
|
// if the system handles compressed instructions, decode appropriately
|
||||||
generate
|
if (!(`C_SUPPORTED)) begin:decompress // no compressed mode
|
||||||
if (!(`C_SUPPORTED)) begin:decompress // no compressed mode
|
assign InstrD = InstrRawD;
|
||||||
assign InstrD = InstrRawD;
|
assign IllegalCompInstrD = 0;
|
||||||
assign IllegalCompInstrD = 0;
|
end else begin : decompress // COMPRESSED mode supported
|
||||||
end else begin : decompress // COMPRESSED mode supported
|
assign instr16 = InstrRawD[15:0]; // instruction is alreay aligned
|
||||||
assign instr16 = InstrRawD[15:0]; // instruction is alreay aligned
|
assign op = instr16[1:0];
|
||||||
assign op = instr16[1:0];
|
assign rds1 = instr16[11:7];
|
||||||
assign rds1 = instr16[11:7];
|
assign rs2 = instr16[6:2];
|
||||||
assign rs2 = instr16[6:2];
|
assign rs1p = {2'b01, instr16[9:7]};
|
||||||
assign rs1p = {2'b01, instr16[9:7]};
|
assign rds1p = {2'b01, instr16[9:7]};
|
||||||
assign rds1p = {2'b01, instr16[9:7]};
|
assign rs2p = {2'b01, instr16[4:2]};
|
||||||
assign rs2p = {2'b01, instr16[4:2]};
|
assign rdp = {2'b01, instr16[4:2]};
|
||||||
assign rdp = {2'b01, instr16[4:2]};
|
|
||||||
|
|
||||||
// many compressed immediate formats
|
// many compressed immediate formats
|
||||||
assign immCILSP = {4'b0000, instr16[3:2], instr16[12], instr16[6:4], 2'b00};
|
assign immCILSP = {4'b0000, instr16[3:2], instr16[12], instr16[6:4], 2'b00};
|
||||||
assign immCILSPD = {3'b000, instr16[4:2], instr16[12], instr16[6:5], 3'b000};
|
assign immCILSPD = {3'b000, instr16[4:2], instr16[12], instr16[6:5], 3'b000};
|
||||||
assign immCSS = {4'b0000, instr16[8:7], instr16[12:9], 2'b00};
|
assign immCSS = {4'b0000, instr16[8:7], instr16[12:9], 2'b00};
|
||||||
assign immCSSD = {3'b000, instr16[9:7], instr16[12:10], 3'b000};
|
assign immCSSD = {3'b000, instr16[9:7], instr16[12:10], 3'b000};
|
||||||
assign immCL = {5'b0, instr16[5], instr16[12:10], instr16[6], 2'b00};
|
assign immCL = {5'b0, instr16[5], instr16[12:10], instr16[6], 2'b00};
|
||||||
assign immCLD = {4'b0, instr16[6:5], instr16[12:10], 3'b000};
|
assign immCLD = {4'b0, instr16[6:5], instr16[12:10], 3'b000};
|
||||||
assign immCS = {5'b0, instr16[5], instr16[12:10], instr16[6], 2'b00};
|
assign immCS = {5'b0, instr16[5], instr16[12:10], instr16[6], 2'b00};
|
||||||
assign immCSD = {4'b0, instr16[6:5], instr16[12:10], 3'b000};
|
assign immCSD = {4'b0, instr16[6:5], instr16[12:10], 3'b000};
|
||||||
assign immCJ = {instr16[12], instr16[8], instr16[10:9], instr16[6], instr16[7], instr16[2], instr16[11], instr16[5:3], {9{instr16[12]}}};
|
assign immCJ = {instr16[12], instr16[8], instr16[10:9], instr16[6], instr16[7], instr16[2], instr16[11], instr16[5:3], {9{instr16[12]}}};
|
||||||
assign immCB = {{4{instr16[12]}}, instr16[6:5], instr16[2], instr16[11:10], instr16[4:3], instr16[12]};
|
assign immCB = {{4{instr16[12]}}, instr16[6:5], instr16[2], instr16[11:10], instr16[4:3], instr16[12]};
|
||||||
assign immCI = {{7{instr16[12]}}, instr16[6:2]};
|
assign immCI = {{7{instr16[12]}}, instr16[6:2]};
|
||||||
assign immCILUI = {{15{instr16[12]}}, instr16[6:2]};
|
assign immCILUI = {{15{instr16[12]}}, instr16[6:2]};
|
||||||
assign immCIASP = {{3{instr16[12]}}, instr16[4:3], instr16[5], instr16[2], instr16[6], 4'b0000};
|
assign immCIASP = {{3{instr16[12]}}, instr16[4:3], instr16[5], instr16[2], instr16[6], 4'b0000};
|
||||||
assign immCIW = {2'b00, instr16[10:7], instr16[12:11], instr16[5], instr16[6], 2'b00};
|
assign immCIW = {2'b00, instr16[10:7], instr16[12:11], instr16[5], instr16[6], 2'b00};
|
||||||
assign immSH = {instr16[12], instr16[6:2]};
|
assign immSH = {instr16[12], instr16[6:2]};
|
||||||
|
|
||||||
// only for RV128
|
// only for RV128
|
||||||
// assign immCILSPQ = {2{instr16[5]}, instr16[5:2], instr16[12], instr16[6], 4'b0000};
|
// assign immCILSPQ = {2{instr16[5]}, instr16[5:2], instr16[12], instr16[6], 4'b0000};
|
||||||
@ -75,104 +74,103 @@ module decompress (
|
|||||||
// assign immCLQ = {4{instr16[10]}, instr16[6:5], instr16[12:11], 4'b0000};
|
// assign immCLQ = {4{instr16[10]}, instr16[6:5], instr16[12:11], 4'b0000};
|
||||||
// assign immCSQ = {4{instr16[10]}, instr16[6:5], instr16[12:11], 4'b0000};
|
// assign immCSQ = {4{instr16[10]}, instr16[6:5], instr16[12:11], 4'b0000};
|
||||||
|
|
||||||
always_comb
|
always_comb
|
||||||
if (op == 2'b11) begin // noncompressed instruction
|
if (op == 2'b11) begin // noncompressed instruction
|
||||||
InstrD = InstrRawD;
|
InstrD = InstrRawD;
|
||||||
IllegalCompInstrD = 0;
|
IllegalCompInstrD = 0;
|
||||||
end else begin // convert compressed instruction into uncompressed
|
end else begin // convert compressed instruction into uncompressed
|
||||||
IllegalCompInstrD = 0;
|
IllegalCompInstrD = 0;
|
||||||
case ({op, instr16[15:13]})
|
case ({op, instr16[15:13]})
|
||||||
5'b00000: if (immCIW != 0) InstrD = {immCIW, 5'b00010, 3'b000, rdp, 7'b0010011}; // c.addi4spn
|
5'b00000: if (immCIW != 0) InstrD = {immCIW, 5'b00010, 3'b000, rdp, 7'b0010011}; // c.addi4spn
|
||||||
else begin // illegal instruction
|
else begin // illegal instruction
|
||||||
|
IllegalCompInstrD = 1;
|
||||||
|
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
|
||||||
|
end
|
||||||
|
5'b00001: InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld
|
||||||
|
5'b00010: InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw
|
||||||
|
5'b00011: if (`XLEN==32)
|
||||||
|
InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw
|
||||||
|
else
|
||||||
|
InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld;
|
||||||
|
5'b00101: InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd
|
||||||
|
5'b00110: InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw
|
||||||
|
5'b00111: if (`XLEN==32)
|
||||||
|
InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw
|
||||||
|
else
|
||||||
|
InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd
|
||||||
|
5'b01000: InstrD = {immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi
|
||||||
|
5'b01001: if (`XLEN==32)
|
||||||
|
InstrD = {immCJ, 5'b00001, 7'b1101111}; // c.jal
|
||||||
|
else
|
||||||
|
InstrD = {immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw
|
||||||
|
5'b01010: InstrD = {immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li
|
||||||
|
5'b01011: if (rds1 != 5'b00010)
|
||||||
|
InstrD = {immCILUI, rds1, 7'b0110111}; // c.lui
|
||||||
|
else
|
||||||
|
InstrD = {immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp
|
||||||
|
5'b01100: if (instr16[11:10] == 2'b00)
|
||||||
|
InstrD = {6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli
|
||||||
|
else if (instr16[11:10] == 2'b01)
|
||||||
|
InstrD = {6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai
|
||||||
|
else if (instr16[11:10] == 2'b10)
|
||||||
|
InstrD = {immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi
|
||||||
|
else if (instr16[12:10] == 3'b011)
|
||||||
|
if (instr16[6:5] == 2'b00)
|
||||||
|
InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.sub
|
||||||
|
else if (instr16[6:5] == 2'b01)
|
||||||
|
InstrD = {7'b0000000, rs2p, rds1p, 3'b100, rds1p, 7'b0110011}; // c.xor
|
||||||
|
else if (instr16[6:5] == 2'b10)
|
||||||
|
InstrD = {7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or
|
||||||
|
else // if (instr16[6:5] == 2'b11)
|
||||||
|
InstrD = {7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and
|
||||||
|
else if (instr16[12:10] == 3'b111 & `XLEN > 32)
|
||||||
|
if (instr16[6:5] == 2'b00)
|
||||||
|
InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw
|
||||||
|
else if (instr16[6:5] == 2'b01)
|
||||||
|
InstrD = {7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw
|
||||||
|
else begin // reserved
|
||||||
IllegalCompInstrD = 1;
|
IllegalCompInstrD = 1;
|
||||||
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
|
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
|
||||||
end
|
end
|
||||||
5'b00001: InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld
|
else begin // illegal instruction
|
||||||
5'b00010: InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw
|
IllegalCompInstrD = 1;
|
||||||
5'b00011: if (`XLEN==32)
|
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
|
||||||
InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw
|
end
|
||||||
|
5'b01101: InstrD = {immCJ, 5'b00000, 7'b1101111}; // c.j
|
||||||
|
5'b01110: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz
|
||||||
|
5'b01111: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez
|
||||||
|
5'b10000: InstrD = {6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli
|
||||||
|
5'b10001: InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp
|
||||||
|
5'b10010: InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp
|
||||||
|
5'b10011: if (`XLEN == 32)
|
||||||
|
InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp
|
||||||
|
else
|
||||||
|
InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp
|
||||||
|
5'b10100: if (instr16[12] == 0)
|
||||||
|
if (instr16[6:2] == 5'b00000)
|
||||||
|
InstrD = {7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr
|
||||||
else
|
else
|
||||||
InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld;
|
InstrD = {7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv
|
||||||
5'b00101: InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd
|
else
|
||||||
5'b00110: InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw
|
if (rs2 == 5'b00000)
|
||||||
5'b00111: if (`XLEN==32)
|
if (rds1 == 5'b00000)
|
||||||
InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw
|
InstrD = {12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak
|
||||||
else
|
|
||||||
InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd
|
|
||||||
5'b01000: InstrD = {immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi
|
|
||||||
5'b01001: if (`XLEN==32)
|
|
||||||
InstrD = {immCJ, 5'b00001, 7'b1101111}; // c.jal
|
|
||||||
else
|
|
||||||
InstrD = {immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw
|
|
||||||
5'b01010: InstrD = {immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li
|
|
||||||
5'b01011: if (rds1 != 5'b00010)
|
|
||||||
InstrD = {immCILUI, rds1, 7'b0110111}; // c.lui
|
|
||||||
else
|
|
||||||
InstrD = {immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp
|
|
||||||
5'b01100: if (instr16[11:10] == 2'b00)
|
|
||||||
InstrD = {6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli
|
|
||||||
else if (instr16[11:10] == 2'b01)
|
|
||||||
InstrD = {6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai
|
|
||||||
else if (instr16[11:10] == 2'b10)
|
|
||||||
InstrD = {immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi
|
|
||||||
else if (instr16[12:10] == 3'b011)
|
|
||||||
if (instr16[6:5] == 2'b00)
|
|
||||||
InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.sub
|
|
||||||
else if (instr16[6:5] == 2'b01)
|
|
||||||
InstrD = {7'b0000000, rs2p, rds1p, 3'b100, rds1p, 7'b0110011}; // c.xor
|
|
||||||
else if (instr16[6:5] == 2'b10)
|
|
||||||
InstrD = {7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or
|
|
||||||
else // if (instr16[6:5] == 2'b11)
|
|
||||||
InstrD = {7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and
|
|
||||||
else if (instr16[12:10] == 3'b111 & `XLEN > 32)
|
|
||||||
if (instr16[6:5] == 2'b00)
|
|
||||||
InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw
|
|
||||||
else if (instr16[6:5] == 2'b01)
|
|
||||||
InstrD = {7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw
|
|
||||||
else begin // reserved
|
|
||||||
IllegalCompInstrD = 1;
|
|
||||||
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
|
|
||||||
end
|
|
||||||
else begin // illegal instruction
|
|
||||||
IllegalCompInstrD = 1;
|
|
||||||
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
|
|
||||||
end
|
|
||||||
5'b01101: InstrD = {immCJ, 5'b00000, 7'b1101111}; // c.j
|
|
||||||
5'b01110: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz
|
|
||||||
5'b01111: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez
|
|
||||||
5'b10000: InstrD = {6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli
|
|
||||||
5'b10001: InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp
|
|
||||||
5'b10010: InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp
|
|
||||||
5'b10011: if (`XLEN == 32)
|
|
||||||
InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp
|
|
||||||
else
|
|
||||||
InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp
|
|
||||||
5'b10100: if (instr16[12] == 0)
|
|
||||||
if (instr16[6:2] == 5'b00000)
|
|
||||||
InstrD = {7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr
|
|
||||||
else
|
else
|
||||||
InstrD = {7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv
|
InstrD = {12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr
|
||||||
else
|
else
|
||||||
if (rs2 == 5'b00000)
|
InstrD = {7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add
|
||||||
if (rds1 == 5'b00000)
|
5'b10101: InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp
|
||||||
InstrD = {12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak
|
5'b10110: InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp
|
||||||
else
|
5'b10111: if (`XLEN==32)
|
||||||
InstrD = {12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr
|
InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp
|
||||||
else
|
else
|
||||||
InstrD = {7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add
|
InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp
|
||||||
5'b10101: InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp
|
default: begin // illegal instruction
|
||||||
5'b10110: InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp
|
IllegalCompInstrD = 1;
|
||||||
5'b10111: if (`XLEN==32)
|
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
|
||||||
InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp
|
end
|
||||||
else
|
endcase
|
||||||
InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp
|
end
|
||||||
default: begin // illegal instruction
|
end
|
||||||
IllegalCompInstrD = 1;
|
|
||||||
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -38,77 +38,75 @@ module subwordread
|
|||||||
// Funct3M[2] is the unsigned bit. mask upper bits.
|
// Funct3M[2] is the unsigned bit. mask upper bits.
|
||||||
// Funct3M[1:0] is the size of the memory access.
|
// Funct3M[1:0] is the size of the memory access.
|
||||||
|
|
||||||
generate
|
if (`XLEN == 64) begin:swrmux
|
||||||
if (`XLEN == 64) begin:swrmux
|
// ByteMe mux
|
||||||
// ByteMe mux
|
always_comb
|
||||||
always_comb
|
case(LsuPAdrM[2:0])
|
||||||
case(LsuPAdrM[2:0])
|
3'b000: ByteM = ReadDataWordMuxM[7:0];
|
||||||
3'b000: ByteM = ReadDataWordMuxM[7:0];
|
3'b001: ByteM = ReadDataWordMuxM[15:8];
|
||||||
3'b001: ByteM = ReadDataWordMuxM[15:8];
|
3'b010: ByteM = ReadDataWordMuxM[23:16];
|
||||||
3'b010: ByteM = ReadDataWordMuxM[23:16];
|
3'b011: ByteM = ReadDataWordMuxM[31:24];
|
||||||
3'b011: ByteM = ReadDataWordMuxM[31:24];
|
3'b100: ByteM = ReadDataWordMuxM[39:32];
|
||||||
3'b100: ByteM = ReadDataWordMuxM[39:32];
|
3'b101: ByteM = ReadDataWordMuxM[47:40];
|
||||||
3'b101: ByteM = ReadDataWordMuxM[47:40];
|
3'b110: ByteM = ReadDataWordMuxM[55:48];
|
||||||
3'b110: ByteM = ReadDataWordMuxM[55:48];
|
3'b111: ByteM = ReadDataWordMuxM[63:56];
|
||||||
3'b111: ByteM = ReadDataWordMuxM[63:56];
|
endcase
|
||||||
|
|
||||||
|
// halfword mux
|
||||||
|
always_comb
|
||||||
|
case(LsuPAdrM[2:1])
|
||||||
|
2'b00: HalfwordM = ReadDataWordMuxM[15:0];
|
||||||
|
2'b01: HalfwordM = ReadDataWordMuxM[31:16];
|
||||||
|
2'b10: HalfwordM = ReadDataWordMuxM[47:32];
|
||||||
|
2'b11: HalfwordM = ReadDataWordMuxM[63:48];
|
||||||
|
endcase
|
||||||
|
|
||||||
|
logic [31:0] WordM;
|
||||||
|
|
||||||
|
always_comb
|
||||||
|
case(LsuPAdrM[2])
|
||||||
|
1'b0: WordM = ReadDataWordMuxM[31:0];
|
||||||
|
1'b1: WordM = ReadDataWordMuxM[63:32];
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
// halfword mux
|
// sign extension
|
||||||
always_comb
|
always_comb
|
||||||
case(LsuPAdrM[2:1])
|
case(Funct3M)
|
||||||
2'b00: HalfwordM = ReadDataWordMuxM[15:0];
|
3'b000: ReadDataM = {{56{ByteM[7]}}, ByteM}; // lb
|
||||||
2'b01: HalfwordM = ReadDataWordMuxM[31:16];
|
3'b001: ReadDataM = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
|
||||||
2'b10: HalfwordM = ReadDataWordMuxM[47:32];
|
3'b010: ReadDataM = {{32{WordM[31]}}, WordM[31:0]}; // lw
|
||||||
2'b11: HalfwordM = ReadDataWordMuxM[63:48];
|
3'b011: ReadDataM = ReadDataWordMuxM; // ld
|
||||||
endcase
|
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 = ReadDataWordMuxM; // Shouldn't happen
|
||||||
|
endcase
|
||||||
|
end else begin:swrmux // 32-bit
|
||||||
|
// byte mux
|
||||||
|
always_comb
|
||||||
|
case(LsuPAdrM[1:0])
|
||||||
|
2'b00: ByteM = ReadDataWordMuxM[7:0];
|
||||||
|
2'b01: ByteM = ReadDataWordMuxM[15:8];
|
||||||
|
2'b10: ByteM = ReadDataWordMuxM[23:16];
|
||||||
|
2'b11: ByteM = ReadDataWordMuxM[31:24];
|
||||||
|
endcase
|
||||||
|
|
||||||
logic [31:0] WordM;
|
// halfword mux
|
||||||
|
always_comb
|
||||||
|
case(LsuPAdrM[1])
|
||||||
|
1'b0: HalfwordM = ReadDataWordMuxM[15:0];
|
||||||
|
1'b1: HalfwordM = ReadDataWordMuxM[31:16];
|
||||||
|
endcase
|
||||||
|
|
||||||
always_comb
|
// sign extension
|
||||||
case(LsuPAdrM[2])
|
always_comb
|
||||||
1'b0: WordM = ReadDataWordMuxM[31:0];
|
case(Funct3M)
|
||||||
1'b1: WordM = ReadDataWordMuxM[63:32];
|
3'b000: ReadDataM = {{24{ByteM[7]}}, ByteM}; // lb
|
||||||
endcase
|
3'b001: ReadDataM = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
|
||||||
|
3'b010: ReadDataM = ReadDataWordMuxM; // lw
|
||||||
// sign extension
|
3'b100: ReadDataM = {24'b0, ByteM[7:0]}; // lbu
|
||||||
always_comb
|
3'b101: ReadDataM = {16'b0, HalfwordM[15:0]}; // lhu
|
||||||
case(Funct3M)
|
default: ReadDataM = ReadDataWordMuxM;
|
||||||
3'b000: ReadDataM = {{56{ByteM[7]}}, ByteM}; // lb
|
endcase
|
||||||
3'b001: ReadDataM = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
|
end
|
||||||
3'b010: ReadDataM = {{32{WordM[31]}}, WordM[31:0]}; // lw
|
|
||||||
3'b011: ReadDataM = ReadDataWordMuxM; // 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 = ReadDataWordMuxM; // Shouldn't happen
|
|
||||||
endcase
|
|
||||||
end else begin :swrmux // 32-bit
|
|
||||||
// byte mux
|
|
||||||
always_comb
|
|
||||||
case(LsuPAdrM[1:0])
|
|
||||||
2'b00: ByteM = ReadDataWordMuxM[7:0];
|
|
||||||
2'b01: ByteM = ReadDataWordMuxM[15:8];
|
|
||||||
2'b10: ByteM = ReadDataWordMuxM[23:16];
|
|
||||||
2'b11: ByteM = ReadDataWordMuxM[31:24];
|
|
||||||
endcase
|
|
||||||
|
|
||||||
// halfword mux
|
|
||||||
always_comb
|
|
||||||
case(LsuPAdrM[1])
|
|
||||||
1'b0: HalfwordM = ReadDataWordMuxM[15:0];
|
|
||||||
1'b1: HalfwordM = ReadDataWordMuxM[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 = ReadDataWordMuxM; // lw
|
|
||||||
3'b100: ReadDataM = {24'b0, ByteM[7:0]}; // lbu
|
|
||||||
3'b101: ReadDataM = {16'b0, HalfwordM[15:0]}; // lhu
|
|
||||||
default: ReadDataM = ReadDataWordMuxM;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -52,7 +52,7 @@ module hptw
|
|||||||
L1_ADR, L1_RD,
|
L1_ADR, L1_RD,
|
||||||
L2_ADR, L2_RD,
|
L2_ADR, L2_RD,
|
||||||
L3_ADR, L3_RD,
|
L3_ADR, L3_RD,
|
||||||
LEAF, IDLE} statetype; // *** placed outside generate statement to remove synthesis errors
|
LEAF, IDLE} statetype;
|
||||||
|
|
||||||
logic DTLBWalk; // register TLBs translation miss requests
|
logic DTLBWalk; // register TLBs translation miss requests
|
||||||
logic [`PPN_BITS-1:0] BasePageTablePPN;
|
logic [`PPN_BITS-1:0] BasePageTablePPN;
|
||||||
|
@ -90,27 +90,25 @@ module mmu #(parameter TLB_ENTRIES = 8, // number of TLB Entries
|
|||||||
|
|
||||||
|
|
||||||
// only instantiate TLB if Virtual Memory is supported
|
// only instantiate TLB if Virtual Memory is supported
|
||||||
generate
|
if (`MEM_VIRTMEM) begin:tlb
|
||||||
if (`MEM_VIRTMEM) begin:tlb
|
logic ReadAccess, WriteAccess;
|
||||||
logic ReadAccess, WriteAccess;
|
assign ReadAccess = ExecuteAccessF | ReadAccessM; // execute also acts as a TLB read. Execute and Read are never active for the same MMU, so safe to mix pipestages
|
||||||
assign ReadAccess = ExecuteAccessF | ReadAccessM; // execute also acts as a TLB read. Execute and Read are never active for the same MMU, so safe to mix pipestages
|
assign WriteAccess = WriteAccessM;
|
||||||
assign WriteAccess = WriteAccessM;
|
tlb #(.TLB_ENTRIES(TLB_ENTRIES), .ITLB(IMMU))
|
||||||
tlb #(.TLB_ENTRIES(TLB_ENTRIES), .ITLB(IMMU))
|
tlb(.clk, .reset,
|
||||||
tlb(.clk, .reset,
|
.SATP_MODE(SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]),
|
||||||
.SATP_MODE(SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]),
|
.SATP_ASID(SATP_REGW[`ASID_BASE+`ASID_BITS-1:`ASID_BASE]),
|
||||||
.SATP_ASID(SATP_REGW[`ASID_BASE+`ASID_BITS-1:`ASID_BASE]),
|
.VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP,
|
||||||
.VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP,
|
.PrivilegeModeW, .ReadAccess, .WriteAccess,
|
||||||
.PrivilegeModeW, .ReadAccess, .WriteAccess,
|
.DisableTranslation, .PTE, .PageTypeWriteVal,
|
||||||
.DisableTranslation, .PTE, .PageTypeWriteVal,
|
.TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit,
|
||||||
.TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit,
|
.Translate, .TLBPageFault);
|
||||||
.Translate, .TLBPageFault);
|
end else begin:tlb// just pass address through as physical
|
||||||
end else begin:tlb// just pass address through as physical
|
assign Translate = 0;
|
||||||
assign Translate = 0;
|
assign TLBMiss = 0;
|
||||||
assign TLBMiss = 0;
|
assign TLBHit = 1; // *** is this necessary
|
||||||
assign TLBHit = 1; // *** is this necessary
|
assign TLBPageFault = 0;
|
||||||
assign TLBPageFault = 0;
|
end
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
// If translation is occuring, select translated physical address from TLB
|
// If translation is occuring, select translated physical address from TLB
|
||||||
mux2 #(`PA_BITS) addressmux(PAdr, TLBPAdr, Translate, PhysicalAddress);
|
mux2 #(`PA_BITS) addressmux(PAdr, TLBPAdr, Translate, PhysicalAddress);
|
||||||
|
@ -68,7 +68,7 @@ module pmpadrdec (
|
|||||||
|
|
||||||
assign NAMask[1:0] = {2'b11};
|
assign NAMask[1:0] = {2'b11};
|
||||||
assign NAMask[`PA_BITS-1:2] = (PMPAdr[`PA_BITS-3:0] + {{(`PA_BITS-3){1'b0}}, (AdrMode == NAPOT)}) ^ PMPAdr[`PA_BITS-3:0];
|
assign NAMask[`PA_BITS-1:2] = (PMPAdr[`PA_BITS-3:0] + {{(`PA_BITS-3){1'b0}}, (AdrMode == NAPOT)}) ^ PMPAdr[`PA_BITS-3:0];
|
||||||
// generates a mask where the bottom k bits are 1, corresponding to a size of 2^k bytes for this memory region.
|
// form a mask where the bottom k bits are 1, corresponding to a size of 2^k bytes for this memory region.
|
||||||
// This assumes we're using at least an NA4 region, but works for any size NAPOT region.
|
// This assumes we're using at least an NA4 region, but works for any size NAPOT region.
|
||||||
assign NABase = {(PMPAdr[`PA_BITS-3:0] & ~NAMask[`PA_BITS-1:2]), 2'b00}; // base physical address of the pmp.
|
assign NABase = {(PMPAdr[`PA_BITS-3:0] & ~NAMask[`PA_BITS-1:2]), 2'b00}; // base physical address of the pmp.
|
||||||
|
|
||||||
|
@ -47,37 +47,34 @@ module pmpchecker (
|
|||||||
output logic PMPStoreAccessFaultM
|
output logic PMPStoreAccessFaultM
|
||||||
);
|
);
|
||||||
|
|
||||||
generate
|
if (`PMP_ENTRIES > 0) begin: pmpchecker
|
||||||
if (`PMP_ENTRIES > 0) begin: pmpchecker
|
// Bit i is high when the address falls in PMP region i
|
||||||
// Bit i is high when the address falls in PMP region i
|
logic EnforcePMP;
|
||||||
logic EnforcePMP;
|
logic [`PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges
|
||||||
logic [`PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges
|
logic [`PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address.
|
||||||
logic [`PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address.
|
logic [`PMP_ENTRIES-1:0] Active; // PMP register i is non-null
|
||||||
logic [`PMP_ENTRIES-1:0] Active; // PMP register i is non-null
|
logic [`PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set
|
||||||
logic [`PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set
|
logic [`PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i]
|
||||||
logic [`PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i]
|
|
||||||
|
|
||||||
pmpadrdec pmpadrdecs[`PMP_ENTRIES-1:0](
|
pmpadrdec pmpadrdecs[`PMP_ENTRIES-1:0](
|
||||||
.PhysicalAddress,
|
.PhysicalAddress,
|
||||||
.PMPCfg(PMPCFG_ARRAY_REGW),
|
.PMPCfg(PMPCFG_ARRAY_REGW),
|
||||||
.PMPAdr(PMPADDR_ARRAY_REGW),
|
.PMPAdr(PMPADDR_ARRAY_REGW),
|
||||||
.PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}),
|
.PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}),
|
||||||
.PAgePMPAdrOut(PAgePMPAdr),
|
.PAgePMPAdrOut(PAgePMPAdr),
|
||||||
.FirstMatch, .Match, .Active, .L, .X, .W, .R);
|
.FirstMatch, .Match, .Active, .L, .X, .W, .R);
|
||||||
|
|
||||||
priorityonehot #(`PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the adress decoders to find the first one that matches.
|
priorityonehot #(`PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the adress decoders to find the first one that matches.
|
||||||
|
|
||||||
// Only enforce PMP checking for S and U modes when at least one PMP is active or in Machine mode when L bit is set in selected region
|
// Only enforce PMP checking for S and U modes when at least one PMP is active or in Machine mode when L bit is set in selected region
|
||||||
assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |L : |Active;
|
assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |L : |Active;
|
||||||
|
|
||||||
assign PMPInstrAccessFaultF = EnforcePMP & ExecuteAccessF & ~|X;
|
assign PMPInstrAccessFaultF = EnforcePMP & ExecuteAccessF & ~|X;
|
||||||
assign PMPStoreAccessFaultM = EnforcePMP & WriteAccessM & ~|W;
|
assign PMPStoreAccessFaultM = EnforcePMP & WriteAccessM & ~|W;
|
||||||
assign PMPLoadAccessFaultM = EnforcePMP & ReadAccessM & ~|R;
|
assign PMPLoadAccessFaultM = EnforcePMP & ReadAccessM & ~|R;
|
||||||
end else begin: pmpchecker // no checker
|
end else begin: pmpchecker // no checker
|
||||||
assign PMPInstrAccessFaultF = 0;
|
assign PMPInstrAccessFaultF = 0;
|
||||||
assign PMPLoadAccessFaultM = 0;
|
assign PMPLoadAccessFaultM = 0;
|
||||||
assign PMPStoreAccessFaultM = 0;
|
assign PMPStoreAccessFaultM = 0;
|
||||||
end
|
end
|
||||||
endgenerate
|
|
||||||
//assign PMPSquashBusAccess = PMPInstrAccessFaultF | PMPLoadAccessFaultM | PMPStoreAccessFaultM;
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -34,25 +34,9 @@ module priorityonehot #(parameter ENTRIES = 8) (
|
|||||||
input logic [ENTRIES-1:0] a,
|
input logic [ENTRIES-1:0] a,
|
||||||
output logic [ENTRIES-1:0] y
|
output logic [ENTRIES-1:0] y
|
||||||
);
|
);
|
||||||
|
|
||||||
/* verilator lint_off UNOPTFLAT */
|
|
||||||
|
|
||||||
logic [ENTRIES-1:0] nolower;
|
logic [ENTRIES-1:0] nolower;
|
||||||
|
|
||||||
// generate thermometer code mask
|
// create thermometer code mask
|
||||||
prioritythermometer #(ENTRIES) maskgen(.a({a[ENTRIES-2:0], 1'b1}), .y(nolower));
|
prioritythermometer #(ENTRIES) maskgen(.a({a[ENTRIES-2:0], 1'b1}), .y(nolower));
|
||||||
// genvar i;
|
|
||||||
// generate
|
|
||||||
// assign nolower[0] = 1'b1;
|
|
||||||
// for (i=1; i<ENTRIES; i++) begin:therm
|
|
||||||
// assign nolower[i] = nolower[i-1] & ~a[i-1];
|
|
||||||
// end
|
|
||||||
// endgenerate
|
|
||||||
// *** replace mask generation logic ^^^ with priority thermometer
|
|
||||||
|
|
||||||
|
|
||||||
assign y = a & nolower;
|
assign y = a & nolower;
|
||||||
|
|
||||||
/* verilator lint_on UNOPTFLAT */
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -37,20 +37,15 @@ module prioritythermometer #(parameter N = 8) (
|
|||||||
output logic [N-1:0] y
|
output logic [N-1:0] y
|
||||||
);
|
);
|
||||||
|
|
||||||
// Carefully crafted so design compiler would synthesize into a fast tree structure
|
// Carefully crafted so design compiler will synthesize into a fast tree structure
|
||||||
// Rather than linear.
|
// Rather than linear.
|
||||||
|
|
||||||
// generate thermometer code mask
|
// create thermometer code mask
|
||||||
genvar i;
|
genvar i;
|
||||||
generate
|
assign y[0] = a[0];
|
||||||
assign y[0] = a[0];
|
for (i=1; i<N; i++) begin:therm
|
||||||
for (i=1; i<N; i++) begin:therm
|
assign y[i] = y[i-1] & ~a[i];
|
||||||
assign y[i] = y[i-1] & ~a[i]; // *** made to be the same as onehot (without the inverter) to see if the probelme is something weird with synthesis
|
end
|
||||||
// assign y[i] = y[i-1] & a[i];
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,38 +60,36 @@ module tlbcamline #(parameter KEY_BITS = 20,
|
|||||||
|
|
||||||
assign MatchASID = (SATP_ASID == Key_ASID) | PTE_G;
|
assign MatchASID = (SATP_ASID == Key_ASID) | PTE_G;
|
||||||
|
|
||||||
generate
|
if (`XLEN == 32) begin: match
|
||||||
if (`XLEN == 32) begin:match
|
|
||||||
|
|
||||||
assign {Key_ASID, Key1, Key0} = Key;
|
assign {Key_ASID, Key1, Key0} = Key;
|
||||||
assign {Query1, Query0} = VPN;
|
assign {Query1, Query0} = VPN;
|
||||||
|
|
||||||
// Calculate the actual match value based on the input vpn and the page type.
|
// Calculate the actual match value based on the input vpn and the page type.
|
||||||
// For example, a megapage in SV32 only cares about VPN[1], so VPN[0]
|
// For example, a megapage in SV32 only cares about VPN[1], so VPN[0]
|
||||||
// should automatically match.
|
// should automatically match.
|
||||||
assign Match0 = (Query0 == Key0) | (PageType[0]); // least signifcant section
|
assign Match0 = (Query0 == Key0) | (PageType[0]); // least signifcant section
|
||||||
assign Match1 = (Query1 == Key1);
|
assign Match1 = (Query1 == Key1);
|
||||||
|
|
||||||
assign Match = Match0 & Match1 & MatchASID & Valid;
|
assign Match = Match0 & Match1 & MatchASID & Valid;
|
||||||
end else begin:match
|
end else begin: match
|
||||||
|
|
||||||
logic [SEGMENT_BITS-1:0] Key2, Key3, Query2, Query3;
|
logic [SEGMENT_BITS-1:0] Key2, Key3, Query2, Query3;
|
||||||
logic Match2, Match3;
|
logic Match2, Match3;
|
||||||
|
|
||||||
assign {Query3, Query2, Query1, Query0} = VPN;
|
assign {Query3, Query2, Query1, Query0} = VPN;
|
||||||
assign {Key_ASID, Key3, Key2, Key1, Key0} = Key;
|
assign {Key_ASID, Key3, Key2, Key1, Key0} = Key;
|
||||||
|
|
||||||
// Calculate the actual match value based on the input vpn and the page type.
|
// Calculate the actual match value based on the input vpn and the page type.
|
||||||
// For example, a gigapage in SV39 only cares about VPN[2], so VPN[0] and VPN[1]
|
// For example, a gigapage in SV39 only cares about VPN[2], so VPN[0] and VPN[1]
|
||||||
// should automatically match.
|
// should automatically match.
|
||||||
assign Match0 = (Query0 == Key0) | (PageType > 2'd0); // least signifcant section
|
assign Match0 = (Query0 == Key0) | (PageType > 2'd0); // least signifcant section
|
||||||
assign Match1 = (Query1 == Key1) | (PageType > 2'd1);
|
assign Match1 = (Query1 == Key1) | (PageType > 2'd1);
|
||||||
assign Match2 = (Query2 == Key2) | (PageType > 2'd2);
|
assign Match2 = (Query2 == Key2) | (PageType > 2'd2);
|
||||||
assign Match3 = (Query3 == Key3) | SV39Mode; // this should always match in sv39 because they aren't used
|
assign Match3 = (Query3 == Key3) | SV39Mode; // this should always match in sv39 because they aren't used
|
||||||
|
|
||||||
assign Match = Match0 & Match1 & Match2 & Match3 & MatchASID & Valid;
|
assign Match = Match0 & Match1 & Match2 & Match3 & MatchASID & Valid;
|
||||||
end
|
end
|
||||||
endgenerate
|
|
||||||
|
|
||||||
// On a write, update the type of the page referred to by this line.
|
// On a write, update the type of the page referred to by this line.
|
||||||
flopenr #(2) pagetypeflop(clk, reset, WriteEnable, PageTypeWriteVal, PageType);
|
flopenr #(2) pagetypeflop(clk, reset, WriteEnable, PageTypeWriteVal, PageType);
|
||||||
|
@ -60,65 +60,59 @@ module tlbcontrol #(parameter ITLB = 0) (
|
|||||||
logic UpperBitsUnequalPageFault;
|
logic UpperBitsUnequalPageFault;
|
||||||
logic DAPageFault;
|
logic DAPageFault;
|
||||||
logic TLBAccess;
|
logic TLBAccess;
|
||||||
|
logic ImproperPrivilege;
|
||||||
|
|
||||||
// Grab the sv mode from SATP and determine whether translation should occur
|
// Grab the sv mode from SATP and determine whether translation should occur
|
||||||
assign EffectivePrivilegeMode = (ITLB == 1) ? PrivilegeModeW : (STATUS_MPRV ? STATUS_MPP : PrivilegeModeW); // DTLB uses MPP mode when MPRV is 1
|
assign EffectivePrivilegeMode = (ITLB == 1) ? PrivilegeModeW : (STATUS_MPRV ? STATUS_MPP : PrivilegeModeW); // DTLB uses MPP mode when MPRV is 1
|
||||||
assign Translate = (SATP_MODE != `NO_TRANSLATE) & (EffectivePrivilegeMode != `M_MODE) & ~DisableTranslation;
|
assign Translate = (SATP_MODE != `NO_TRANSLATE) & (EffectivePrivilegeMode != `M_MODE) & ~DisableTranslation;
|
||||||
generate
|
if (`XLEN==64) begin:rv64
|
||||||
if (`XLEN==64) begin:rv64
|
assign SV39Mode = (SATP_MODE == `SV39);
|
||||||
assign SV39Mode = (SATP_MODE == `SV39);
|
// page fault if upper bits aren't all the same
|
||||||
// generate page fault if upper bits aren't all the same
|
logic UpperEqual39, UpperEqual48;
|
||||||
logic UpperEqual39, UpperEqual48;
|
assign UpperEqual39 = &(VAdr[63:38]) | ~|(VAdr[63:38]);
|
||||||
assign UpperEqual39 = &(VAdr[63:38]) | ~|(VAdr[63:38]);
|
assign UpperEqual48 = &(VAdr[63:47]) | ~|(VAdr[63:47]);
|
||||||
assign UpperEqual48 = &(VAdr[63:47]) | ~|(VAdr[63:47]);
|
assign UpperBitsUnequalPageFault = SV39Mode ? ~UpperEqual39 : ~UpperEqual48;
|
||||||
assign UpperBitsUnequalPageFault = SV39Mode ? ~UpperEqual39 : ~UpperEqual48;
|
end else begin
|
||||||
end else begin
|
assign SV39Mode = 0;
|
||||||
assign SV39Mode = 0;
|
assign UpperBitsUnequalPageFault = 0;
|
||||||
assign UpperBitsUnequalPageFault = 0;
|
end
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
// Determine whether TLB is being used
|
// Determine whether TLB is being used
|
||||||
assign TLBAccess = ReadAccess | WriteAccess;
|
assign TLBAccess = ReadAccess | WriteAccess;
|
||||||
|
|
||||||
// Check whether upper bits of virtual addresss are all equal
|
// Check whether upper bits of virtual addresss are all equal
|
||||||
|
|
||||||
|
|
||||||
// unswizzle useful PTE bits
|
// unswizzle useful PTE bits
|
||||||
assign {PTE_D, PTE_A} = PTEAccessBits[7:6];
|
assign {PTE_D, PTE_A} = PTEAccessBits[7:6];
|
||||||
assign {PTE_U, PTE_X, PTE_W, PTE_R, PTE_V} = PTEAccessBits[4:0];
|
assign {PTE_U, PTE_X, PTE_W, PTE_R, PTE_V} = PTEAccessBits[4:0];
|
||||||
|
|
||||||
// Check whether the access is allowed, page faulting if not.
|
// Check whether the access is allowed, page faulting if not.
|
||||||
generate
|
if (ITLB == 1) begin:itlb // Instruction TLB fault checking
|
||||||
if (ITLB == 1) begin:itlb // Instruction TLB fault checking
|
// User mode may only execute user mode pages, and supervisor mode may
|
||||||
logic ImproperPrivilege;
|
// only execute non-user mode pages.
|
||||||
|
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) |
|
||||||
|
((EffectivePrivilegeMode == `S_MODE) & PTE_U);
|
||||||
|
// fault for software handling if access bit is off
|
||||||
|
assign DAPageFault = ~PTE_A;
|
||||||
|
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | ~PTE_X | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
|
||||||
|
end else begin:dtlb // Data TLB fault checking
|
||||||
|
logic InvalidRead, InvalidWrite;
|
||||||
|
|
||||||
// User mode may only execute user mode pages, and supervisor mode may
|
// User mode may only load/store from user mode pages, and supervisor mode
|
||||||
// only execute non-user mode pages.
|
// may only access user mode pages when STATUS_SUM is low.
|
||||||
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) |
|
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) |
|
||||||
((EffectivePrivilegeMode == `S_MODE) & PTE_U);
|
((EffectivePrivilegeMode == `S_MODE) & PTE_U & ~STATUS_SUM);
|
||||||
// fault for software handling if access bit is off
|
// Check for read error. Reads are invalid when the page is not readable
|
||||||
assign DAPageFault = ~PTE_A;
|
// (and executable pages are not readable) or when the page is neither
|
||||||
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | ~PTE_X | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
|
// readable nor executable (and executable pages are readable).
|
||||||
end else begin:dtlb // Data TLB fault checking
|
assign InvalidRead = ReadAccess & ~PTE_R & (~STATUS_MXR | ~PTE_X);
|
||||||
logic ImproperPrivilege, InvalidRead, InvalidWrite;
|
// Check for write error. Writes are invalid when the page's write bit is
|
||||||
|
// low.
|
||||||
// User mode may only load/store from user mode pages, and supervisor mode
|
assign InvalidWrite = WriteAccess & ~PTE_W;
|
||||||
// may only access user mode pages when STATUS_SUM is low.
|
// Fault for software handling if access bit is off or writing a page with dirty bit off
|
||||||
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) |
|
assign DAPageFault = ~PTE_A | WriteAccess & ~PTE_D;
|
||||||
((EffectivePrivilegeMode == `S_MODE) & PTE_U & ~STATUS_SUM);
|
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
|
||||||
// Check for read error. Reads are invalid when the page is not readable
|
end
|
||||||
// (and executable pages are not readable) or when the page is neither
|
|
||||||
// readable nor executable (and executable pages are readable).
|
|
||||||
assign InvalidRead = ReadAccess & ~PTE_R & (~STATUS_MXR | ~PTE_X);
|
|
||||||
// Check for write error. Writes are invalid when the page's write bit is
|
|
||||||
// low.
|
|
||||||
assign InvalidWrite = WriteAccess & ~PTE_W;
|
|
||||||
// Fault for software handling if access bit is off or writing a page with dirty bit off
|
|
||||||
assign DAPageFault = ~PTE_A | WriteAccess & ~PTE_D;
|
|
||||||
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
assign TLBHit = CAMHit & TLBAccess;
|
assign TLBHit = CAMHit & TLBAccess;
|
||||||
assign TLBMiss = (~CAMHit | TLBFlush) & Translate & TLBAccess;
|
assign TLBMiss = (~CAMHit | TLBFlush) & Translate & TLBAccess;
|
||||||
|
@ -43,18 +43,16 @@ module tlbmixer (
|
|||||||
logic [`PPN_BITS-1:0] PPNMixed;
|
logic [`PPN_BITS-1:0] PPNMixed;
|
||||||
|
|
||||||
// produce PageNumberMask with 1s where virtual page number bits should be untranslaetd for superpages
|
// produce PageNumberMask with 1s where virtual page number bits should be untranslaetd for superpages
|
||||||
generate
|
if (`XLEN == 32)
|
||||||
if (`XLEN == 32)
|
// kilopage: 22 bits of PPN, 0 bits of VPN
|
||||||
// kilopage: 22 bits of PPN, 0 bits of VPN
|
// megapage: 12 bits of PPN, 10 bits of VPN
|
||||||
// megapage: 12 bits of PPN, 10 bits of VPN
|
mux2 #(22) pnm(22'h000000, 22'h0003FF, HitPageType[0], PageNumberMask);
|
||||||
mux2 #(22) pnm(22'h000000, 22'h0003FF, HitPageType[0], PageNumberMask);
|
else
|
||||||
else
|
// kilopage: 44 bits of PPN, 0 bits of VPN
|
||||||
// kilopage: 44 bits of PPN, 0 bits of VPN
|
// megapage: 35 bits of PPN, 9 bits of VPN
|
||||||
// megapage: 35 bits of PPN, 9 bits of VPN
|
// gigapage: 26 bits of PPN, 18 bits of VPN
|
||||||
// gigapage: 26 bits of PPN, 18 bits of VPN
|
// terapage: 17 bits of PPN, 27 bits of VPN
|
||||||
// terapage: 17 bits of PPN, 27 bits of VPN
|
mux4 #(44) pnm(44'h00000000000, 44'h000000001FF, 44'h0000003FFFF, 44'h00007FFFFFF, HitPageType, PageNumberMask);
|
||||||
mux4 #(44) pnm(44'h00000000000, 44'h000000001FF, 44'h0000003FFFF, 44'h00007FFFFFF, HitPageType, PageNumberMask);
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
// merge low segments of VPN with high segments of PPN decided by the pagetype.
|
// merge low segments of VPN with high segments of PPN decided by the pagetype.
|
||||||
assign ZeroExtendedVPN = {{EXTRA_BITS{1'b0}}, VPN}; // forces the VPN to be the same width as PPN.
|
assign ZeroExtendedVPN = {{EXTRA_BITS{1'b0}}, VPN}; // forces the VPN to be the same width as PPN.
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -60,15 +60,13 @@ module intdivrestoring (
|
|||||||
assign DivBusyE = (state == BUSY) | DivStartE;
|
assign DivBusyE = (state == BUSY) | DivStartE;
|
||||||
|
|
||||||
// Handle sign extension for W-type instructions
|
// Handle sign extension for W-type instructions
|
||||||
generate
|
if (`XLEN == 64) begin:rv64 // RV64 has W-type instructions
|
||||||
if (`XLEN == 64) begin:rv64 // RV64 has W-type instructions
|
mux2 #(`XLEN) xinmux(ForwardedSrcAE, {ForwardedSrcAE[31:0], 32'b0}, W64E, XinE);
|
||||||
mux2 #(`XLEN) xinmux(ForwardedSrcAE, {ForwardedSrcAE[31:0], 32'b0}, W64E, XinE);
|
mux2 #(`XLEN) dinmux(ForwardedSrcBE, {{32{ForwardedSrcBE[31]&DivSignedE}}, ForwardedSrcBE[31:0]}, W64E, DinE);
|
||||||
mux2 #(`XLEN) dinmux(ForwardedSrcBE, {{32{ForwardedSrcBE[31]&DivSignedE}}, ForwardedSrcBE[31:0]}, W64E, DinE);
|
end else begin // RV32 has no W-type instructions
|
||||||
end else begin // RV32 has no W-type instructions
|
assign XinE = ForwardedSrcAE;
|
||||||
assign XinE = ForwardedSrcAE;
|
assign DinE = ForwardedSrcBE;
|
||||||
assign DinE = ForwardedSrcBE;
|
|
||||||
end
|
end
|
||||||
endgenerate
|
|
||||||
|
|
||||||
// Extract sign bits and check fo division by zero
|
// Extract sign bits and check fo division by zero
|
||||||
assign SignDE = DivSignedE & DinE[`XLEN-1];
|
assign SignDE = DivSignedE & DinE[`XLEN-1];
|
||||||
@ -97,11 +95,9 @@ module intdivrestoring (
|
|||||||
flopen #(3) Div0eMReg(clk, DivStartE, {Div0E, NegQE, SignXE}, {Div0M, NegQM, NegWM});
|
flopen #(3) Div0eMReg(clk, DivStartE, {Div0E, NegQE, SignXE}, {Div0M, NegQM, NegWM});
|
||||||
|
|
||||||
// one copy of divstep for each bit produced per cycle
|
// one copy of divstep for each bit produced per cycle
|
||||||
generate
|
genvar i;
|
||||||
genvar i;
|
for (i=0; i<`DIV_BITSPERCYCLE; i = i+1)
|
||||||
for (i=0; i<`DIV_BITSPERCYCLE; i = i+1)
|
intdivrestoringstep divstep(WM[i], XQM[i], DAbsBM, WM[i+1], XQM[i+1]);
|
||||||
intdivrestoringstep divstep(WM[i], XQM[i], DAbsBM, WM[i+1], XQM[i+1]);
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
// On final setp of signed operations, negate outputs as needed to get correct sign
|
// On final setp of signed operations, negate outputs as needed to get correct sign
|
||||||
neg #(`XLEN) qneg(XQM[0], XQnM);
|
neg #(`XLEN) qneg(XQM[0], XQnM);
|
||||||
|
@ -49,8 +49,8 @@ module mul (
|
|||||||
// Signed * Unsigned = P' + ( PA - PB)*2^(XLEN-1) - PP*2^(2XLEN-2)
|
// Signed * Unsigned = P' + ( PA - PB)*2^(XLEN-1) - PP*2^(2XLEN-2)
|
||||||
// Unsigned * Unsigned = P' + ( PA + PB)*2^(XLEN-1) + PP*2^(2XLEN-2)
|
// Unsigned * Unsigned = P' + ( PA + PB)*2^(XLEN-1) + PP*2^(2XLEN-2)
|
||||||
|
|
||||||
logic [`XLEN*2-1:0] PP0E, PP1E, PP2E, PP3E, PP4E;
|
logic [`XLEN*2-1:0] PP1E, PP2E, PP3E, PP4E;
|
||||||
logic [`XLEN*2-1:0] PP0M, PP1M, PP2M, PP3M, PP4M;
|
logic [`XLEN*2-1:0] PP1M, PP2M, PP3M, PP4M;
|
||||||
logic [`XLEN-2:0] PA, PB;
|
logic [`XLEN-2:0] PA, PB;
|
||||||
logic PP;
|
logic PP;
|
||||||
logic MULH, MULHSU;
|
logic MULH, MULHSU;
|
||||||
@ -62,7 +62,7 @@ module mul (
|
|||||||
|
|
||||||
assign Aprime = {1'b0, ForwardedSrcAE[`XLEN-2:0]};
|
assign Aprime = {1'b0, ForwardedSrcAE[`XLEN-2:0]};
|
||||||
assign Bprime = {1'b0, ForwardedSrcBE[`XLEN-2:0]};
|
assign Bprime = {1'b0, ForwardedSrcBE[`XLEN-2:0]};
|
||||||
redundantmul #(`XLEN) bigmul(.a(Aprime), .b(Bprime), .out0(PP0E), .out1(PP1E));
|
assign PP1E = Aprime * Bprime;
|
||||||
assign PA = {(`XLEN-1){ForwardedSrcAE[`XLEN-1]}} & ForwardedSrcBE[`XLEN-2:0];
|
assign PA = {(`XLEN-1){ForwardedSrcAE[`XLEN-1]}} & ForwardedSrcBE[`XLEN-2:0];
|
||||||
assign PB = {(`XLEN-1){ForwardedSrcBE[`XLEN-1]}} & ForwardedSrcAE[`XLEN-2:0];
|
assign PB = {(`XLEN-1){ForwardedSrcBE[`XLEN-1]}} & ForwardedSrcAE[`XLEN-2:0];
|
||||||
assign PP = ForwardedSrcAE[`XLEN-1] & ForwardedSrcBE[`XLEN-1];
|
assign PP = ForwardedSrcAE[`XLEN-1] & ForwardedSrcBE[`XLEN-1];
|
||||||
@ -83,12 +83,11 @@ module mul (
|
|||||||
// Memory Stage: Sum partial proudcts
|
// Memory Stage: Sum partial proudcts
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
|
|
||||||
flopenrc #(`XLEN*2) PP0Reg(clk, reset, FlushM, ~StallM, PP0E, PP0M);
|
|
||||||
flopenrc #(`XLEN*2) PP1Reg(clk, reset, FlushM, ~StallM, PP1E, PP1M);
|
flopenrc #(`XLEN*2) PP1Reg(clk, reset, FlushM, ~StallM, PP1E, PP1M);
|
||||||
flopenrc #(`XLEN*2) PP2Reg(clk, reset, FlushM, ~StallM, PP2E, PP2M);
|
flopenrc #(`XLEN*2) PP2Reg(clk, reset, FlushM, ~StallM, PP2E, PP2M);
|
||||||
flopenrc #(`XLEN*2) PP3Reg(clk, reset, FlushM, ~StallM, PP3E, PP3M);
|
flopenrc #(`XLEN*2) PP3Reg(clk, reset, FlushM, ~StallM, PP3E, PP3M);
|
||||||
flopenrc #(`XLEN*2) PP4Reg(clk, reset, FlushM, ~StallM, PP4E, PP4M);
|
flopenrc #(`XLEN*2) PP4Reg(clk, reset, FlushM, ~StallM, PP4E, PP4M);
|
||||||
|
|
||||||
assign ProdM = PP0M + PP1M + PP2M + PP3M + PP4M; //ForwardedSrcAE * ForwardedSrcBE;
|
assign ProdM = PP1M + PP2M + PP3M + PP4M; //ForwardedSrcAE * ForwardedSrcBE;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -74,13 +74,11 @@ module muldiv (
|
|||||||
|
|
||||||
// Handle sign extension for W-type instructions
|
// Handle sign extension for W-type instructions
|
||||||
flopenrc #(1) W64MReg(clk, reset, FlushM, ~StallM, W64E, W64M);
|
flopenrc #(1) W64MReg(clk, reset, FlushM, ~StallM, W64E, W64M);
|
||||||
generate
|
if (`XLEN == 64) begin:resmux // RV64 has W-type instructions
|
||||||
if (`XLEN == 64) begin:resmux // RV64 has W-type instructions
|
assign MulDivResultM = W64M ? {{32{PrelimResultM[31]}}, PrelimResultM[31:0]} : PrelimResultM;
|
||||||
assign MulDivResultM = W64M ? {{32{PrelimResultM[31]}}, PrelimResultM[31:0]} : PrelimResultM;
|
end else begin:resmux // RV32 has no W-type instructions
|
||||||
end else begin:resmux // RV32 has no W-type instructions
|
assign MulDivResultM = PrelimResultM;
|
||||||
assign MulDivResultM = PrelimResultM;
|
end
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
// Writeback stage pipeline register
|
// Writeback stage pipeline register
|
||||||
flopenrc #(`XLEN) MulDivResultWReg(clk, reset, FlushW, ~StallW, MulDivResultM, MulDivResultW);
|
flopenrc #(`XLEN) MulDivResultWReg(clk, reset, FlushW, ~StallW, MulDivResultM, MulDivResultW);
|
||||||
|
@ -56,111 +56,109 @@ module csrc #(parameter
|
|||||||
output logic IllegalCSRCAccessM
|
output logic IllegalCSRCAccessM
|
||||||
);
|
);
|
||||||
|
|
||||||
generate
|
if (`ZICOUNTERS_SUPPORTED) begin:counters
|
||||||
if (`ZICOUNTERS_SUPPORTED) begin:counters
|
(* mark_debug = "true" *) logic [63:0] CYCLE_REGW, INSTRET_REGW;
|
||||||
(* mark_debug = "true" *) logic [63:0] CYCLE_REGW, INSTRET_REGW;
|
logic [63:0] CYCLEPlusM, INSTRETPlusM;
|
||||||
logic [63:0] CYCLEPlusM, INSTRETPlusM;
|
logic [`XLEN-1:0] NextCYCLEM, NextINSTRETM;
|
||||||
logic [`XLEN-1:0] NextCYCLEM, NextINSTRETM;
|
logic WriteCYCLEM, WriteINSTRETM;
|
||||||
logic WriteCYCLEM, WriteINSTRETM;
|
logic [4:0] CounterNumM;
|
||||||
logic [4:0] CounterNumM;
|
logic [`XLEN-1:0] HPMCOUNTER_REGW[`COUNTERS-1:0];
|
||||||
logic [`XLEN-1:0] HPMCOUNTER_REGW[`COUNTERS-1:0];
|
logic [`XLEN-1:0] HPMCOUNTERH_REGW[`COUNTERS-1:0];
|
||||||
logic [`XLEN-1:0] HPMCOUNTERH_REGW[`COUNTERS-1:0];
|
logic InstrValidNotFlushedM;
|
||||||
logic InstrValidNotFlushedM;
|
logic LoadStallE, LoadStallM;
|
||||||
logic LoadStallE, LoadStallM;
|
logic [`COUNTERS-1:0] WriteHPMCOUNTERM;
|
||||||
logic [`COUNTERS-1:0] WriteHPMCOUNTERM;
|
logic [`COUNTERS-1:0] CounterEvent;
|
||||||
logic [`COUNTERS-1:0] CounterEvent;
|
logic [63:0] HPMCOUNTERPlusM[`COUNTERS-1:0];
|
||||||
logic [63:0] HPMCOUNTERPlusM[`COUNTERS-1:0];
|
logic [`XLEN-1:0] NextHPMCOUNTERM[`COUNTERS-1:0];
|
||||||
logic [`XLEN-1:0] NextHPMCOUNTERM[`COUNTERS-1:0];
|
genvar i;
|
||||||
genvar i;
|
|
||||||
|
|
||||||
// Interface signals
|
// Interface signals
|
||||||
flopenrc #(1) LoadStallEReg(.clk, .reset, .clear(1'b0), .en(~StallE), .d(LoadStallD), .q(LoadStallE)); // don't flush the load stall during a load stall.
|
flopenrc #(1) LoadStallEReg(.clk, .reset, .clear(1'b0), .en(~StallE), .d(LoadStallD), .q(LoadStallE)); // don't flush the load stall during a load stall.
|
||||||
flopenrc #(1) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(LoadStallE), .q(LoadStallM));
|
flopenrc #(1) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(LoadStallE), .q(LoadStallM));
|
||||||
assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW;
|
assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW;
|
||||||
|
|
||||||
// Determine when to increment each counter
|
// Determine when to increment each counter
|
||||||
assign CounterEvent[0] = 1'b1; // MCYCLE always increments
|
assign CounterEvent[0] = 1'b1; // MCYCLE always increments
|
||||||
assign CounterEvent[1] = 1'b0; // Counter 0 doesn't exist
|
assign CounterEvent[1] = 1'b0; // Counter 0 doesn't exist
|
||||||
assign CounterEvent[2] = InstrValidNotFlushedM;
|
assign CounterEvent[2] = InstrValidNotFlushedM;
|
||||||
if(`QEMU) begin // No other performance counters in QEMU
|
if(`QEMU) begin: cevent // No other performance counters in QEMU
|
||||||
assign CounterEvent[`COUNTERS-1:3] = 0;
|
assign CounterEvent[`COUNTERS-1:3] = 0;
|
||||||
end else begin // User-defined counters
|
end else begin: cevent // User-defined counters
|
||||||
assign CounterEvent[3] = LoadStallM; // don't want to suppress on flush as this only happens if flushed.
|
assign CounterEvent[3] = LoadStallM; // don't want to suppress on flush as this only happens if flushed.
|
||||||
assign CounterEvent[4] = BPPredDirWrongM & InstrValidNotFlushedM;
|
assign CounterEvent[4] = BPPredDirWrongM & InstrValidNotFlushedM;
|
||||||
assign CounterEvent[5] = InstrClassM[0] & InstrValidNotFlushedM;
|
assign CounterEvent[5] = InstrClassM[0] & InstrValidNotFlushedM;
|
||||||
assign CounterEvent[6] = BTBPredPCWrongM & InstrValidNotFlushedM;
|
assign CounterEvent[6] = BTBPredPCWrongM & InstrValidNotFlushedM;
|
||||||
assign CounterEvent[7] = (InstrClassM[4] | InstrClassM[2] | InstrClassM[1]) & InstrValidNotFlushedM;
|
assign CounterEvent[7] = (InstrClassM[4] | InstrClassM[2] | InstrClassM[1]) & InstrValidNotFlushedM;
|
||||||
assign CounterEvent[8] = RASPredPCWrongM & InstrValidNotFlushedM;
|
assign CounterEvent[8] = RASPredPCWrongM & InstrValidNotFlushedM;
|
||||||
assign CounterEvent[9] = InstrClassM[3] & InstrValidNotFlushedM;
|
assign CounterEvent[9] = InstrClassM[3] & InstrValidNotFlushedM;
|
||||||
assign CounterEvent[10] = BPPredClassNonCFIWrongM & InstrValidNotFlushedM;
|
assign CounterEvent[10] = BPPredClassNonCFIWrongM & InstrValidNotFlushedM;
|
||||||
assign CounterEvent[11] = DCacheAccess;
|
assign CounterEvent[11] = DCacheAccess;
|
||||||
assign CounterEvent[12] = DCacheMiss;
|
assign CounterEvent[12] = DCacheMiss;
|
||||||
assign CounterEvent[`COUNTERS-1:13] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions
|
assign CounterEvent[`COUNTERS-1:13] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions
|
||||||
end
|
|
||||||
|
|
||||||
// Counter update and write logic
|
|
||||||
for (i = 0; i < `COUNTERS; i = i+1) begin
|
|
||||||
assign WriteHPMCOUNTERM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERBASE + i);
|
|
||||||
assign NextHPMCOUNTERM[i][`XLEN-1:0] = WriteHPMCOUNTERM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][`XLEN-1:0];
|
|
||||||
always_ff @(posedge clk) //, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
|
|
||||||
if (reset) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 0;
|
|
||||||
else HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERM[i];
|
|
||||||
|
|
||||||
if (`XLEN==32) begin // write high and low separately
|
|
||||||
logic [`COUNTERS-1:0] WriteHPMCOUNTERHM;
|
|
||||||
logic [`XLEN-1:0] NextHPMCOUNTERHM[`COUNTERS-1:0];
|
|
||||||
assign HPMCOUNTERPlusM[i] = {HPMCOUNTERH_REGW[i], HPMCOUNTER_REGW[i]} + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
|
|
||||||
assign WriteHPMCOUNTERHM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERHBASE + i);
|
|
||||||
assign NextHPMCOUNTERHM[i] = WriteHPMCOUNTERHM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][63:32];
|
|
||||||
always_ff @(posedge clk) //, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
|
|
||||||
if (reset) HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 0;
|
|
||||||
else HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERHM[i];
|
|
||||||
end else begin // XLEN=64; write entire register
|
|
||||||
assign HPMCOUNTERPlusM[i] = HPMCOUNTER_REGW[i] + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
// Read Counters, or cause excepiton if insufficient privilege in light of COUNTEREN flags
|
|
||||||
assign CounterNumM = CSRAdrM[4:0]; // which counter to read?
|
|
||||||
always_comb
|
|
||||||
if (PrivilegeModeW == `M_MODE |
|
|
||||||
MCOUNTEREN_REGW[CounterNumM] & (!`S_SUPPORTED | PrivilegeModeW == `S_MODE | SCOUNTEREN_REGW[CounterNumM])) begin
|
|
||||||
IllegalCSRCAccessM = 0;
|
|
||||||
if (`XLEN==64) begin // 64-bit counter reads
|
|
||||||
// Veri lator doesn't realize this only occurs for XLEN=64
|
|
||||||
/* verilator lint_off WIDTH */
|
|
||||||
if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT; // TIME register is a shadow of the memory-mapped MTIME from the CLINT
|
|
||||||
/* verilator lint_on WIDTH */
|
|
||||||
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
|
|
||||||
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
|
|
||||||
else begin
|
|
||||||
CSRCReadValM = 0;
|
|
||||||
IllegalCSRCAccessM = 1; // requested CSR doesn't exist
|
|
||||||
end
|
|
||||||
end else begin // 32-bit counter reads
|
|
||||||
// Veri lator doesn't realize this only occurs for XLEN=32
|
|
||||||
/* verilator lint_off WIDTH */
|
|
||||||
if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT[31:0];// TIME register is a shadow of the memory-mapped MTIME from the CLINT
|
|
||||||
else if (CSRAdrM == TIMEH) CSRCReadValM = MTIME_CLINT[63:32];
|
|
||||||
/* verilator lint_on WIDTH */
|
|
||||||
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
|
|
||||||
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
|
|
||||||
else if (CSRAdrM >= MHPMCOUNTERHBASE & CSRAdrM < MHPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM];
|
|
||||||
else if (CSRAdrM >= HPMCOUNTERHBASE & CSRAdrM < HPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM];
|
|
||||||
else begin
|
|
||||||
CSRCReadValM = 0;
|
|
||||||
IllegalCSRCAccessM = 1; // requested CSR doesn't exist
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
CSRCReadValM = 0;
|
|
||||||
IllegalCSRCAccessM = 1; // no privileges for this csr
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
assign CSRCReadValM = 0;
|
|
||||||
assign IllegalCSRCAccessM = 1; // counters aren't enabled
|
|
||||||
end
|
end
|
||||||
endgenerate
|
|
||||||
|
// Counter update and write logic
|
||||||
|
for (i = 0; i < `COUNTERS; i = i+1) begin:cntr
|
||||||
|
assign WriteHPMCOUNTERM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERBASE + i);
|
||||||
|
assign NextHPMCOUNTERM[i][`XLEN-1:0] = WriteHPMCOUNTERM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][`XLEN-1:0];
|
||||||
|
always_ff @(posedge clk) //, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
|
||||||
|
if (reset) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 0;
|
||||||
|
else HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERM[i];
|
||||||
|
|
||||||
|
if (`XLEN==32) begin // write high and low separately
|
||||||
|
logic [`COUNTERS-1:0] WriteHPMCOUNTERHM;
|
||||||
|
logic [`XLEN-1:0] NextHPMCOUNTERHM[`COUNTERS-1:0];
|
||||||
|
assign HPMCOUNTERPlusM[i] = {HPMCOUNTERH_REGW[i], HPMCOUNTER_REGW[i]} + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
|
||||||
|
assign WriteHPMCOUNTERHM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERHBASE + i);
|
||||||
|
assign NextHPMCOUNTERHM[i] = WriteHPMCOUNTERHM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][63:32];
|
||||||
|
always_ff @(posedge clk) //, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
|
||||||
|
if (reset) HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 0;
|
||||||
|
else HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERHM[i];
|
||||||
|
end else begin // XLEN=64; write entire register
|
||||||
|
assign HPMCOUNTERPlusM[i] = HPMCOUNTER_REGW[i] + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// Read Counters, or cause excepiton if insufficient privilege in light of COUNTEREN flags
|
||||||
|
assign CounterNumM = CSRAdrM[4:0]; // which counter to read?
|
||||||
|
always_comb
|
||||||
|
if (PrivilegeModeW == `M_MODE |
|
||||||
|
MCOUNTEREN_REGW[CounterNumM] & (!`S_SUPPORTED | PrivilegeModeW == `S_MODE | SCOUNTEREN_REGW[CounterNumM])) begin
|
||||||
|
IllegalCSRCAccessM = 0;
|
||||||
|
if (`XLEN==64) begin // 64-bit counter reads
|
||||||
|
// Veri lator doesn't realize this only occurs for XLEN=64
|
||||||
|
/* verilator lint_off WIDTH */
|
||||||
|
if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT; // TIME register is a shadow of the memory-mapped MTIME from the CLINT
|
||||||
|
/* verilator lint_on WIDTH */
|
||||||
|
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
|
||||||
|
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
|
||||||
|
else begin
|
||||||
|
CSRCReadValM = 0;
|
||||||
|
IllegalCSRCAccessM = 1; // requested CSR doesn't exist
|
||||||
|
end
|
||||||
|
end else begin // 32-bit counter reads
|
||||||
|
// Veri lator doesn't realize this only occurs for XLEN=32
|
||||||
|
/* verilator lint_off WIDTH */
|
||||||
|
if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT[31:0];// TIME register is a shadow of the memory-mapped MTIME from the CLINT
|
||||||
|
else if (CSRAdrM == TIMEH) CSRCReadValM = MTIME_CLINT[63:32];
|
||||||
|
/* verilator lint_on WIDTH */
|
||||||
|
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
|
||||||
|
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
|
||||||
|
else if (CSRAdrM >= MHPMCOUNTERHBASE & CSRAdrM < MHPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM];
|
||||||
|
else if (CSRAdrM >= HPMCOUNTERHBASE & CSRAdrM < HPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM];
|
||||||
|
else begin
|
||||||
|
CSRCReadValM = 0;
|
||||||
|
IllegalCSRCAccessM = 1; // requested CSR doesn't exist
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
CSRCReadValM = 0;
|
||||||
|
IllegalCSRCAccessM = 1; // no privileges for this csr
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
assign CSRCReadValM = 0;
|
||||||
|
assign IllegalCSRCAccessM = 1; // counters aren't enabled
|
||||||
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
// To Do:
|
// To Do:
|
||||||
|
@ -66,58 +66,54 @@ module csri #(parameter
|
|||||||
assign WriteSIPM = CSRSWriteM & (CSRAdrM == SIP) & ~StallW;
|
assign WriteSIPM = CSRSWriteM & (CSRAdrM == SIP) & ~StallW;
|
||||||
assign WriteSIEM = CSRSWriteM & (CSRAdrM == SIE) & ~StallW;
|
assign WriteSIEM = CSRSWriteM & (CSRAdrM == SIE) & ~StallW;
|
||||||
|
|
||||||
// Interrupt Pending and Enable Registers
|
// Interrupt Pending and Enable Registers
|
||||||
// MEIP, MTIP, MSIP are read-only
|
// MEIP, MTIP, MSIP are read-only
|
||||||
// SEIP, STIP, SSIP is writable in MIP if S mode exists
|
// SEIP, STIP, SSIP is writable in MIP if S mode exists
|
||||||
// SSIP is writable in SIP if S mode exists
|
// SSIP is writable in SIP if S mode exists
|
||||||
generate
|
if (`S_SUPPORTED) begin:mask
|
||||||
if (`S_SUPPORTED) begin:mask
|
assign MIP_WRITE_MASK = 12'h222; // SEIP, STIP, SSIP are writable in MIP (20210108-draft 3.1.9)
|
||||||
assign MIP_WRITE_MASK = 12'h222; // SEIP, STIP, SSIP are writable in MIP (20210108-draft 3.1.9)
|
assign SIP_WRITE_MASK = 12'h002; // SSIP is writable in SIP (privileged 20210108-draft 4.1.3)
|
||||||
assign SIP_WRITE_MASK = 12'h002; // SSIP is writable in SIP (privileged 20210108-draft 4.1.3)
|
end else begin:mask
|
||||||
end else begin:mask
|
assign MIP_WRITE_MASK = 12'h000;
|
||||||
assign MIP_WRITE_MASK = 12'h000;
|
assign SIP_WRITE_MASK = 12'h000;
|
||||||
assign SIP_WRITE_MASK = 12'h000;
|
end
|
||||||
end
|
always @(posedge clk) //, posedge reset) begin // *** I strongly feel that IntInM should go directly to IP_REGW -- Ben 9/7/21
|
||||||
always @(posedge clk) //, posedge reset) begin // *** I strongly feel that IntInM should go directly to IP_REGW -- Ben 9/7/21
|
if (reset) IP_REGW_writeable <= 10'b0;
|
||||||
if (reset) IP_REGW_writeable <= 10'b0;
|
else if (WriteMIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & MIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable
|
||||||
else if (WriteMIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & MIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable
|
else if (WriteSIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & SIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable
|
||||||
else if (WriteSIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & SIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable
|
|
||||||
// else if (WriteUIPM) IP_REGW = (CSRWriteValM & 12'hBBB) | (NextIPM & 12'h080); // MTIP unclearable
|
// else if (WriteUIPM) IP_REGW = (CSRWriteValM & 12'hBBB) | (NextIPM & 12'h080); // MTIP unclearable
|
||||||
else IP_REGW_writeable <= IP_REGW_writeable | IntInM[9:0]; // *** check this turns off interrupts properly even when MIDELEG changes
|
else IP_REGW_writeable <= IP_REGW_writeable | IntInM[9:0]; // *** check this turns off interrupts properly even when MIDELEG changes
|
||||||
always @(posedge clk) //, posedge reset) begin
|
always @(posedge clk) //, posedge reset) begin
|
||||||
if (reset) IE_REGW <= 12'b0;
|
if (reset) IE_REGW <= 12'b0;
|
||||||
else if (WriteMIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'hAAA); // MIE controls M and S fields
|
else if (WriteMIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'hAAA); // MIE controls M and S fields
|
||||||
else if (WriteSIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'h222) | (IE_REGW & 12'h888); // only S fields
|
else if (WriteSIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'h222) | (IE_REGW & 12'h888); // only S fields
|
||||||
// else if (WriteUIEM) IE_REGW = (CSRWriteValM & 12'h111) | (IE_REGW & 12'hAAA); // only U field
|
// else if (WriteUIEM) IE_REGW = (CSRWriteValM & 12'h111) | (IE_REGW & 12'hAAA); // only U field
|
||||||
endgenerate
|
|
||||||
|
|
||||||
// restricted views of registers
|
// restricted views of registers
|
||||||
generate
|
always_comb begin:regs
|
||||||
always_comb begin:regs
|
// Add MEIP read-only signal
|
||||||
// Add MEIP read-only signal
|
IP_REGW = {IntInM[11],1'b0,IP_REGW_writeable};
|
||||||
IP_REGW = {IntInM[11],1'b0,IP_REGW_writeable};
|
|
||||||
|
|
||||||
// Machine Mode
|
// Machine Mode
|
||||||
MIP_REGW = IP_REGW;
|
MIP_REGW = IP_REGW;
|
||||||
MIE_REGW = IE_REGW;
|
MIE_REGW = IE_REGW;
|
||||||
|
|
||||||
// Supervisor mode
|
// Supervisor mode
|
||||||
if (`S_SUPPORTED) begin
|
if (`S_SUPPORTED) begin
|
||||||
SIP_REGW = IP_REGW & MIDELEG_REGW[11:0] & 'h222; // only delegated interrupts visible
|
SIP_REGW = IP_REGW & MIDELEG_REGW[11:0] & 'h222; // only delegated interrupts visible
|
||||||
SIE_REGW = IE_REGW & MIDELEG_REGW[11:0] & 'h222;
|
SIE_REGW = IE_REGW & MIDELEG_REGW[11:0] & 'h222;
|
||||||
end else begin
|
end else begin
|
||||||
SIP_REGW = 12'b0;
|
SIP_REGW = 12'b0;
|
||||||
SIE_REGW = 12'b0;
|
SIE_REGW = 12'b0;
|
||||||
end
|
|
||||||
|
|
||||||
// User Modes iterrupts depricated
|
|
||||||
/*if (`U_SUPPORTED & `N_SUPPORTED) begin
|
|
||||||
UIP_REGW = IP_REGW & MIDELEG_REGW & SIDELEG_REGW & 'h111; // only delegated interrupts visible
|
|
||||||
UIE_REGW = IE_REGW & MIDELEG_REGW & SIDELEG_REGW & 'h111; // only delegated interrupts visible
|
|
||||||
end else begin
|
|
||||||
UIP_REGW = 12'b0;
|
|
||||||
UIE_REGW = 12'b0;
|
|
||||||
end */
|
|
||||||
end
|
end
|
||||||
endgenerate
|
|
||||||
|
// User Modes iterrupts depricated
|
||||||
|
/*if (`U_SUPPORTED & `N_SUPPORTED) begin
|
||||||
|
UIP_REGW = IP_REGW & MIDELEG_REGW & SIDELEG_REGW & 'h111; // only delegated interrupts visible
|
||||||
|
UIE_REGW = IE_REGW & MIDELEG_REGW & SIDELEG_REGW & 'h111; // only delegated interrupts visible
|
||||||
|
end else begin
|
||||||
|
UIP_REGW = 12'b0;
|
||||||
|
UIE_REGW = 12'b0;
|
||||||
|
end */
|
||||||
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -92,32 +92,30 @@ module csrm #(parameter
|
|||||||
|
|
||||||
// There are PMP_ENTRIES = 0, 16, or 64 PMPADDR registers, each of which has its own flop
|
// There are PMP_ENTRIES = 0, 16, or 64 PMPADDR registers, each of which has its own flop
|
||||||
genvar i;
|
genvar i;
|
||||||
generate
|
if (`PMP_ENTRIES > 0) begin:pmp
|
||||||
if (`PMP_ENTRIES > 0) begin:pmp
|
logic [`PMP_ENTRIES-1:0] WritePMPCFGM;
|
||||||
logic [`PMP_ENTRIES-1:0] WritePMPCFGM;
|
logic [`PMP_ENTRIES-1:0] WritePMPADDRM ;
|
||||||
logic [`PMP_ENTRIES-1:0] WritePMPADDRM ;
|
logic [`PMP_ENTRIES-1:0] ADDRLocked, CFGLocked;
|
||||||
logic [`PMP_ENTRIES-1:0] ADDRLocked, CFGLocked;
|
for(i=0; i<`PMP_ENTRIES; i++) begin
|
||||||
for(i=0; i<`PMP_ENTRIES; i++) begin
|
// when the lock bit is set, don't allow writes to the PMPCFG or PMPADDR
|
||||||
// when the lock bit is set, don't allow writes to the PMPCFG or PMPADDR
|
// also, when the lock bit of the next entry is set and the next entry is TOR, don't allow writes to this entry PMPADDR
|
||||||
// also, when the lock bit of the next entry is set and the next entry is TOR, don't allow writes to this entry PMPADDR
|
assign CFGLocked[i] = PMPCFG_ARRAY_REGW[i][7];
|
||||||
assign CFGLocked[i] = PMPCFG_ARRAY_REGW[i][7];
|
if (i == `PMP_ENTRIES-1)
|
||||||
if (i == `PMP_ENTRIES-1)
|
assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7];
|
||||||
assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7];
|
else
|
||||||
else
|
assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7] | (PMPCFG_ARRAY_REGW[i+1][7] & PMPCFG_ARRAY_REGW[i+1][4:3] == 2'b01);
|
||||||
assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7] | (PMPCFG_ARRAY_REGW[i+1][7] & PMPCFG_ARRAY_REGW[i+1][4:3] == 2'b01);
|
|
||||||
|
|
||||||
assign WritePMPADDRM[i] = (CSRMWriteM & (CSRAdrM == (PMPADDR0+i))) & ~StallW & ~ADDRLocked[i];
|
assign WritePMPADDRM[i] = (CSRMWriteM & (CSRAdrM == (PMPADDR0+i))) & ~StallW & ~ADDRLocked[i];
|
||||||
flopenr #(`XLEN) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM, PMPADDR_ARRAY_REGW[i]);
|
flopenr #(`XLEN) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM, PMPADDR_ARRAY_REGW[i]);
|
||||||
if (`XLEN==64) begin
|
if (`XLEN==64) begin
|
||||||
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & ~StallW & ~CFGLocked[i];
|
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & ~StallW & ~CFGLocked[i];
|
||||||
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%8)*8+7:(i%8)*8], PMPCFG_ARRAY_REGW[i]);
|
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%8)*8+7:(i%8)*8], PMPCFG_ARRAY_REGW[i]);
|
||||||
end else begin
|
end else begin
|
||||||
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & ~StallW & ~CFGLocked[i];
|
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & ~StallW & ~CFGLocked[i];
|
||||||
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%4)*8+7:(i%4)*8], PMPCFG_ARRAY_REGW[i]);
|
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%4)*8+7:(i%4)*8], PMPCFG_ARRAY_REGW[i]);
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endgenerate
|
end
|
||||||
|
|
||||||
localparam MISA_26 = (`MISA) & 32'h03ffffff;
|
localparam MISA_26 = (`MISA) & 32'h03ffffff;
|
||||||
|
|
||||||
@ -143,28 +141,24 @@ module csrm #(parameter
|
|||||||
|
|
||||||
// CSRs
|
// CSRs
|
||||||
flopenr #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, MTVEC_REGW); //busybear: changed reset value to 0
|
flopenr #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, MTVEC_REGW); //busybear: changed reset value to 0
|
||||||
generate
|
if (`S_SUPPORTED | (`U_SUPPORTED & `N_SUPPORTED)) begin:deleg // DELEG registers should exist
|
||||||
if (`S_SUPPORTED | (`U_SUPPORTED & `N_SUPPORTED)) begin:deleg // DELEG registers should exist
|
flopenr #(`XLEN) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK /*12'h7FF*/, MEDELEG_REGW);
|
||||||
flopenr #(`XLEN) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK /*12'h7FF*/, MEDELEG_REGW);
|
flopenr #(`XLEN) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM & MIDELEG_MASK /*12'h222*/, MIDELEG_REGW);
|
||||||
flopenr #(`XLEN) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM & MIDELEG_MASK /*12'h222*/, MIDELEG_REGW);
|
end else begin
|
||||||
end else begin
|
assign MEDELEG_REGW = 0;
|
||||||
assign MEDELEG_REGW = 0;
|
assign MIDELEG_REGW = 0;
|
||||||
assign MIDELEG_REGW = 0;
|
end
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
flopenr #(`XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW);
|
flopenr #(`XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW);
|
||||||
flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW);
|
flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW);
|
||||||
flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, MCAUSE_REGW);
|
flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, MCAUSE_REGW);
|
||||||
if(`QEMU) assign MTVAL_REGW = `XLEN'b0;
|
if(`QEMU) assign MTVAL_REGW = `XLEN'b0;
|
||||||
else flopenr #(`XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW);
|
else flopenr #(`XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW);
|
||||||
generate // *** needs comment about bit 1
|
if (`BUSYBEAR == 1) begin:counters // counter 1 (TIME) enable tied to 0 to match simulator***
|
||||||
if (`BUSYBEAR == 1) begin:counters
|
|
||||||
flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, MCOUNTEREN_REGW);
|
flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, MCOUNTEREN_REGW);
|
||||||
end else begin:counters
|
end else begin:counters
|
||||||
flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], MCOUNTEREN_REGW);
|
flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], MCOUNTEREN_REGW);
|
||||||
end
|
end
|
||||||
endgenerate
|
|
||||||
flopenr #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], MCOUNTINHIBIT_REGW);
|
flopenr #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], MCOUNTINHIBIT_REGW);
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,52 +49,50 @@ module csrn #(parameter
|
|||||||
);
|
);
|
||||||
|
|
||||||
// User mode CSRs below only needed when user mode traps are supported
|
// User mode CSRs below only needed when user mode traps are supported
|
||||||
generate
|
if (`N_SUPPORTED) begin:nmode // depricated; consider removing***
|
||||||
if (`N_SUPPORTED) begin:nmode
|
logic WriteUTVECM;
|
||||||
logic WriteUTVECM;
|
logic WriteUSCRATCHM, WriteUEPCM;
|
||||||
logic WriteUSCRATCHM, WriteUEPCM;
|
logic WriteUCAUSEM, WriteUTVALM;
|
||||||
logic WriteUCAUSEM, WriteUTVALM;
|
logic [`XLEN-1:0] UEDELEG_REGW, UIDELEG_REGW;
|
||||||
logic [`XLEN-1:0] UEDELEG_REGW, UIDELEG_REGW;
|
logic [`XLEN-1:0] USCRATCH_REGW, UCAUSE_REGW, UTVAL_REGW;
|
||||||
logic [`XLEN-1:0] USCRATCH_REGW, UCAUSE_REGW, UTVAL_REGW;
|
|
||||||
|
|
||||||
// Write enables
|
// Write enables
|
||||||
assign WriteUSTATUSM = CSRNWriteM & (CSRAdrM == USTATUS) & ~StallW;
|
assign WriteUSTATUSM = CSRNWriteM & (CSRAdrM == USTATUS) & ~StallW;
|
||||||
assign WriteUTVECM = CSRNWriteM & (CSRAdrM == UTVEC) & ~StallW;
|
assign WriteUTVECM = CSRNWriteM & (CSRAdrM == UTVEC) & ~StallW;
|
||||||
assign WriteUEPCM = UTrapM | (CSRNWriteM & (CSRAdrM == UEPC)) & ~StallW;
|
assign WriteUEPCM = UTrapM | (CSRNWriteM & (CSRAdrM == UEPC)) & ~StallW;
|
||||||
assign WriteUCAUSEM = UTrapM | (CSRNWriteM & (CSRAdrM == UCAUSE)) & ~StallW;
|
assign WriteUCAUSEM = UTrapM | (CSRNWriteM & (CSRAdrM == UCAUSE)) & ~StallW;
|
||||||
assign WriteUTVALM = UTrapM | (CSRNWriteM & (CSRAdrM == UTVAL)) & ~StallW;
|
assign WriteUTVALM = UTrapM | (CSRNWriteM & (CSRAdrM == UTVAL)) & ~StallW;
|
||||||
|
|
||||||
// CSRs
|
// CSRs
|
||||||
flopenl #(`XLEN) UTVECreg(clk, reset, WriteUTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, `RESET_VECTOR, UTVEC_REGW);
|
flopenl #(`XLEN) UTVECreg(clk, reset, WriteUTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, `RESET_VECTOR, UTVEC_REGW);
|
||||||
flopenr #(`XLEN) USCRATCHreg(clk, reset, WriteUSCRATCHM, CSRWriteValM, USCRATCH_REGW);
|
flopenr #(`XLEN) USCRATCHreg(clk, reset, WriteUSCRATCHM, CSRWriteValM, USCRATCH_REGW);
|
||||||
flopenr #(`XLEN) UEPCreg(clk, reset, WriteUEPCM, NextEPCM, UEPC_REGW);
|
flopenr #(`XLEN) UEPCreg(clk, reset, WriteUEPCM, NextEPCM, UEPC_REGW);
|
||||||
flopenr #(`XLEN) UCAUSEreg(clk, reset, WriteUCAUSEM, NextCauseM, UCAUSE_REGW);
|
flopenr #(`XLEN) UCAUSEreg(clk, reset, WriteUCAUSEM, NextCauseM, UCAUSE_REGW);
|
||||||
flopenr #(`XLEN) UTVALreg(clk, reset, WriteUTVALM, NextMtvalM, UTVAL_REGW);
|
flopenr #(`XLEN) UTVALreg(clk, reset, WriteUTVALM, NextMtvalM, UTVAL_REGW);
|
||||||
|
|
||||||
// CSR Reads
|
// CSR Reads
|
||||||
always_comb begin
|
always_comb begin
|
||||||
IllegalCSRNAccessM = 0;
|
IllegalCSRNAccessM = 0;
|
||||||
case (CSRAdrM)
|
case (CSRAdrM)
|
||||||
USTATUS: CSRNReadValM = USTATUS_REGW;
|
USTATUS: CSRNReadValM = USTATUS_REGW;
|
||||||
UTVEC: CSRNReadValM = UTVEC_REGW;
|
UTVEC: CSRNReadValM = UTVEC_REGW;
|
||||||
UIP: CSRNReadValM = {{(`XLEN-12){1'b0}}, UIP_REGW};
|
UIP: CSRNReadValM = {{(`XLEN-12){1'b0}}, UIP_REGW};
|
||||||
UIE: CSRNReadValM = {{(`XLEN-12){1'b0}}, UIE_REGW};
|
UIE: CSRNReadValM = {{(`XLEN-12){1'b0}}, UIE_REGW};
|
||||||
USCRATCH: CSRNReadValM = USCRATCH_REGW;
|
USCRATCH: CSRNReadValM = USCRATCH_REGW;
|
||||||
UEPC: CSRNReadValM = UEPC_REGW;
|
UEPC: CSRNReadValM = UEPC_REGW;
|
||||||
UCAUSE: CSRNReadValM = UCAUSE_REGW;
|
UCAUSE: CSRNReadValM = UCAUSE_REGW;
|
||||||
UTVAL: CSRNReadValM = UTVAL_REGW;
|
UTVAL: CSRNReadValM = UTVAL_REGW;
|
||||||
default: begin
|
default: begin
|
||||||
CSRNReadValM = 0;
|
CSRNReadValM = 0;
|
||||||
IllegalCSRNAccessM = 1;
|
IllegalCSRNAccessM = 1;
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
|
||||||
end else begin // if not supported
|
|
||||||
assign WriteUSTATUSM = 0;
|
|
||||||
assign CSRNReadValM = 0;
|
|
||||||
assign UEPC_REGW = 0;
|
|
||||||
assign UTVEC_REGW = 0;
|
|
||||||
assign IllegalCSRNAccessM = 1;
|
|
||||||
end
|
end
|
||||||
endgenerate
|
end else begin // if not supported
|
||||||
endmodule
|
assign WriteUSTATUSM = 0;
|
||||||
|
assign CSRNReadValM = 0;
|
||||||
|
assign UEPC_REGW = 0;
|
||||||
|
assign UTVEC_REGW = 0;
|
||||||
|
assign IllegalCSRNAccessM = 1;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
@ -69,89 +69,87 @@ module csrs #(parameter
|
|||||||
//logic [`XLEN-1:0] SEDELEG_MASK = ~(zero | 3'b111 << 9); // sedeleg[11:9] hardwired to zero per Privileged Spec 3.1.8
|
//logic [`XLEN-1:0] SEDELEG_MASK = ~(zero | 3'b111 << 9); // sedeleg[11:9] hardwired to zero per Privileged Spec 3.1.8
|
||||||
|
|
||||||
// Supervisor mode CSRs sometimes supported
|
// Supervisor mode CSRs sometimes supported
|
||||||
generate
|
if (`S_SUPPORTED) begin:csrs
|
||||||
if (`S_SUPPORTED) begin:csrs
|
logic WriteSTVECM;
|
||||||
logic WriteSTVECM;
|
logic WriteSSCRATCHM, WriteSEPCM;
|
||||||
logic WriteSSCRATCHM, WriteSEPCM;
|
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
|
||||||
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
|
logic [`XLEN-1:0] SSCRATCH_REGW, STVAL_REGW;
|
||||||
logic [`XLEN-1:0] SSCRATCH_REGW, STVAL_REGW;
|
(* mark_debug = "true" *) logic [`XLEN-1:0] SCAUSE_REGW;
|
||||||
(* mark_debug = "true" *) logic [`XLEN-1:0] SCAUSE_REGW;
|
|
||||||
|
|
||||||
assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS) & ~StallW;
|
assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS) & ~StallW;
|
||||||
assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC) & ~StallW;
|
assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC) & ~StallW;
|
||||||
assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH) & ~StallW;
|
assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH) & ~StallW;
|
||||||
assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC)) & ~StallW;
|
assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC)) & ~StallW;
|
||||||
assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE)) & ~StallW;
|
assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE)) & ~StallW;
|
||||||
assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)) & ~StallW;
|
assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)) & ~StallW;
|
||||||
assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == `M_MODE | ~STATUS_TVM) & ~StallW;
|
assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == `M_MODE | ~STATUS_TVM) & ~StallW;
|
||||||
assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN) & ~StallW;
|
assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN) & ~StallW;
|
||||||
|
|
||||||
// CSRs
|
// CSRs
|
||||||
flopenr #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW); //busybear: change reset to 0
|
flopenr #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW); //busybear: change reset to 0
|
||||||
flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW);
|
flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW);
|
||||||
flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW);
|
flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW);
|
||||||
flopenr #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, SCAUSE_REGW);
|
flopenr #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, SCAUSE_REGW);
|
||||||
flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW);
|
flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW);
|
||||||
if (`MEM_VIRTMEM)
|
if (`MEM_VIRTMEM)
|
||||||
flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW);
|
flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW);
|
||||||
else
|
else
|
||||||
assign SATP_REGW = 0; // hardwire to zero if virtual memory not supported
|
assign SATP_REGW = 0; // hardwire to zero if virtual memory not supported
|
||||||
if (`BUSYBEAR == 1) begin:scounteren
|
if (`BUSYBEAR == 1) begin:scounteren
|
||||||
flopenr #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, SCOUNTEREN_REGW);
|
flopenr #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, SCOUNTEREN_REGW);
|
||||||
end else if (`BUILDROOT == 1) begin:scounteren
|
end else if (`BUILDROOT == 1) begin:scounteren
|
||||||
flopenr #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW);
|
flopenr #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW);
|
||||||
end else begin:scounteren
|
end else begin:scounteren
|
||||||
flopens #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW);
|
flopens #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW);
|
||||||
end
|
end
|
||||||
if (`N_SUPPORTED) begin:nregs
|
if (`N_SUPPORTED) begin:nregs
|
||||||
logic WriteSEDELEGM, WriteSIDELEGM;
|
logic WriteSEDELEGM, WriteSIDELEGM;
|
||||||
assign WriteSEDELEGM = CSRSWriteM & (CSRAdrM == SEDELEG);
|
assign WriteSEDELEGM = CSRSWriteM & (CSRAdrM == SEDELEG);
|
||||||
assign WriteSIDELEGM = CSRSWriteM & (CSRAdrM == SIDELEG);
|
assign WriteSIDELEGM = CSRSWriteM & (CSRAdrM == SIDELEG);
|
||||||
flopenr #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK, SEDELEG_REGW);
|
flopenr #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK, SEDELEG_REGW);
|
||||||
flopenr #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, SIDELEG_REGW);
|
flopenr #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, SIDELEG_REGW);
|
||||||
end else begin
|
|
||||||
assign SEDELEG_REGW = 0;
|
|
||||||
assign SIDELEG_REGW = 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
// CSR Reads
|
|
||||||
always_comb begin:csrr
|
|
||||||
IllegalCSRSAccessM = !(`N_SUPPORTED) & (CSRAdrM == SEDELEG | CSRAdrM == SIDELEG); // trap on DELEG register access when no N-mode
|
|
||||||
case (CSRAdrM)
|
|
||||||
SSTATUS: CSRSReadValM = SSTATUS_REGW;
|
|
||||||
STVEC: CSRSReadValM = STVEC_REGW;
|
|
||||||
// SIDELEG: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIDELEG_REGW};
|
|
||||||
// SEDELEG: CSRSReadValM = {{(`XLEN-12){1'b0}}, SEDELEG_REGW};
|
|
||||||
SIDELEG: CSRSReadValM = SIDELEG_REGW;
|
|
||||||
SEDELEG: CSRSReadValM = SEDELEG_REGW;
|
|
||||||
SIP: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIP_REGW};
|
|
||||||
SIE: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIE_REGW};
|
|
||||||
SSCRATCH: CSRSReadValM = SSCRATCH_REGW;
|
|
||||||
SEPC: CSRSReadValM = SEPC_REGW;
|
|
||||||
SCAUSE: CSRSReadValM = SCAUSE_REGW;
|
|
||||||
STVAL: CSRSReadValM = STVAL_REGW;
|
|
||||||
SATP: if (`MEM_VIRTMEM & (PrivilegeModeW == `M_MODE | ~STATUS_TVM)) CSRSReadValM = SATP_REGW;
|
|
||||||
else begin
|
|
||||||
CSRSReadValM = 0;
|
|
||||||
if (PrivilegeModeW == `S_MODE & STATUS_TVM) IllegalCSRSAccessM = 1;
|
|
||||||
end
|
|
||||||
SCOUNTEREN:CSRSReadValM = {{(`XLEN-32){1'b0}}, SCOUNTEREN_REGW};
|
|
||||||
default: begin
|
|
||||||
CSRSReadValM = 0;
|
|
||||||
IllegalCSRSAccessM = 1;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end else begin
|
end else begin
|
||||||
assign WriteSSTATUSM = 0;
|
|
||||||
assign CSRSReadValM = 0;
|
|
||||||
assign SEPC_REGW = 0;
|
|
||||||
assign STVEC_REGW = 0;
|
|
||||||
assign SEDELEG_REGW = 0;
|
assign SEDELEG_REGW = 0;
|
||||||
assign SIDELEG_REGW = 0;
|
assign SIDELEG_REGW = 0;
|
||||||
assign SCOUNTEREN_REGW = 0;
|
|
||||||
assign SATP_REGW = 0;
|
|
||||||
assign IllegalCSRSAccessM = 1;
|
|
||||||
end
|
end
|
||||||
endgenerate
|
|
||||||
|
// CSR Reads
|
||||||
|
always_comb begin:csrr
|
||||||
|
IllegalCSRSAccessM = !(`N_SUPPORTED) & (CSRAdrM == SEDELEG | CSRAdrM == SIDELEG); // trap on DELEG register access when no N-mode
|
||||||
|
case (CSRAdrM)
|
||||||
|
SSTATUS: CSRSReadValM = SSTATUS_REGW;
|
||||||
|
STVEC: CSRSReadValM = STVEC_REGW;
|
||||||
|
// SIDELEG: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIDELEG_REGW};
|
||||||
|
// SEDELEG: CSRSReadValM = {{(`XLEN-12){1'b0}}, SEDELEG_REGW};
|
||||||
|
SIDELEG: CSRSReadValM = SIDELEG_REGW;
|
||||||
|
SEDELEG: CSRSReadValM = SEDELEG_REGW;
|
||||||
|
SIP: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIP_REGW};
|
||||||
|
SIE: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIE_REGW};
|
||||||
|
SSCRATCH: CSRSReadValM = SSCRATCH_REGW;
|
||||||
|
SEPC: CSRSReadValM = SEPC_REGW;
|
||||||
|
SCAUSE: CSRSReadValM = SCAUSE_REGW;
|
||||||
|
STVAL: CSRSReadValM = STVAL_REGW;
|
||||||
|
SATP: if (`MEM_VIRTMEM & (PrivilegeModeW == `M_MODE | ~STATUS_TVM)) CSRSReadValM = SATP_REGW;
|
||||||
|
else begin
|
||||||
|
CSRSReadValM = 0;
|
||||||
|
if (PrivilegeModeW == `S_MODE & STATUS_TVM) IllegalCSRSAccessM = 1;
|
||||||
|
end
|
||||||
|
SCOUNTEREN:CSRSReadValM = {{(`XLEN-32){1'b0}}, SCOUNTEREN_REGW};
|
||||||
|
default: begin
|
||||||
|
CSRSReadValM = 0;
|
||||||
|
IllegalCSRSAccessM = 1;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
assign WriteSSTATUSM = 0;
|
||||||
|
assign CSRSReadValM = 0;
|
||||||
|
assign SEPC_REGW = 0;
|
||||||
|
assign STVEC_REGW = 0;
|
||||||
|
assign SEDELEG_REGW = 0;
|
||||||
|
assign SIDELEG_REGW = 0;
|
||||||
|
assign SCOUNTEREN_REGW = 0;
|
||||||
|
assign SATP_REGW = 0;
|
||||||
|
assign IllegalCSRSAccessM = 1;
|
||||||
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -50,54 +50,50 @@ module csrsr (
|
|||||||
// See Privileged Spec Section 3.1.6
|
// See Privileged Spec Section 3.1.6
|
||||||
// Lower privilege status registers are a subset of the full status register
|
// Lower privilege status registers are a subset of the full status register
|
||||||
// *** consider adding MBE, SBE, UBE fields later from 20210108 draft spec
|
// *** consider adding MBE, SBE, UBE fields later from 20210108 draft spec
|
||||||
generate
|
if (`XLEN==64) begin: csrsr64 // RV64
|
||||||
if (`XLEN==64) begin: csrsr64 // RV64
|
assign MSTATUS_REGW = {STATUS_SD, 27'b0, STATUS_SXL, STATUS_UXL, 9'b0,
|
||||||
assign MSTATUS_REGW = {STATUS_SD, 27'b0, STATUS_SXL, STATUS_UXL, 9'b0,
|
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||||
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0,
|
||||||
STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0,
|
STATUS_SPP, STATUS_MPIE, 1'b0, STATUS_SPIE, STATUS_UPIE,
|
||||||
STATUS_SPP, STATUS_MPIE, 1'b0, STATUS_SPIE, STATUS_UPIE,
|
STATUS_MIE, 1'b0, STATUS_SIE, STATUS_UIE};
|
||||||
STATUS_MIE, 1'b0, STATUS_SIE, STATUS_UIE};
|
assign SSTATUS_REGW = {STATUS_SD, /*27'b0, */ 29'b0, /*STATUS_SXL, */ STATUS_UXL, /*9'b0, */ 12'b0,
|
||||||
assign SSTATUS_REGW = {STATUS_SD, /*27'b0, */ 29'b0, /*STATUS_SXL, */ STATUS_UXL, /*9'b0, */ 12'b0,
|
/*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0,
|
||||||
/*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0,
|
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
|
||||||
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
|
STATUS_SPP, /*STATUS_MPIE, 1'b0*/ 2'b0, STATUS_SPIE, STATUS_UPIE,
|
||||||
STATUS_SPP, /*STATUS_MPIE, 1'b0*/ 2'b0, STATUS_SPIE, STATUS_UPIE,
|
/*STATUS_MIE, 1'b0*/ 2'b0, STATUS_SIE, STATUS_UIE};
|
||||||
/*STATUS_MIE, 1'b0*/ 2'b0, STATUS_SIE, STATUS_UIE};
|
assign USTATUS_REGW = {/*STATUS_SD, */ 59'b0, /*STATUS_SXL, STATUS_UXL, 9'b0, */
|
||||||
assign USTATUS_REGW = {/*STATUS_SD, */ 59'b0, /*STATUS_SXL, STATUS_UXL, 9'b0, */
|
/*STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, , 1'b0,*/
|
||||||
/*STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, , 1'b0,*/
|
/* STATUS_XS, STATUS_FS, /*STATUS_MPP, 8'b0, */
|
||||||
/* STATUS_XS, STATUS_FS, /*STATUS_MPP, 8'b0, */
|
/*STATUS_SPP, STATUS_MPIE, 1'b0 2'b0, STATUS_SPIE,*/ STATUS_UPIE,
|
||||||
/*STATUS_SPP, STATUS_MPIE, 1'b0 2'b0, STATUS_SPIE,*/ STATUS_UPIE,
|
/*STATUS_MIE, 1'b0*/ 3'b0, /*STATUS_SIE, */STATUS_UIE};
|
||||||
/*STATUS_MIE, 1'b0*/ 3'b0, /*STATUS_SIE, */STATUS_UIE};
|
end else begin: csrsr32 // RV32
|
||||||
end else begin: csrsr32 // RV32
|
assign MSTATUS_REGW = {STATUS_SD, 8'b0,
|
||||||
assign MSTATUS_REGW = {STATUS_SD, 8'b0,
|
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||||
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0,
|
||||||
STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0,
|
STATUS_SPP, STATUS_MPIE, 1'b0, STATUS_SPIE, STATUS_UPIE, STATUS_MIE, 1'b0, STATUS_SIE, STATUS_UIE};
|
||||||
STATUS_SPP, STATUS_MPIE, 1'b0, STATUS_SPIE, STATUS_UPIE, STATUS_MIE, 1'b0, STATUS_SIE, STATUS_UIE};
|
assign SSTATUS_REGW = {STATUS_SD, 11'b0,
|
||||||
assign SSTATUS_REGW = {STATUS_SD, 11'b0,
|
/*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0,
|
||||||
/*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0,
|
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
|
||||||
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
|
STATUS_SPP, /*STATUS_MPIE, 1'b0*/ 2'b0, STATUS_SPIE, STATUS_UPIE,
|
||||||
STATUS_SPP, /*STATUS_MPIE, 1'b0*/ 2'b0, STATUS_SPIE, STATUS_UPIE,
|
/*STATUS_MIE, 1'b0*/ 2'b0, STATUS_SIE, STATUS_UIE};
|
||||||
/*STATUS_MIE, 1'b0*/ 2'b0, STATUS_SIE, STATUS_UIE};
|
assign USTATUS_REGW = {/*STATUS_SD, */ 27'b0, /*STATUS_SXL, STATUS_UXL, 9'b0, */
|
||||||
assign USTATUS_REGW = {/*STATUS_SD, */ 27'b0, /*STATUS_SXL, STATUS_UXL, 9'b0, */
|
/*STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, , 1'b0,*/
|
||||||
/*STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, , 1'b0,*/
|
/*STATUS_XS, STATUS_FS, STATUS_MPP, 8'b0, */
|
||||||
/*STATUS_XS, STATUS_FS, STATUS_MPP, 8'b0, */
|
/*STATUS_SPP, STATUS_MPIE, 1'b0 2'b0, STATUS_SPIE,*/ STATUS_UPIE,
|
||||||
/*STATUS_SPP, STATUS_MPIE, 1'b0 2'b0, STATUS_SPIE,*/ STATUS_UPIE,
|
/*STATUS_MIE, 1'b0*/ 3'b0, /*STATUS_SIE, */STATUS_UIE};
|
||||||
/*STATUS_MIE, 1'b0*/ 3'b0, /*STATUS_SIE, */STATUS_UIE};
|
end
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
// harwired STATUS bits
|
// harwired STATUS bits
|
||||||
generate
|
assign STATUS_TSR = `S_SUPPORTED & STATUS_TSR_INT; // override reigster with 0 if supervisor mode not supported
|
||||||
assign STATUS_TSR = `S_SUPPORTED & STATUS_TSR_INT; // override reigster with 0 if supervisor mode not supported
|
assign STATUS_TW = (`S_SUPPORTED | `U_SUPPORTED) & STATUS_TW_INT; // override reigster with 0 if only machine mode supported
|
||||||
assign STATUS_TW = (`S_SUPPORTED | `U_SUPPORTED) & STATUS_TW_INT; // override reigster with 0 if only machine mode supported
|
assign STATUS_TVM = `S_SUPPORTED & STATUS_TVM_INT; // override reigster with 0 if supervisor mode not supported
|
||||||
assign STATUS_TVM = `S_SUPPORTED & STATUS_TVM_INT; // override reigster with 0 if supervisor mode not supported
|
assign STATUS_MXR = `S_SUPPORTED & STATUS_MXR_INT; // override reigster with 0 if supervisor mode not supported
|
||||||
assign STATUS_MXR = `S_SUPPORTED & STATUS_MXR_INT; // override reigster with 0 if supervisor mode not supported
|
// SXL and UXL bits only matter for RV64. Set to 10 for RV64 if mode is supported, or 0 if not
|
||||||
// SXL and UXL bits only matter for RV64. Set to 10 for RV64 if mode is supported, or 0 if not
|
assign STATUS_SXL = `S_SUPPORTED & ~`QEMU ? 2'b10 : 2'b00; // 10 if supervisor mode supported
|
||||||
assign STATUS_SXL = `S_SUPPORTED & ~`QEMU ? 2'b10 : 2'b00; // 10 if supervisor mode supported
|
assign STATUS_UXL = `U_SUPPORTED & ~`QEMU ? 2'b10 : 2'b00; // 10 if user mode supported
|
||||||
assign STATUS_UXL = `U_SUPPORTED & ~`QEMU ? 2'b10 : 2'b00; // 10 if user mode supported
|
assign STATUS_SUM = `S_SUPPORTED & `MEM_VIRTMEM & STATUS_SUM_INT; // override reigster with 0 if supervisor mode not supported
|
||||||
assign STATUS_SUM = `S_SUPPORTED & `MEM_VIRTMEM & STATUS_SUM_INT; // override reigster with 0 if supervisor mode not supported
|
assign STATUS_MPRV = `U_SUPPORTED & STATUS_MPRV_INT; // override with 0 if user mode not supported
|
||||||
assign STATUS_MPRV = `U_SUPPORTED & STATUS_MPRV_INT; // override with 0 if user mode not supported
|
assign STATUS_FS = (`S_SUPPORTED & (`F_SUPPORTED | `D_SUPPORTED)) ? STATUS_FS_INT : 2'b00; // off if no FP
|
||||||
assign STATUS_FS = (`S_SUPPORTED & (`F_SUPPORTED | `D_SUPPORTED)) ? STATUS_FS_INT : 2'b00; // off if no FP
|
|
||||||
endgenerate
|
|
||||||
assign STATUS_SD = (STATUS_FS == 2'b11) | (STATUS_XS == 2'b11); // dirty state logic
|
assign STATUS_SD = (STATUS_FS == 2'b11) | (STATUS_XS == 2'b11); // dirty state logic
|
||||||
assign STATUS_XS = 2'b00; // No additional user-mode state to be dirty
|
assign STATUS_XS = 2'b00; // No additional user-mode state to be dirty
|
||||||
|
|
||||||
|
@ -44,42 +44,40 @@ module csru #(parameter
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Floating Point CSRs in User Mode only needed if Floating Point is supported
|
// Floating Point CSRs in User Mode only needed if Floating Point is supported
|
||||||
generate
|
if (`F_SUPPORTED | `D_SUPPORTED) begin:csru
|
||||||
if (`F_SUPPORTED | `D_SUPPORTED) begin:csru
|
logic [4:0] FFLAGS_REGW;
|
||||||
logic [4:0] FFLAGS_REGW;
|
logic [2:0] NextFRMM;
|
||||||
logic [2:0] NextFRMM;
|
logic [4:0] NextFFLAGSM;
|
||||||
logic [4:0] NextFFLAGSM;
|
|
||||||
|
|
||||||
// Write enables
|
// Write enables
|
||||||
//assign WriteFCSRM = CSRUWriteM & (CSRAdrM == FCSR) & ~StallW;
|
//assign WriteFCSRM = CSRUWriteM & (CSRAdrM == FCSR) & ~StallW;
|
||||||
assign WriteFRMM = (CSRUWriteM & (CSRAdrM == FRM | CSRAdrM == FCSR)) & ~StallW;
|
assign WriteFRMM = (CSRUWriteM & (CSRAdrM == FRM | CSRAdrM == FCSR)) & ~StallW;
|
||||||
assign WriteFFLAGSM = (CSRUWriteM & (CSRAdrM == FFLAGS | CSRAdrM == FCSR)) & ~StallW;
|
assign WriteFFLAGSM = (CSRUWriteM & (CSRAdrM == FFLAGS | CSRAdrM == FCSR)) & ~StallW;
|
||||||
|
|
||||||
// Write Values
|
// Write Values
|
||||||
assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0];
|
assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0];
|
||||||
assign NextFFLAGSM = WriteFFLAGSM ? CSRWriteValM[4:0] : FFLAGS_REGW | SetFflagsM;
|
assign NextFFLAGSM = WriteFFLAGSM ? CSRWriteValM[4:0] : FFLAGS_REGW | SetFflagsM;
|
||||||
|
|
||||||
// CSRs
|
// CSRs
|
||||||
flopenr #(3) FRMreg(clk, reset, WriteFRMM, NextFRMM, FRM_REGW);
|
flopenr #(3) FRMreg(clk, reset, WriteFRMM, NextFRMM, FRM_REGW);
|
||||||
flopr #(5) FFLAGSreg(clk, reset, NextFFLAGSM, FFLAGS_REGW);
|
flopr #(5) FFLAGSreg(clk, reset, NextFFLAGSM, FFLAGS_REGW);
|
||||||
|
|
||||||
// CSR Reads
|
// CSR Reads
|
||||||
always_comb begin
|
always_comb begin
|
||||||
IllegalCSRUAccessM = 0;
|
IllegalCSRUAccessM = 0;
|
||||||
case (CSRAdrM)
|
case (CSRAdrM)
|
||||||
FFLAGS: CSRUReadValM = {{(`XLEN-5){1'b0}}, FFLAGS_REGW};
|
FFLAGS: CSRUReadValM = {{(`XLEN-5){1'b0}}, FFLAGS_REGW};
|
||||||
FRM: CSRUReadValM = {{(`XLEN-3){1'b0}}, FRM_REGW};
|
FRM: CSRUReadValM = {{(`XLEN-3){1'b0}}, FRM_REGW};
|
||||||
FCSR: CSRUReadValM = {{(`XLEN-8){1'b0}}, FRM_REGW, FFLAGS_REGW};
|
FCSR: CSRUReadValM = {{(`XLEN-8){1'b0}}, FRM_REGW, FFLAGS_REGW};
|
||||||
default: begin
|
default: begin
|
||||||
CSRUReadValM = 0;
|
CSRUReadValM = 0;
|
||||||
IllegalCSRUAccessM = 1;
|
IllegalCSRUAccessM = 1;
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
|
||||||
end else begin // if not supported
|
|
||||||
assign FRM_REGW = 0;
|
|
||||||
assign CSRUReadValM = 0;
|
|
||||||
assign IllegalCSRUAccessM = 1;
|
|
||||||
end
|
end
|
||||||
endgenerate
|
end else begin // if not supported
|
||||||
|
assign FRM_REGW = 0;
|
||||||
|
assign CSRUReadValM = 0;
|
||||||
|
assign IllegalCSRUAccessM = 1;
|
||||||
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -103,18 +103,16 @@ module trap (
|
|||||||
// > implemented without a hardware adder circuit.
|
// > implemented without a hardware adder circuit.
|
||||||
// For example, we could require m/stvec be aligned on 7 bits to let us replace the adder directly below with
|
// For example, we could require m/stvec be aligned on 7 bits to let us replace the adder directly below with
|
||||||
// [untested] PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:7], CauseM[3:0], 4'b0000}
|
// [untested] PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:7], CauseM[3:0], 4'b0000}
|
||||||
generate
|
if(`VECTORED_INTERRUPTS_SUPPORTED) begin:vec
|
||||||
if(`VECTORED_INTERRUPTS_SUPPORTED) begin:vec
|
always_comb
|
||||||
always_comb
|
if (PrivilegedTrapVector[1:0] == 2'b01 & CauseM[`XLEN-1] == 1)
|
||||||
if (PrivilegedTrapVector[1:0] == 2'b01 & CauseM[`XLEN-1] == 1)
|
PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2] + {CauseM[`XLEN-5:0], 2'b00}, 2'b00};
|
||||||
PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2] + {CauseM[`XLEN-5:0], 2'b00}, 2'b00};
|
else
|
||||||
else
|
PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00};
|
||||||
PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00};
|
end
|
||||||
end
|
else begin
|
||||||
else begin
|
assign PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00};
|
||||||
assign PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00};
|
end
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
always_comb
|
always_comb
|
||||||
if (mretM) PrivilegedNextPCM = MEPC_REGW;
|
if (mretM) PrivilegedNextPCM = MEPC_REGW;
|
||||||
|
@ -55,12 +55,8 @@ module clint (
|
|||||||
assign HREADYCLINT = 1'b1; // *** needs to depend on DONE during accesses
|
assign HREADYCLINT = 1'b1; // *** needs to depend on DONE during accesses
|
||||||
|
|
||||||
// word aligned reads
|
// word aligned reads
|
||||||
generate
|
if (`XLEN==64) assign #2 entry = {HADDR[15:3], 3'b000};
|
||||||
if (`XLEN==64)
|
else assign #2 entry = {HADDR[15:2], 2'b00};
|
||||||
assign #2 entry = {HADDR[15:3], 3'b000};
|
|
||||||
else
|
|
||||||
assign #2 entry = {HADDR[15:2], 2'b00};
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
// DH 2/20/21: Eventually allow MTIME to run off a separate clock
|
// DH 2/20/21: Eventually allow MTIME to run off a separate clock
|
||||||
// This will require synchronizing MTIME to the system clock
|
// This will require synchronizing MTIME to the system clock
|
||||||
@ -69,74 +65,72 @@ module clint (
|
|||||||
// Use req and ack signals synchronized across the clock domains.
|
// Use req and ack signals synchronized across the clock domains.
|
||||||
|
|
||||||
// register access
|
// register access
|
||||||
generate
|
if (`XLEN==64) begin:clint // 64-bit
|
||||||
if (`XLEN==64) begin:clint // 64-bit
|
always @(posedge HCLK) begin
|
||||||
always @(posedge HCLK) begin
|
case(entry)
|
||||||
case(entry)
|
16'h0000: HREADCLINT <= {63'b0, MSIP};
|
||||||
16'h0000: HREADCLINT <= {63'b0, MSIP};
|
16'h4000: HREADCLINT <= MTIMECMP;
|
||||||
16'h4000: HREADCLINT <= MTIMECMP;
|
16'hBFF8: HREADCLINT <= MTIME;
|
||||||
16'hBFF8: HREADCLINT <= MTIME;
|
default: HREADCLINT <= 0;
|
||||||
default: HREADCLINT <= 0;
|
endcase
|
||||||
endcase
|
end
|
||||||
|
always_ff @(posedge HCLK or negedge HRESETn)
|
||||||
|
if (~HRESETn) begin
|
||||||
|
MSIP <= 0;
|
||||||
|
MTIMECMP <= 0;
|
||||||
|
// MTIMECMP is not reset
|
||||||
|
end else if (memwrite) begin
|
||||||
|
if (entryd == 16'h0000) MSIP <= HWDATA[0];
|
||||||
|
if (entryd == 16'h4000) MTIMECMP <= HWDATA;
|
||||||
end
|
end
|
||||||
always_ff @(posedge HCLK or negedge HRESETn)
|
|
||||||
if (~HRESETn) begin
|
|
||||||
MSIP <= 0;
|
|
||||||
MTIMECMP <= 0;
|
|
||||||
// MTIMECMP is not reset
|
|
||||||
end else if (memwrite) begin
|
|
||||||
if (entryd == 16'h0000) MSIP <= HWDATA[0];
|
|
||||||
if (entryd == 16'h4000) MTIMECMP <= HWDATA;
|
|
||||||
end
|
|
||||||
|
|
||||||
// eventually replace MTIME logic below with timereg
|
|
||||||
// timereg tr(HCLK, HRESETn, TIMECLK, memwrite & (entryd==16'hBFF8), 1'b0, HWDATA, MTIME, done);
|
|
||||||
|
|
||||||
always_ff @(posedge HCLK or negedge HRESETn)
|
|
||||||
if (~HRESETn) begin
|
|
||||||
MTIME <= 0;
|
|
||||||
// MTIMECMP is not reset
|
|
||||||
end else if (memwrite & entryd == 16'hBFF8) begin
|
|
||||||
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
|
|
||||||
MTIME <= HWDATA;
|
|
||||||
end else MTIME <= MTIME + 1;
|
|
||||||
end else begin:clint // 32-bit
|
|
||||||
always @(posedge HCLK) begin
|
|
||||||
case(entry)
|
|
||||||
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 HCLK or negedge HRESETn)
|
|
||||||
if (~HRESETn) begin
|
|
||||||
MSIP <= 0;
|
|
||||||
MTIMECMP <= 0;
|
|
||||||
// MTIMECMP is not reset ***?
|
|
||||||
end else if (memwrite) begin
|
|
||||||
if (entryd == 16'h0000) MSIP <= HWDATA[0];
|
|
||||||
if (entryd == 16'h4000) MTIMECMP[31:0] <= HWDATA;
|
|
||||||
if (entryd == 16'h4004) MTIMECMP[63:32] <= HWDATA;
|
|
||||||
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
|
|
||||||
end
|
|
||||||
|
|
||||||
// eventually replace MTIME logic below with timereg
|
// eventually replace MTIME logic below with timereg
|
||||||
// timereg tr(HCLK, HRESETn, TIMECLK, memwrite & (entryd==16'hBFF8), memwrite & (entryd == 16'hBFFC), HWDATA, MTIME, done);
|
// timereg tr(HCLK, HRESETn, TIMECLK, memwrite & (entryd==16'hBFF8), 1'b0, HWDATA, MTIME, done);
|
||||||
always_ff @(posedge HCLK or negedge HRESETn)
|
|
||||||
if (~HRESETn) begin
|
always_ff @(posedge HCLK or negedge HRESETn)
|
||||||
MTIME <= 0;
|
if (~HRESETn) begin
|
||||||
// MTIMECMP is not reset
|
MTIME <= 0;
|
||||||
end else if (memwrite & (entryd == 16'hBFF8)) begin
|
// MTIMECMP is not reset
|
||||||
MTIME[31:0] <= HWDATA;
|
end else if (memwrite & entryd == 16'hBFF8) begin
|
||||||
end else if (memwrite & (entryd == 16'hBFFC)) begin
|
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
|
||||||
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
|
MTIME <= HWDATA;
|
||||||
MTIME[63:32]<= HWDATA;
|
end else MTIME <= MTIME + 1;
|
||||||
end else MTIME <= MTIME + 1;
|
end else begin:clint // 32-bit
|
||||||
|
always @(posedge HCLK) begin
|
||||||
|
case(entry)
|
||||||
|
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
|
end
|
||||||
endgenerate
|
always_ff @(posedge HCLK or negedge HRESETn)
|
||||||
|
if (~HRESETn) begin
|
||||||
|
MSIP <= 0;
|
||||||
|
MTIMECMP <= 0;
|
||||||
|
// MTIMECMP is not reset ***?
|
||||||
|
end else if (memwrite) begin
|
||||||
|
if (entryd == 16'h0000) MSIP <= HWDATA[0];
|
||||||
|
if (entryd == 16'h4000) MTIMECMP[31:0] <= HWDATA;
|
||||||
|
if (entryd == 16'h4004) MTIMECMP[63:32] <= HWDATA;
|
||||||
|
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
|
||||||
|
end
|
||||||
|
|
||||||
|
// eventually replace MTIME logic below with timereg
|
||||||
|
// timereg tr(HCLK, HRESETn, TIMECLK, memwrite & (entryd==16'hBFF8), memwrite & (entryd == 16'hBFFC), HWDATA, MTIME, done);
|
||||||
|
always_ff @(posedge HCLK or negedge HRESETn)
|
||||||
|
if (~HRESETn) begin
|
||||||
|
MTIME <= 0;
|
||||||
|
// MTIMECMP is not reset
|
||||||
|
end else if (memwrite & (entryd == 16'hBFF8)) begin
|
||||||
|
MTIME[31:0] <= HWDATA;
|
||||||
|
end else if (memwrite & (entryd == 16'hBFFC)) begin
|
||||||
|
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
|
||||||
|
MTIME[63:32]<= HWDATA;
|
||||||
|
end else MTIME <= MTIME + 1;
|
||||||
|
end
|
||||||
|
|
||||||
// Software interrupt when MSIP is set
|
// Software interrupt when MSIP is set
|
||||||
assign SwIntM = MSIP;
|
assign SwIntM = MSIP;
|
||||||
@ -234,13 +228,9 @@ module graytobinary #(parameter N = `XLEN) (
|
|||||||
|
|
||||||
// B[N-1] = G[N-1]; B[i] = G[i] ^ B[i+1] for 0 <= i < N-1
|
// B[N-1] = G[N-1]; B[i] = G[i] ^ B[i+1] for 0 <= i < N-1
|
||||||
// requires rippling through N-1 XOR gates
|
// requires rippling through N-1 XOR gates
|
||||||
generate
|
genvar i;
|
||||||
begin
|
assign b[N-1] = g[N-1];
|
||||||
genvar i;
|
for (i=N-2; i >= 0; i--) begin:g2b
|
||||||
assign b[N-1] = g[N-1];
|
assign b[i] = g[i] ^ b[i+1];
|
||||||
for (i=N-2; i >= 0; i--) begin:g2b
|
|
||||||
assign b[i] = g[i] ^ b[i+1];
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
endgenerate
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -61,23 +61,13 @@ module gpio (
|
|||||||
// account for subword read/write circuitry
|
// account for subword read/write circuitry
|
||||||
// -- Note GPIO registers are 32 bits no matter what; access them with LW SW.
|
// -- 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")
|
// (At least that's what I think when FE310 spec says "only naturally aligned 32-bit accesses are supported")
|
||||||
generate
|
if (`XLEN == 64) begin:gpio
|
||||||
if (`XLEN == 64) begin:gpio
|
assign Din = entryd[2] ? HWDATA[63:32] : HWDATA[31:0];
|
||||||
always_comb
|
assign HREADGPIO = entryd[2] ? {Dout,32'b0} : {32'b0,Dout};
|
||||||
if (entryd[2]) begin
|
end else begin:gpio // 32-bit
|
||||||
Din = HWDATA[63:32];
|
assign Din = HWDATA[31:0];
|
||||||
HREADGPIO = {Dout,32'b0};
|
assign HREADGPIO = Dout;
|
||||||
end else begin
|
end
|
||||||
Din = HWDATA[31:0];
|
|
||||||
HREADGPIO = {32'b0,Dout};
|
|
||||||
end
|
|
||||||
end else begin:gpio // 32-bit
|
|
||||||
always_comb begin
|
|
||||||
Din = HWDATA[31:0];
|
|
||||||
HREADGPIO = Dout;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
// register access
|
// register access
|
||||||
always_ff @(posedge HCLK, negedge HRESETn) begin
|
always_ff @(posedge HCLK, negedge HRESETn) begin
|
||||||
|
Loading…
Reference in New Issue
Block a user