1 |
11 |
dinesha |
/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
|
2 |
|
|
/// @file
|
3 |
|
|
/// @brief Multi Port Register File (MPRF)
|
4 |
|
|
///
|
5 |
|
|
|
6 |
|
|
`include "scr1_arch_description.svh"
|
7 |
|
|
`include "scr1_arch_types.svh"
|
8 |
|
|
|
9 |
|
|
module scr1_pipe_mprf (
|
10 |
|
|
// Common
|
11 |
|
|
`ifdef SCR1_MPRF_RST_EN
|
12 |
|
|
input logic rst_n, // MPRF reset
|
13 |
|
|
`endif // SCR1_MPRF_RST_EN
|
14 |
|
|
input logic clk, // MPRF clock
|
15 |
|
|
|
16 |
|
|
// EXU <-> MPRF interface
|
17 |
|
|
input logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rs1_addr_i, // MPRF rs1 read address
|
18 |
|
|
output logic [`SCR1_XLEN-1:0] mprf2exu_rs1_data_o, // MPRF rs1 read data
|
19 |
|
|
input logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rs2_addr_i, // MPRF rs2 read address
|
20 |
|
|
output logic [`SCR1_XLEN-1:0] mprf2exu_rs2_data_o, // MPRF rs2 read data
|
21 |
|
|
input logic exu2mprf_w_req_i, // MPRF write request
|
22 |
|
|
input logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rd_addr_i, // MPRF rd write address
|
23 |
|
|
input logic [`SCR1_XLEN-1:0] exu2mprf_rd_data_i // MPRF rd write data
|
24 |
|
|
);
|
25 |
|
|
|
26 |
|
|
//-------------------------------------------------------------------------------
|
27 |
|
|
// Local types declaration
|
28 |
|
|
//-------------------------------------------------------------------------------
|
29 |
|
|
|
30 |
|
|
logic wr_req_vd;
|
31 |
|
|
|
32 |
|
|
logic rs1_addr_vd;
|
33 |
|
|
logic rs2_addr_vd;
|
34 |
|
|
|
35 |
|
|
`ifdef SCR1_MPRF_RAM
|
36 |
|
|
logic rs1_addr_vd_ff;
|
37 |
|
|
logic rs2_addr_vd_ff;
|
38 |
|
|
|
39 |
|
|
logic rs1_new_data_req;
|
40 |
|
|
logic rs2_new_data_req;
|
41 |
|
|
logic rs1_new_data_req_ff;
|
42 |
|
|
logic rs2_new_data_req_ff;
|
43 |
|
|
logic read_new_data_req;
|
44 |
|
|
|
45 |
|
|
logic [`SCR1_XLEN-1:0] rd_data_ff;
|
46 |
|
|
|
47 |
|
|
logic [`SCR1_XLEN-1:0] rs1_data_ff;
|
48 |
|
|
logic [`SCR1_XLEN-1:0] rs2_data_ff;
|
49 |
|
|
|
50 |
|
|
// when using RAM, 2 memories are needed because 3 simultaneous independent
|
51 |
|
|
// write/read operations can occur
|
52 |
|
|
`ifdef SCR1_TRGT_FPGA_INTEL_MAX10
|
53 |
|
|
(* ramstyle = "M9K" *) logic [`SCR1_XLEN-1:0] mprf_int [1:`SCR1_MPRF_SIZE-1];
|
54 |
|
|
(* ramstyle = "M9K" *) logic [`SCR1_XLEN-1:0] mprf_int2 [1:`SCR1_MPRF_SIZE-1];
|
55 |
|
|
`elsif SCR1_TRGT_FPGA_INTEL_ARRIAV
|
56 |
|
|
(* ramstyle = "M10K" *) logic [`SCR1_XLEN-1:0] mprf_int [1:`SCR1_MPRF_SIZE-1];
|
57 |
|
|
(* ramstyle = "M10K" *) logic [`SCR1_XLEN-1:0] mprf_int2 [1:`SCR1_MPRF_SIZE-1];
|
58 |
|
|
`else
|
59 |
|
|
logic [`SCR1_XLEN-1:0] mprf_int [1:`SCR1_MPRF_SIZE-1];
|
60 |
|
|
logic [`SCR1_XLEN-1:0] mprf_int2 [1:`SCR1_MPRF_SIZE-1];
|
61 |
|
|
`endif
|
62 |
|
|
`else // distributed logic implementation
|
63 |
|
|
type_scr1_mprf_v [1:`SCR1_MPRF_SIZE-1] mprf_int;
|
64 |
|
|
`endif
|
65 |
|
|
|
66 |
|
|
//------------------------------------------------------------------------------
|
67 |
|
|
// MPRF control logic
|
68 |
|
|
//------------------------------------------------------------------------------
|
69 |
|
|
|
70 |
|
|
// control signals common for distributed logic and RAM implementations
|
71 |
|
|
assign rs1_addr_vd = |exu2mprf_rs1_addr_i;
|
72 |
|
|
assign rs2_addr_vd = |exu2mprf_rs2_addr_i;
|
73 |
|
|
|
74 |
|
|
assign wr_req_vd = exu2mprf_w_req_i & |exu2mprf_rd_addr_i;
|
75 |
|
|
|
76 |
|
|
// RAM implementation specific control signals
|
77 |
|
|
`ifdef SCR1_MPRF_RAM
|
78 |
|
|
assign rs1_new_data_req = wr_req_vd & ( exu2mprf_rs1_addr_i == exu2mprf_rd_addr_i );
|
79 |
|
|
assign rs2_new_data_req = wr_req_vd & ( exu2mprf_rs2_addr_i == exu2mprf_rd_addr_i );
|
80 |
|
|
assign read_new_data_req = rs1_new_data_req | rs2_new_data_req;
|
81 |
|
|
|
82 |
|
|
always_ff @( posedge clk ) begin
|
83 |
|
|
rs1_addr_vd_ff <= rs1_addr_vd;
|
84 |
|
|
rs2_addr_vd_ff <= rs2_addr_vd;
|
85 |
|
|
rs1_new_data_req_ff <= rs1_new_data_req;
|
86 |
|
|
rs2_new_data_req_ff <= rs2_new_data_req;
|
87 |
|
|
end
|
88 |
|
|
`endif // SCR1_MPRF_RAM
|
89 |
|
|
|
90 |
|
|
`ifdef SCR1_MPRF_RAM
|
91 |
|
|
//-------------------------------------------------------------------------------
|
92 |
|
|
// RAM implementation
|
93 |
|
|
//-------------------------------------------------------------------------------
|
94 |
|
|
|
95 |
|
|
// RAM is implemented with 2 simple dual-port memories with sync read operation;
|
96 |
|
|
// logic for "write-first" RDW behavior is implemented externally to the embedded
|
97 |
|
|
// memory blocks
|
98 |
|
|
|
99 |
|
|
// bypass new wr_data to the read output if write/read collision occurs
|
100 |
|
|
assign mprf2exu_rs1_data_o = ( rs1_new_data_req_ff ) ? rd_data_ff
|
101 |
|
|
: (( rs1_addr_vd_ff ) ? rs1_data_ff
|
102 |
|
|
: '0 );
|
103 |
|
|
|
104 |
|
|
assign mprf2exu_rs2_data_o = ( rs2_new_data_req_ff ) ? rd_data_ff
|
105 |
|
|
: (( rs2_addr_vd_ff ) ? rs2_data_ff
|
106 |
|
|
: '0 );
|
107 |
|
|
|
108 |
|
|
always_ff @( posedge clk ) begin
|
109 |
|
|
if ( read_new_data_req ) begin
|
110 |
|
|
rd_data_ff <= exu2mprf_rd_data_i;
|
111 |
|
|
end
|
112 |
|
|
end
|
113 |
|
|
|
114 |
|
|
// synchronous read operation
|
115 |
|
|
always_ff @( posedge clk ) begin
|
116 |
|
|
rs1_data_ff <= mprf_int[exu2mprf_rs1_addr_i];
|
117 |
|
|
rs2_data_ff <= mprf_int2[exu2mprf_rs2_addr_i];
|
118 |
|
|
end
|
119 |
|
|
|
120 |
|
|
// write operation
|
121 |
|
|
always_ff @( posedge clk ) begin
|
122 |
|
|
if ( wr_req_vd ) begin
|
123 |
|
|
mprf_int[exu2mprf_rd_addr_i] <= exu2mprf_rd_data_i;
|
124 |
|
|
mprf_int2[exu2mprf_rd_addr_i] <= exu2mprf_rd_data_i;
|
125 |
|
|
end
|
126 |
|
|
end
|
127 |
|
|
`else // distributed logic implementation
|
128 |
|
|
//------------------------------------------------------------------------------
|
129 |
|
|
// distributed logic implementation
|
130 |
|
|
//------------------------------------------------------------------------------
|
131 |
|
|
|
132 |
|
|
// asynchronous read operation
|
133 |
|
|
assign mprf2exu_rs1_data_o = ( rs1_addr_vd ) ? mprf_int[exu2mprf_rs1_addr_i] : '0;
|
134 |
|
|
assign mprf2exu_rs2_data_o = ( rs2_addr_vd ) ? mprf_int[exu2mprf_rs2_addr_i] : '0;
|
135 |
|
|
|
136 |
|
|
// write operation
|
137 |
|
|
`ifdef SCR1_MPRF_RST_EN
|
138 |
|
|
always_ff @( posedge clk, negedge rst_n ) begin
|
139 |
|
|
if ( ~rst_n ) begin
|
140 |
|
|
mprf_int <= '{default: '0};
|
141 |
|
|
end else if ( wr_req_vd ) begin
|
142 |
|
|
mprf_int[exu2mprf_rd_addr_i] <= exu2mprf_rd_data_i;
|
143 |
|
|
end
|
144 |
|
|
end
|
145 |
|
|
`else // ~SCR1_MPRF_RST_EN
|
146 |
|
|
always_ff @( posedge clk ) begin
|
147 |
|
|
if ( wr_req_vd ) begin
|
148 |
|
|
mprf_int[exu2mprf_rd_addr_i] <= exu2mprf_rd_data_i;
|
149 |
|
|
end
|
150 |
|
|
end
|
151 |
|
|
`endif // ~SCR1_MPRF_RST_EN
|
152 |
|
|
`endif
|
153 |
|
|
|
154 |
|
|
`ifdef SCR1_TRGT_SIMULATION
|
155 |
|
|
//-------------------------------------------------------------------------------
|
156 |
|
|
// Assertion
|
157 |
|
|
//-------------------------------------------------------------------------------
|
158 |
|
|
`ifdef SCR1_MPRF_RST_EN
|
159 |
|
|
SCR1_SVA_MPRF_WRITEX : assert property (
|
160 |
|
|
@(negedge clk) disable iff (~rst_n)
|
161 |
|
|
exu2mprf_w_req_i |-> !$isunknown({exu2mprf_rd_addr_i, (|exu2mprf_rd_addr_i ? exu2mprf_rd_data_i : `SCR1_XLEN'd0)})
|
162 |
|
|
) else $error("MPRF error: unknown values");
|
163 |
|
|
`endif // SCR1_MPRF_RST_EN
|
164 |
|
|
|
165 |
|
|
`endif // SCR1_TRGT_SIMULATION
|
166 |
|
|
|
167 |
|
|
endmodule : scr1_pipe_mprf
|