696 lines
19 KiB
Systemverilog
696 lines
19 KiB
Systemverilog
// SPDX-License-Identifier: Apache-2.0
|
|
// Copyright 2020 Western Digital Corporation or its affiliates.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// all flops call the rvdff flop
|
|
|
|
|
|
module rvdff #(
|
|
parameter WIDTH = 1,
|
|
SHORT = 0
|
|
) (
|
|
input logic [WIDTH-1:0] din,
|
|
input logic clk,
|
|
input logic rst_l,
|
|
|
|
output logic [WIDTH-1:0] dout
|
|
);
|
|
|
|
if (SHORT == 1) begin
|
|
assign dout = din;
|
|
end
|
|
else begin
|
|
always_ff @(posedge clk or negedge rst_l) begin
|
|
if (rst_l == 0) dout[WIDTH-1:0] <= 0;
|
|
else dout[WIDTH-1:0] <= din[WIDTH-1:0];
|
|
end
|
|
|
|
end
|
|
endmodule
|
|
|
|
// rvdff with 2:1 input mux to flop din iff sel==1
|
|
module rvdffs #(
|
|
parameter WIDTH = 1,
|
|
SHORT = 0
|
|
) (
|
|
input logic [WIDTH-1:0] din,
|
|
input logic en,
|
|
input logic clk,
|
|
input logic rst_l,
|
|
output logic [WIDTH-1:0] dout
|
|
);
|
|
|
|
if (SHORT == 1) begin : genblock
|
|
assign dout = din;
|
|
end else begin : genblock
|
|
rvdff #(WIDTH) dffs (
|
|
.din((en) ? din[WIDTH-1:0] : dout[WIDTH-1:0]),
|
|
.*
|
|
);
|
|
end
|
|
|
|
endmodule
|
|
|
|
// rvdff with en and clear
|
|
module rvdffsc #(
|
|
parameter WIDTH = 1,
|
|
SHORT = 0
|
|
) (
|
|
input logic [WIDTH-1:0] din,
|
|
input logic en,
|
|
input logic clear,
|
|
input logic clk,
|
|
input logic rst_l,
|
|
output logic [WIDTH-1:0] dout
|
|
);
|
|
|
|
logic [WIDTH-1:0] din_new;
|
|
if (SHORT == 1) begin
|
|
assign dout = din;
|
|
end else begin
|
|
assign din_new = {WIDTH{~clear}} & (en ? din[WIDTH-1:0] : dout[WIDTH-1:0]);
|
|
rvdff #(WIDTH) dffsc (
|
|
.din(din_new[WIDTH-1:0]),
|
|
.*
|
|
);
|
|
end
|
|
endmodule
|
|
|
|
module rvdffe #(
|
|
parameter WIDTH = 1,
|
|
SHORT = 0,
|
|
OVERRIDE = 0
|
|
) (
|
|
input logic [WIDTH-1:0] din,
|
|
input logic en,
|
|
input logic clk,
|
|
input logic rst_l,
|
|
input logic scan_mode,
|
|
output logic [WIDTH-1:0] dout
|
|
);
|
|
|
|
logic l1clk;
|
|
|
|
if (SHORT == 1) begin : genblock
|
|
if (1) begin : genblock
|
|
assign dout = din;
|
|
end
|
|
end else begin : genblock
|
|
rvclkhdr clkhdr (.*);
|
|
rvdff #(WIDTH) dff (
|
|
.*,
|
|
.clk(l1clk)
|
|
);
|
|
end // else: !if(SHORT == 1)
|
|
|
|
endmodule // rvdffe
|
|
|
|
|
|
module rvdffpcie #(
|
|
parameter WIDTH = 31
|
|
) (
|
|
input logic [WIDTH-1:0] din,
|
|
input logic clk,
|
|
input logic rst_l,
|
|
input logic en,
|
|
input logic scan_mode,
|
|
output logic [WIDTH-1:0] dout
|
|
);
|
|
|
|
rvdfflie #(
|
|
.WIDTH(WIDTH),
|
|
.LEFT (19)
|
|
) dff (
|
|
.*
|
|
);
|
|
|
|
|
|
endmodule
|
|
|
|
// format: { LEFT, EXTRA }
|
|
// LEFT # of bits will be done with rvdffie, all else EXTRA with rvdffe
|
|
module rvdfflie #(
|
|
parameter WIDTH = 16,
|
|
LEFT = 8
|
|
) (
|
|
input logic [WIDTH-1:0] din,
|
|
input logic clk,
|
|
input logic rst_l,
|
|
input logic en,
|
|
input logic scan_mode,
|
|
output logic [WIDTH-1:0] dout
|
|
);
|
|
|
|
localparam EXTRA = WIDTH - LEFT;
|
|
|
|
localparam LMSB = WIDTH - 1;
|
|
localparam LLSB = LMSB - LEFT + 1;
|
|
localparam XMSB = LLSB - 1;
|
|
localparam XLSB = LLSB - EXTRA;
|
|
|
|
rvdffiee #(LEFT) dff_left (
|
|
.*,
|
|
.din (din[LMSB:LLSB]),
|
|
.dout(dout[LMSB:LLSB])
|
|
);
|
|
rvdffe #(EXTRA) dff_extra (
|
|
.*,
|
|
.din (din[XMSB:XLSB]),
|
|
.dout(dout[XMSB:XLSB])
|
|
);
|
|
|
|
endmodule
|
|
|
|
|
|
|
|
|
|
// special power flop for predict packet
|
|
// format: { LEFT, RIGHT==31 }
|
|
// LEFT # of bits will be done with rvdffe; RIGHT is enabled by LEFT[LSB] & en
|
|
module rvdffppe #(
|
|
parameter WIDTH = 32
|
|
) (
|
|
input logic [WIDTH-1:0] din,
|
|
input logic clk,
|
|
input logic rst_l,
|
|
input logic en,
|
|
input logic scan_mode,
|
|
output logic [WIDTH-1:0] dout
|
|
);
|
|
|
|
localparam RIGHT = 31;
|
|
localparam LEFT = WIDTH - RIGHT;
|
|
|
|
localparam LMSB = WIDTH - 1;
|
|
localparam LLSB = LMSB - LEFT + 1;
|
|
localparam RMSB = LLSB - 1;
|
|
localparam RLSB = LLSB - RIGHT;
|
|
|
|
rvdffe #(LEFT) dff_left (
|
|
.*,
|
|
.din (din[LMSB:LLSB]),
|
|
.dout(dout[LMSB:LLSB])
|
|
);
|
|
rvdffe #(RIGHT) dff_right (
|
|
.*,
|
|
.din (din[RMSB:RLSB]),
|
|
.dout(dout[RMSB:RLSB]),
|
|
.en (en & din[LLSB])
|
|
); // qualify with pret
|
|
|
|
endmodule
|
|
|
|
|
|
|
|
|
|
module rvdffie #(
|
|
parameter WIDTH = 1,
|
|
OVERRIDE = 0
|
|
) (
|
|
input logic [WIDTH-1:0] din,
|
|
|
|
input logic clk,
|
|
input logic rst_l,
|
|
input logic scan_mode,
|
|
output logic [WIDTH-1:0] dout
|
|
);
|
|
|
|
logic l1clk;
|
|
logic en;
|
|
|
|
assign en = |(din ^ dout);
|
|
|
|
rvclkhdr clkhdr (.*);
|
|
rvdff #(WIDTH) dff (
|
|
.*,
|
|
.clk(l1clk)
|
|
);
|
|
|
|
endmodule
|
|
|
|
// ie flop but it has an .en input
|
|
module rvdffiee #(
|
|
parameter WIDTH = 1,
|
|
OVERRIDE = 0
|
|
) (
|
|
input logic [WIDTH-1:0] din,
|
|
|
|
input logic clk,
|
|
input logic rst_l,
|
|
input logic scan_mode,
|
|
input logic en,
|
|
output logic [WIDTH-1:0] dout
|
|
);
|
|
|
|
logic l1clk;
|
|
logic final_en;
|
|
|
|
|
|
assign final_en = (|(din ^ dout)) & en;
|
|
|
|
rvdffe #(WIDTH) dff (
|
|
.*,
|
|
.en(final_en)
|
|
);
|
|
|
|
endmodule
|
|
|
|
|
|
|
|
module rvsyncss #(
|
|
parameter WIDTH = 251
|
|
) (
|
|
input logic clk,
|
|
input logic rst_l,
|
|
input logic [WIDTH-1:0] din,
|
|
output logic [WIDTH-1:0] dout
|
|
);
|
|
|
|
logic [WIDTH-1:0] din_ff1;
|
|
|
|
rvdff #(WIDTH) sync_ff1 (
|
|
.*,
|
|
.din (din[WIDTH-1:0]),
|
|
.dout(din_ff1[WIDTH-1:0])
|
|
);
|
|
rvdff #(WIDTH) sync_ff2 (
|
|
.*,
|
|
.din (din_ff1[WIDTH-1:0]),
|
|
.dout(dout[WIDTH-1:0])
|
|
);
|
|
|
|
endmodule // rvsyncss
|
|
|
|
module rvlsadder (
|
|
input logic [31:0] rs1,
|
|
input logic [11:0] offset,
|
|
|
|
output logic [31:0] dout
|
|
);
|
|
|
|
logic cout;
|
|
logic sign;
|
|
|
|
logic [31:12] rs1_inc;
|
|
logic [31:12] rs1_dec;
|
|
|
|
assign {cout, dout[11:0]} = {1'b0, rs1[11:0]} + {1'b0, offset[11:0]};
|
|
|
|
assign rs1_inc[31:12] = rs1[31:12] + 1;
|
|
|
|
assign rs1_dec[31:12] = rs1[31:12] - 1;
|
|
|
|
assign sign = offset[11];
|
|
|
|
assign dout[31:12] = ({20{ sign ^~ cout}} & rs1[31:12]) |
|
|
({20{ ~sign & cout}} & rs1_inc[31:12]) |
|
|
({20{ sign & ~cout}} & rs1_dec[31:12]);
|
|
|
|
endmodule // rvlsadder
|
|
|
|
// assume we only maintain pc[31:1] in the pipe
|
|
|
|
module rvbradder (
|
|
input [31:1] pc,
|
|
input [12:1] offset,
|
|
|
|
output [31:1] dout
|
|
);
|
|
|
|
logic cout;
|
|
logic sign;
|
|
|
|
logic [31:13] pc_inc;
|
|
logic [31:13] pc_dec;
|
|
|
|
assign {cout, dout[12:1]} = {1'b0, pc[12:1]} + {1'b0, offset[12:1]};
|
|
|
|
assign pc_inc[31:13] = pc[31:13] + 1;
|
|
|
|
assign pc_dec[31:13] = pc[31:13] - 1;
|
|
|
|
assign sign = offset[12];
|
|
|
|
|
|
assign dout[31:13] = ({19{ sign ^~ cout}} & pc[31:13]) |
|
|
({19{ ~sign & cout}} & pc_inc[31:13]) |
|
|
({19{ sign & ~cout}} & pc_dec[31:13]);
|
|
|
|
|
|
endmodule // rvbradder
|
|
|
|
|
|
// 2s complement circuit
|
|
module rvtwoscomp #(
|
|
parameter WIDTH = 32
|
|
) (
|
|
input logic [WIDTH-1:0] din,
|
|
|
|
output logic [WIDTH-1:0] dout
|
|
);
|
|
|
|
logic [WIDTH-1:1] dout_temp; // holding for all other bits except for the lsb. LSB is always din
|
|
|
|
genvar i;
|
|
|
|
for (i = 1; i < WIDTH; i++) begin : flip_after_first_one
|
|
assign dout_temp[i] = (|din[i-1:0]) ? ~din[i] : din[i];
|
|
end : flip_after_first_one
|
|
|
|
assign dout[WIDTH-1:0] = {dout_temp[WIDTH-1:1], din[0]};
|
|
|
|
endmodule // 2'scomp
|
|
|
|
// find first
|
|
module rvfindfirst1 #(
|
|
parameter WIDTH = 32,
|
|
SHIFT = $clog2(WIDTH)
|
|
) (
|
|
input logic [WIDTH-1:0] din,
|
|
|
|
output logic [SHIFT-1:0] dout
|
|
);
|
|
logic done;
|
|
|
|
always_comb begin
|
|
dout[SHIFT-1:0] = {SHIFT{1'b0}};
|
|
done = 1'b0;
|
|
|
|
for (int i = WIDTH - 1; i > 0; i--) begin : find_first_one
|
|
done |= din[i];
|
|
dout[SHIFT-1:0] += done ? 1'b0 : 1'b1;
|
|
end : find_first_one
|
|
end
|
|
endmodule // rvfindfirst1
|
|
|
|
module rvfindfirst1hot #(
|
|
parameter WIDTH = 32
|
|
) (
|
|
input logic [WIDTH-1:0] din,
|
|
|
|
output logic [WIDTH-1:0] dout
|
|
);
|
|
logic done;
|
|
|
|
always_comb begin
|
|
dout[WIDTH-1:0] = {WIDTH{1'b0}};
|
|
done = 1'b0;
|
|
for (int i = 0; i < WIDTH; i++) begin : find_first_one
|
|
dout[i] = ~done & din[i];
|
|
done |= din[i];
|
|
end : find_first_one
|
|
end
|
|
endmodule // rvfindfirst1hot
|
|
|
|
// mask and match function matches bits after finding the first 0 position
|
|
// find first starting from LSB. Skip that location and match the rest of the bits
|
|
module rvmaskandmatch #(
|
|
parameter WIDTH = 32
|
|
) (
|
|
input logic [WIDTH-1:0] mask, // this will have the mask in the lower bit positions
|
|
input logic [WIDTH-1:0] data, // this is what needs to be matched on the upper bits with the mask's upper bits
|
|
input logic masken, // when 1 : do mask. 0 : full match
|
|
output logic match
|
|
);
|
|
|
|
logic [WIDTH-1:0] matchvec;
|
|
logic masken_or_fullmask;
|
|
|
|
assign masken_or_fullmask = masken & ~(&mask[WIDTH-1:0]);
|
|
|
|
assign matchvec[0] = masken_or_fullmask | (mask[0] == data[0]);
|
|
genvar i;
|
|
|
|
for (i = 1; i < WIDTH; i++) begin : match_after_first_zero
|
|
assign matchvec[i] = (&mask[i-1:0] & masken_or_fullmask) ? 1'b1 : (mask[i] == data[i]);
|
|
end : match_after_first_zero
|
|
|
|
assign match = &matchvec[WIDTH-1:0]; // all bits either matched or were masked off
|
|
|
|
endmodule // rvmaskandmatch
|
|
|
|
|
|
|
|
|
|
// Check if the S_ADDR <= addr < E_ADDR
|
|
module rvrangecheck #(
|
|
CCM_SADR = 32'h0,
|
|
CCM_SIZE = 128
|
|
) (
|
|
input logic [31:0] addr, // Address to be checked for range
|
|
output logic in_range, // S_ADDR <= start_addr < E_ADDR
|
|
output logic in_region
|
|
);
|
|
|
|
localparam REGION_BITS = 4;
|
|
localparam MASK_BITS = 10 + $clog2(CCM_SIZE);
|
|
|
|
logic [31:0] start_addr;
|
|
logic [ 3:0] region;
|
|
|
|
assign start_addr[31:0] = CCM_SADR;
|
|
assign region[REGION_BITS-1:0] = start_addr[31:(32-REGION_BITS)];
|
|
|
|
assign in_region = (addr[31:(32-REGION_BITS)] == region[REGION_BITS-1:0]);
|
|
if (CCM_SIZE == 48)
|
|
assign in_range = (addr[31:MASK_BITS] == start_addr[31:MASK_BITS]) & ~(&addr[MASK_BITS-1 : MASK_BITS-2]);
|
|
else assign in_range = (addr[31:MASK_BITS] == start_addr[31:MASK_BITS]);
|
|
|
|
endmodule // rvrangechecker
|
|
|
|
// 16 bit even parity generator
|
|
module rveven_paritygen #(
|
|
WIDTH = 16
|
|
) (
|
|
input logic [WIDTH-1:0] data_in, // Data
|
|
output logic parity_out // generated even parity
|
|
);
|
|
|
|
assign parity_out = ^(data_in[WIDTH-1:0]);
|
|
|
|
endmodule // rveven_paritygen
|
|
|
|
module rveven_paritycheck #(
|
|
WIDTH = 16
|
|
) (
|
|
input logic [WIDTH-1:0] data_in, // Data
|
|
input logic parity_in,
|
|
output logic parity_err // Parity error
|
|
);
|
|
|
|
assign parity_err = ^(data_in[WIDTH-1:0]) ^ parity_in;
|
|
|
|
endmodule // rveven_paritycheck
|
|
|
|
module rvecc_encode (
|
|
input [31:0] din,
|
|
output [ 6:0] ecc_out
|
|
);
|
|
logic [5:0] ecc_out_temp;
|
|
|
|
assign ecc_out_temp[0] = din[0]^din[1]^din[3]^din[4]^din[6]^din[8]^din[10]^din[11]^din[13]^din[15]^din[17]^din[19]^din[21]^din[23]^din[25]^din[26]^din[28]^din[30];
|
|
assign ecc_out_temp[1] = din[0]^din[2]^din[3]^din[5]^din[6]^din[9]^din[10]^din[12]^din[13]^din[16]^din[17]^din[20]^din[21]^din[24]^din[25]^din[27]^din[28]^din[31];
|
|
assign ecc_out_temp[2] = din[1]^din[2]^din[3]^din[7]^din[8]^din[9]^din[10]^din[14]^din[15]^din[16]^din[17]^din[22]^din[23]^din[24]^din[25]^din[29]^din[30]^din[31];
|
|
assign ecc_out_temp[3] = din[4]^din[5]^din[6]^din[7]^din[8]^din[9]^din[10]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25];
|
|
assign ecc_out_temp[4] = din[11]^din[12]^din[13]^din[14]^din[15]^din[16]^din[17]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25];
|
|
assign ecc_out_temp[5] = din[26] ^ din[27] ^ din[28] ^ din[29] ^ din[30] ^ din[31];
|
|
|
|
assign ecc_out[6:0] = {(^din[31:0]) ^ (^ecc_out_temp[5:0]), ecc_out_temp[5:0]};
|
|
|
|
endmodule // rvecc_encode
|
|
|
|
module rvecc_decode (
|
|
input en,
|
|
input [31:0] din,
|
|
input [ 6:0] ecc_in,
|
|
input sed_ded, // only do detection and no correction. Used for the I$
|
|
output [31:0] dout,
|
|
output [ 6:0] ecc_out,
|
|
output single_ecc_error,
|
|
output double_ecc_error
|
|
|
|
);
|
|
|
|
logic [ 6:0] ecc_check;
|
|
logic [38:0] error_mask;
|
|
logic [38:0] din_plus_parity, dout_plus_parity;
|
|
|
|
// Generate the ecc bits
|
|
assign ecc_check[0] = ecc_in[0]^din[0]^din[1]^din[3]^din[4]^din[6]^din[8]^din[10]^din[11]^din[13]^din[15]^din[17]^din[19]^din[21]^din[23]^din[25]^din[26]^din[28]^din[30];
|
|
assign ecc_check[1] = ecc_in[1]^din[0]^din[2]^din[3]^din[5]^din[6]^din[9]^din[10]^din[12]^din[13]^din[16]^din[17]^din[20]^din[21]^din[24]^din[25]^din[27]^din[28]^din[31];
|
|
assign ecc_check[2] = ecc_in[2]^din[1]^din[2]^din[3]^din[7]^din[8]^din[9]^din[10]^din[14]^din[15]^din[16]^din[17]^din[22]^din[23]^din[24]^din[25]^din[29]^din[30]^din[31];
|
|
assign ecc_check[3] = ecc_in[3]^din[4]^din[5]^din[6]^din[7]^din[8]^din[9]^din[10]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25];
|
|
assign ecc_check[4] = ecc_in[4]^din[11]^din[12]^din[13]^din[14]^din[15]^din[16]^din[17]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25];
|
|
assign ecc_check[5] = ecc_in[5] ^ din[26] ^ din[27] ^ din[28] ^ din[29] ^ din[30] ^ din[31];
|
|
|
|
// This is the parity bit
|
|
assign ecc_check[6] = ((^din[31:0]) ^ (^ecc_in[6:0])) & ~sed_ded;
|
|
|
|
assign single_ecc_error = en & (ecc_check[6:0] != 0) & ecc_check[6]; // this will never be on for sed_ded
|
|
assign double_ecc_error = en & (ecc_check[6:0] != 0) & ~ecc_check[6]; // all errors in the sed_ded case will be recorded as DE
|
|
|
|
// Generate the mask for error correctiong
|
|
for (genvar i = 1; i < 40; i++) begin
|
|
assign error_mask[i-1] = (ecc_check[5:0] == i);
|
|
end
|
|
|
|
// Generate the corrected data
|
|
assign din_plus_parity[38:0] = {
|
|
ecc_in[6],
|
|
din[31:26],
|
|
ecc_in[5],
|
|
din[25:11],
|
|
ecc_in[4],
|
|
din[10:4],
|
|
ecc_in[3],
|
|
din[3:1],
|
|
ecc_in[2],
|
|
din[0],
|
|
ecc_in[1:0]
|
|
};
|
|
|
|
assign dout_plus_parity[38:0] = single_ecc_error ? (error_mask[38:0] ^ din_plus_parity[38:0]) : din_plus_parity[38:0];
|
|
assign dout[31:0] = {
|
|
dout_plus_parity[37:32],
|
|
dout_plus_parity[30:16],
|
|
dout_plus_parity[14:8],
|
|
dout_plus_parity[6:4],
|
|
dout_plus_parity[2]
|
|
};
|
|
assign ecc_out[6:0] = {
|
|
(dout_plus_parity[38] ^ (ecc_check[6:0] == 7'b1000000)),
|
|
dout_plus_parity[31],
|
|
dout_plus_parity[15],
|
|
dout_plus_parity[7],
|
|
dout_plus_parity[3],
|
|
dout_plus_parity[1:0]
|
|
};
|
|
|
|
endmodule // rvecc_decode
|
|
|
|
module rvecc_encode_64 (
|
|
input [63:0] din,
|
|
output [ 6:0] ecc_out
|
|
);
|
|
assign ecc_out[0] = din[0]^din[1]^din[3]^din[4]^din[6]^din[8]^din[10]^din[11]^din[13]^din[15]^din[17]^din[19]^din[21]^din[23]^din[25]^din[26]^din[28]^din[30]^din[32]^din[34]^din[36]^din[38]^din[40]^din[42]^din[44]^din[46]^din[48]^din[50]^din[52]^din[54]^din[56]^din[57]^din[59]^din[61]^din[63];
|
|
|
|
assign ecc_out[1] = din[0]^din[2]^din[3]^din[5]^din[6]^din[9]^din[10]^din[12]^din[13]^din[16]^din[17]^din[20]^din[21]^din[24]^din[25]^din[27]^din[28]^din[31]^din[32]^din[35]^din[36]^din[39]^din[40]^din[43]^din[44]^din[47]^din[48]^din[51]^din[52]^din[55]^din[56]^din[58]^din[59]^din[62]^din[63];
|
|
|
|
assign ecc_out[2] = din[1]^din[2]^din[3]^din[7]^din[8]^din[9]^din[10]^din[14]^din[15]^din[16]^din[17]^din[22]^din[23]^din[24]^din[25]^din[29]^din[30]^din[31]^din[32]^din[37]^din[38]^din[39]^din[40]^din[45]^din[46]^din[47]^din[48]^din[53]^din[54]^din[55]^din[56]^din[60]^din[61]^din[62]^din[63];
|
|
|
|
assign ecc_out[3] = din[4]^din[5]^din[6]^din[7]^din[8]^din[9]^din[10]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25]^din[33]^din[34]^din[35]^din[36]^din[37]^din[38]^din[39]^din[40]^din[49]^din[50]^din[51]^din[52]^din[53]^din[54]^din[55]^din[56];
|
|
|
|
assign ecc_out[4] = din[11]^din[12]^din[13]^din[14]^din[15]^din[16]^din[17]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25]^din[41]^din[42]^din[43]^din[44]^din[45]^din[46]^din[47]^din[48]^din[49]^din[50]^din[51]^din[52]^din[53]^din[54]^din[55]^din[56];
|
|
|
|
assign ecc_out[5] = din[26]^din[27]^din[28]^din[29]^din[30]^din[31]^din[32]^din[33]^din[34]^din[35]^din[36]^din[37]^din[38]^din[39]^din[40]^din[41]^din[42]^din[43]^din[44]^din[45]^din[46]^din[47]^din[48]^din[49]^din[50]^din[51]^din[52]^din[53]^din[54]^din[55]^din[56];
|
|
|
|
assign ecc_out[6] = din[57] ^ din[58] ^ din[59] ^ din[60] ^ din[61] ^ din[62] ^ din[63];
|
|
|
|
endmodule // rvecc_encode_64
|
|
|
|
|
|
module rvecc_decode_64 (
|
|
input en,
|
|
input [63:0] din,
|
|
input [ 6:0] ecc_in,
|
|
output ecc_error
|
|
);
|
|
|
|
logic [6:0] ecc_check;
|
|
|
|
// Generate the ecc bits
|
|
assign ecc_check[0] = ecc_in[0]^din[0]^din[1]^din[3]^din[4]^din[6]^din[8]^din[10]^din[11]^din[13]^din[15]^din[17]^din[19]^din[21]^din[23]^din[25]^din[26]^din[28]^din[30]^din[32]^din[34]^din[36]^din[38]^din[40]^din[42]^din[44]^din[46]^din[48]^din[50]^din[52]^din[54]^din[56]^din[57]^din[59]^din[61]^din[63];
|
|
|
|
assign ecc_check[1] = ecc_in[1]^din[0]^din[2]^din[3]^din[5]^din[6]^din[9]^din[10]^din[12]^din[13]^din[16]^din[17]^din[20]^din[21]^din[24]^din[25]^din[27]^din[28]^din[31]^din[32]^din[35]^din[36]^din[39]^din[40]^din[43]^din[44]^din[47]^din[48]^din[51]^din[52]^din[55]^din[56]^din[58]^din[59]^din[62]^din[63];
|
|
|
|
assign ecc_check[2] = ecc_in[2]^din[1]^din[2]^din[3]^din[7]^din[8]^din[9]^din[10]^din[14]^din[15]^din[16]^din[17]^din[22]^din[23]^din[24]^din[25]^din[29]^din[30]^din[31]^din[32]^din[37]^din[38]^din[39]^din[40]^din[45]^din[46]^din[47]^din[48]^din[53]^din[54]^din[55]^din[56]^din[60]^din[61]^din[62]^din[63];
|
|
|
|
assign ecc_check[3] = ecc_in[3]^din[4]^din[5]^din[6]^din[7]^din[8]^din[9]^din[10]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25]^din[33]^din[34]^din[35]^din[36]^din[37]^din[38]^din[39]^din[40]^din[49]^din[50]^din[51]^din[52]^din[53]^din[54]^din[55]^din[56];
|
|
|
|
assign ecc_check[4] = ecc_in[4]^din[11]^din[12]^din[13]^din[14]^din[15]^din[16]^din[17]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25]^din[41]^din[42]^din[43]^din[44]^din[45]^din[46]^din[47]^din[48]^din[49]^din[50]^din[51]^din[52]^din[53]^din[54]^din[55]^din[56];
|
|
|
|
assign ecc_check[5] = ecc_in[5]^din[26]^din[27]^din[28]^din[29]^din[30]^din[31]^din[32]^din[33]^din[34]^din[35]^din[36]^din[37]^din[38]^din[39]^din[40]^din[41]^din[42]^din[43]^din[44]^din[45]^din[46]^din[47]^din[48]^din[49]^din[50]^din[51]^din[52]^din[53]^din[54]^din[55]^din[56];
|
|
|
|
assign ecc_check[6] = ecc_in[6]^din[57]^din[58]^din[59]^din[60]^din[61]^din[62]^din[63];
|
|
|
|
assign ecc_error = en & (ecc_check[6:0] != 0); // all errors in the sed_ded case will be recorded as DE
|
|
|
|
endmodule // rvecc_decode_64
|
|
|
|
|
|
module clockhdr (
|
|
input logic SE,
|
|
EN,
|
|
CK,
|
|
output Q
|
|
);
|
|
|
|
logic en_ff;
|
|
logic enable;
|
|
|
|
assign enable = EN | SE;
|
|
|
|
`ifdef VERILATOR
|
|
always @(negedge CK) begin
|
|
en_ff <= enable;
|
|
end
|
|
`else
|
|
always @(CK, enable) begin
|
|
if (!CK) en_ff = enable;
|
|
end
|
|
`endif
|
|
assign Q = CK & en_ff;
|
|
|
|
endmodule
|
|
|
|
module rvclkhdr (
|
|
input logic en,
|
|
input logic clk,
|
|
input logic scan_mode,
|
|
output logic l1clk
|
|
);
|
|
|
|
logic SE;
|
|
assign SE = 0;
|
|
|
|
clockhdr clkhdr (
|
|
.*,
|
|
.EN(en),
|
|
.CK(clk),
|
|
.Q (l1clk)
|
|
);
|
|
|
|
endmodule // rvclkhdr
|
|
|
|
module rvoclkhdr (
|
|
input logic en,
|
|
input logic clk,
|
|
input logic scan_mode,
|
|
output logic l1clk
|
|
);
|
|
|
|
logic SE;
|
|
assign SE = 0;
|
|
|
|
clockhdr clkhdr (
|
|
.*,
|
|
.EN(en),
|
|
.CK(clk),
|
|
.Q (l1clk)
|
|
);
|
|
endmodule
|
|
|
|
|
|
|