1 |
4 |
ericw |
/*
|
2 |
|
|
--------------------------------------------------------------------------------
|
3 |
|
|
|
4 |
|
|
Module : pointer_ring.v
|
5 |
|
|
|
6 |
|
|
--------------------------------------------------------------------------------
|
7 |
|
|
|
8 |
|
|
Function:
|
9 |
|
|
- Processor stack pointer storage ring.
|
10 |
|
|
|
11 |
|
|
Instantiates:
|
12 |
|
|
- (1x) pipe.v
|
13 |
|
|
|
14 |
|
|
Notes:
|
15 |
|
|
- 8 stage pointer storage ring for 8 BRAM based LIFOs:
|
16 |
|
|
|
17 |
|
|
1 : pop applied
|
18 |
|
|
2 : push applied; pop errors output
|
19 |
|
|
3 : push errors output
|
20 |
|
|
6 : pointers & writes output
|
21 |
|
|
- Logic assumes pop | push will not be issued simultaneously with clear.
|
22 |
|
|
- Externally concatenate thread 6 & pointers to form stack memory addresses.
|
23 |
|
|
- Level width is PTR_W+1 to accomodate 0 to 2^n levels (1 + 2n states).
|
24 |
|
|
- Empty push is to address 1, full push is to address 0.
|
25 |
|
|
- Combo pop/push is accomodated with no net fullness/pointer change.
|
26 |
|
|
- Pop when empty is a pop error.
|
27 |
|
|
- Push when full is a push error.
|
28 |
|
|
- Pop/push when full is NOT an error.
|
29 |
|
|
- Pop/push when empty is a pop error ONLY.
|
30 |
|
|
- Parameterized stack error handling. If the associated protection is turned on
|
31 |
|
|
then pop/push errors are reported but otherwise not acted upon, i.e. errors
|
32 |
|
|
will not corrupt fullness/pointers. If the associated protection is turned
|
33 |
|
|
off then errors are still reported, but fullness/pointers will be corrupted.
|
34 |
|
|
|
35 |
|
|
--------------------------------------------------------------------------------
|
36 |
|
|
*/
|
37 |
|
|
|
38 |
|
|
module pointer_ring
|
39 |
|
|
#(
|
40 |
|
|
parameter integer THREADS = 8, // threads
|
41 |
|
|
parameter integer STACKS = 8, // stacks
|
42 |
|
|
parameter integer PNTR_W = 5, // stack pointer width
|
43 |
|
|
parameter integer PROT_POP = 1, // 1=error protection, 0=none
|
44 |
|
|
parameter integer PROT_PUSH = 1 // 1=error protection, 0=none
|
45 |
|
|
)
|
46 |
|
|
(
|
47 |
|
|
// clocks & resets
|
48 |
|
|
input wire clk_i, // clock
|
49 |
|
|
input wire rst_i, // async. reset, active high
|
50 |
|
|
// control I/O
|
51 |
|
|
input wire clr_i, // stacks clear
|
52 |
|
|
input wire [STACKS-1:0] pop_i, // stacks pop
|
53 |
|
|
input wire [STACKS-1:0] push_i, // stacks push
|
54 |
|
|
// pointers
|
55 |
|
|
output wire [PNTR_W-1:0] pntr0_6_o, // stack pointer
|
56 |
|
|
output wire [PNTR_W-1:0] pntr1_6_o, // stack pointer
|
57 |
|
|
output wire [PNTR_W-1:0] pntr2_6_o, // stack pointer
|
58 |
|
|
output wire [PNTR_W-1:0] pntr3_6_o, // stack pointer
|
59 |
|
|
output wire [PNTR_W-1:0] pntr4_6_o, // stack pointer
|
60 |
|
|
output wire [PNTR_W-1:0] pntr5_6_o, // stack pointer
|
61 |
|
|
output wire [PNTR_W-1:0] pntr6_6_o, // stack pointer
|
62 |
|
|
output wire [PNTR_W-1:0] pntr7_6_o, // stack pointer
|
63 |
|
|
// write enables
|
64 |
|
|
output wire [STACKS-1:0] wr_6_o, // write enables
|
65 |
|
|
// errors
|
66 |
|
|
output wire [STACKS-1:0] pop_er_2_o, // pop when empty, active high
|
67 |
|
|
output wire [STACKS-1:0] push_er_3_o // push when full, active high
|
68 |
|
|
);
|
69 |
|
|
|
70 |
|
|
|
71 |
|
|
/*
|
72 |
|
|
----------------------
|
73 |
|
|
-- internal signals --
|
74 |
|
|
----------------------
|
75 |
|
|
*/
|
76 |
|
|
localparam integer LEVEL_W = PNTR_W+1; // +1 extra bit
|
77 |
|
|
localparam [LEVEL_W-1:0] EMPTY_VAL = 'b0; // empty value
|
78 |
|
|
localparam [LEVEL_W-1:0] FULL_VAL = 1'b1 << PNTR_W; // full value
|
79 |
|
|
//
|
80 |
|
|
integer s, t;
|
81 |
|
|
//
|
82 |
|
|
reg [LEVEL_W-1:0] level[0:STACKS-1][0:THREADS-1];
|
83 |
|
|
//
|
84 |
|
|
reg [STACKS-1:0] pop_1, push_1, push_2;
|
85 |
|
|
reg [STACKS-1:0] empty_1, full_2;
|
86 |
|
|
wire [STACKS-1:0] dec_1, inc_2;
|
87 |
|
|
wire [STACKS-1:0] pop_er_1, push_er_2;
|
88 |
|
|
|
89 |
|
|
|
90 |
|
|
/*
|
91 |
|
|
================
|
92 |
|
|
== code start ==
|
93 |
|
|
================
|
94 |
|
|
*/
|
95 |
|
|
|
96 |
|
|
|
97 |
|
|
// pipeline control signals
|
98 |
|
|
always @ ( posedge clk_i or posedge rst_i ) begin
|
99 |
|
|
if ( rst_i ) begin
|
100 |
|
|
pop_1 <= 'b0;
|
101 |
|
|
push_1 <= 'b0;
|
102 |
|
|
push_2 <= 'b0;
|
103 |
|
|
end else begin
|
104 |
|
|
pop_1 <= pop_i;
|
105 |
|
|
push_1 <= push_i;
|
106 |
|
|
push_2 <= push_1;
|
107 |
|
|
end
|
108 |
|
|
end
|
109 |
|
|
|
110 |
|
|
// decode watermarks
|
111 |
|
|
always @ ( * ) begin
|
112 |
|
|
for ( s=0; s<STACKS; s=s+1 ) begin
|
113 |
|
|
empty_1[s] <= ( level[s][1] == EMPTY_VAL );
|
114 |
|
|
full_2[s] <= ( level[s][2] == FULL_VAL );
|
115 |
|
|
end
|
116 |
|
|
end
|
117 |
|
|
|
118 |
|
|
// prohibit pointer changes @ errors if configured to do so
|
119 |
|
|
assign dec_1 = ( PROT_POP ) ? pop_1 & ~empty_1 : pop_1;
|
120 |
|
|
assign inc_2 = ( PROT_PUSH ) ? push_2 & ~full_2 : push_2;
|
121 |
|
|
|
122 |
|
|
// decode errors - pop when empty, push when full
|
123 |
|
|
assign pop_er_1 = pop_1 & empty_1;
|
124 |
|
|
assign push_er_2 = push_2 & full_2;
|
125 |
|
|
|
126 |
|
|
// decode & pipeline levels
|
127 |
|
|
always @ ( posedge clk_i or posedge rst_i ) begin
|
128 |
|
|
if ( rst_i ) begin
|
129 |
|
|
for ( s=0; s<STACKS; s=s+1 ) begin
|
130 |
|
|
for ( t=0; t<THREADS; t=t+1 ) begin
|
131 |
|
|
level[s][t] <= 'b0;
|
132 |
|
|
end
|
133 |
|
|
end
|
134 |
|
|
end else begin
|
135 |
|
|
for ( s=0; s<STACKS; s=s+1 ) begin
|
136 |
|
|
for ( t=0; t<THREADS; t=t+1 ) begin
|
137 |
|
|
if ( t == 0 ) level[s][t] <= level[s][THREADS-1]; // wrap around
|
138 |
|
|
else if ( t == 1 ) level[s][t] <= ( clr_i ) ? 1'b0 : level[s][t-1]; // clear
|
139 |
|
|
else if ( t == 2 ) level[s][t] <= ( dec_1[s] ) ? level[s][t-1] - 1'b1 : level[s][t-1]; // pop
|
140 |
|
|
else if ( t == 3 ) level[s][t] <= ( inc_2[s] ) ? level[s][t-1] + 1'b1 : level[s][t-1]; // push
|
141 |
|
|
else level[s][t] <= level[s][t-1];
|
142 |
|
|
end
|
143 |
|
|
end
|
144 |
|
|
end
|
145 |
|
|
end
|
146 |
|
|
|
147 |
|
|
|
148 |
|
|
// decode & pipeline write enables
|
149 |
|
|
pipe
|
150 |
|
|
#(
|
151 |
|
|
.DEPTH ( 4 ),
|
152 |
|
|
.WIDTH ( STACKS ),
|
153 |
|
|
.RESET_VAL ( 0 )
|
154 |
|
|
)
|
155 |
|
|
wr_pipe
|
156 |
|
|
(
|
157 |
|
|
.clk_i ( clk_i ),
|
158 |
|
|
.rst_i ( rst_i ),
|
159 |
|
|
.data_i ( inc_2 ),
|
160 |
|
|
.data_o ( wr_6_o )
|
161 |
|
|
);
|
162 |
|
|
|
163 |
|
|
|
164 |
|
|
// register output errors
|
165 |
|
|
pipe
|
166 |
|
|
#(
|
167 |
|
|
.DEPTH ( 1 ),
|
168 |
|
|
.WIDTH ( STACKS+STACKS ),
|
169 |
|
|
.RESET_VAL ( 0 )
|
170 |
|
|
)
|
171 |
|
|
reg_errors
|
172 |
|
|
(
|
173 |
|
|
.clk_i ( clk_i ),
|
174 |
|
|
.rst_i ( rst_i ),
|
175 |
|
|
.data_i ( { pop_er_1, push_er_2 } ),
|
176 |
|
|
.data_o ( { pop_er_2_o, push_er_3_o } )
|
177 |
|
|
);
|
178 |
|
|
|
179 |
|
|
|
180 |
|
|
// output pointers
|
181 |
|
|
assign pntr0_6_o = level[0][6][PNTR_W-1:0];
|
182 |
|
|
assign pntr1_6_o = level[1][6][PNTR_W-1:0];
|
183 |
|
|
assign pntr2_6_o = level[2][6][PNTR_W-1:0];
|
184 |
|
|
assign pntr3_6_o = level[3][6][PNTR_W-1:0];
|
185 |
|
|
assign pntr4_6_o = level[4][6][PNTR_W-1:0];
|
186 |
|
|
assign pntr5_6_o = level[5][6][PNTR_W-1:0];
|
187 |
|
|
assign pntr6_6_o = level[6][6][PNTR_W-1:0];
|
188 |
|
|
assign pntr7_6_o = level[7][6][PNTR_W-1:0];
|
189 |
|
|
|
190 |
|
|
|
191 |
|
|
endmodule
|