-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpc.sv
More file actions
101 lines (83 loc) · 3.86 KB
/
pc.sv
File metadata and controls
101 lines (83 loc) · 3.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// program counter
module pc
#(
parameter BITS=32 // default number of BITS per word
)
(
output logic [BITS-1:0] pc_addr, // current instruction address
input clk, // system clock
input [BITS-7:0] addr, // jump address
input rst_, // system reset
input jmp, // take a jump
input load_instr, // load the next address
input [BITS-1:0] sign_ext_imm, // branch address
input equal, // values equal for branch
input breq, // doing branch on equal
input not_equal, // values not equal for branch
input brne, // doing branch on not equal
input jreg, // jumping to register value
input [BITS-1:0] r1_data, // value read from register file for jreg
input stall_pipe, // stall signal for load-use hazard
// Jump register forwarding inputs
input j_fwd_s4, // Forward from Stage 4 for JR
input j_fwd_s5, // Forward from Stage 5 for JR
input [BITS-1:0] alu_out_s4, // Forwarded data from Stage 4
input [BITS-1:0] reg_wdata, // Forwarded data from Stage 5
// Cache stall input
input cache_stall // stall signal for cache miss
);
localparam logic ZERO = 1'b0;
localparam logic ONE = 1'b1;
// --------------------------------------------------------
// Next-PC building blocks (word-addressed)
// --------------------------------------------------------
logic [BITS-1:0] p1; // pc + 1 (fall-through)
logic beq_taken;
logic bne_taken;
logic br_taken;
logic [BITS-1:0] br_target; // branch target
logic [BITS-1:0] j_target; // jump target
logic [BITS-1:0] jr_target; // jump register
// Mutually exclusive enables - mask each candidate, then OR
logic seq_en;
logic [BITS-1:0] cand_seq;
logic [BITS-1:0] cand_br;
logic [BITS-1:0] cand_j;
logic [BITS-1:0] cand_jr;
logic [BITS-1:0] next_pc;
// Fall-through path: +1 word
assign p1 = pc_addr + {{(BITS-1){ZERO}}, ONE};
// Branch-taken detection
assign beq_taken = breq & equal;
assign bne_taken = brne & not_equal;
assign br_taken = beq_taken | bne_taken;
// Form targets from CURRENT PC (pc_addr), not from p1
assign br_target = pc_addr + sign_ext_imm;
assign j_target = {pc_addr[BITS-1:BITS-4], 2'b00, addr};
// Jump register target with forwarding support
// Priority: Stage 4 > Stage 5 > Register file
assign jr_target = j_fwd_s4 ? alu_out_s4 : // Stage 4 (highest priority)
j_fwd_s5 ? reg_wdata : // Stage 5 (medium priority)
r1_data; // Register file (lowest priority)
// Mutually exclusive enables
assign seq_en = ~(br_taken | jmp | jreg);
assign cand_seq = {BITS{seq_en}} & p1;
assign cand_br = {BITS{br_taken}} & br_target;
assign cand_j = {BITS{jmp}} & j_target;
assign cand_jr = {BITS{jreg}} & jr_target;
assign next_pc = cand_seq | cand_br | cand_j | cand_jr;
// --------------------------------------------------------
// PC register
// --------------------------------------------------------
always_ff @(posedge clk or negedge rst_) begin
if (!rst_) begin
pc_addr <= {BITS{1'b0}};
end else if (load_instr && !stall_pipe && !(cache_stall && !jmp && !jreg && !br_taken)) begin
// Update PC unless:
// - stall_pipe (data hazard)
// - cache_stall AND not taking branch/jump (cache miss on sequential)
pc_addr <= next_pc;
end
// else hold (frozen during stall)
end
endmodule