~ruther/verilog-riscv-semestral-project

ref: 489df84930a405a04e27485ed89e224ec6fab8b1 verilog-riscv-semestral-project/src/cpu.sv -rwxr-xr-x 3.4 KiB
489df849 — Rutherther chore: import cpu types in stages 1 year, 4 months ago
                                                                                
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import cpu_types::*;

module cpu(
  input             clk,
  input             rst_n,

  // program memory
  input [31:0]      instruction,
  output reg [31:0] pc,

  // ram
  output [31:0]     memory_address,
  input [31:0]      memory_out,
  output [31:0]     memory_write,
  output [3:0]      memory_byte_enable,
  output            memory_we,

  output            ebreak
);
  parameter WIDTH = 32;

  reg [31:0]  pc_next;

  wire [4:0]  reg_a_1, reg_a_2, reg_a_w;
  wire [31:0] reg_rd1, reg_rd2;
  reg [31:0]  reg_write;
  wire        reg_we;

  reg [2:0]  last_non_ready_stage;
  reg        all_stages_ready;

  wire        jump;
  wire [31:0] jumping_pc_next;

  stage_status_t stages_in[1:4];
/* verilator lint_off UNOPTFLAT */
  stage_status_t stages_out[0:3];
/* verilator lint_on UNOPTFLAT */

  assign ebreak = stages_out[ACCESS].instruction.ebreak;

  // stage registers
  always_ff @(posedge clk) begin
    if (rst_n == 0) begin
      for (int i = 0; i < $size(stages_in); i++) begin
        stages_in[i].data.address = 0;
      end
    end
    else begin
      for (int i = 0; i < $size(stages_in); i++) begin
        if (all_stages_ready || i >= last_non_ready_stage) begin
          stages_in[i + 1] = stages_out[i];
        end
      end
    end
  end

  // find first non ready stage. Stages before that will be stalled
  always_comb begin
    last_non_ready_stage = 0;
    all_stages_ready = 1'b1;
    for (int i = 0; i < $size(stages_out); i++) begin
      if (!stages_out[i].ready) begin
        last_non_ready_stage = i[2:0];
        all_stages_ready = 1'b0;
      end
    end
  end

  always_comb begin
    if (jump)
      pc_next = jumping_pc_next;
    else if (all_stages_ready) // assume no jump. If jump, if result will be thrown out
      pc_next = pc + 4;
    else // stalling (in any stage, meaning not fetching new instructions)
      pc_next = pc;
  end

  forwarding_data_status_t data_in_pipeline;
  assign data_in_pipeline.execute_out = stages_out[EXECUTE].data;
  assign data_in_pipeline.access_out = stages_out[ACCESS].data;
  assign data_in_pipeline.writeback_in = stages_in[WRITEBACK].data;

  fetch fetch_inst(
    .clk(clk),
    .pc(pc),
    .mem_instruction(instruction),
    .jump(jump),
    .stage_out(stages_out[FETCH])
  );

  decode decode_inst(
    .clk(clk),
    .data_in_pipeline(data_in_pipeline),
    .reg_a_1(reg_a_1),
    .reg_a_2(reg_a_2),
    .reg_rd1(reg_rd1),
    .reg_rd2(reg_rd2),
    .jump(jump),
    .pc_next(jumping_pc_next),
    .stage_in(stages_in[DECODE]),
    .stage_out(stages_out[DECODE])
  );

  execute execute_inst(
    .clk(clk),
    .stage_in(stages_in[EXECUTE]),
    .stage_out(stages_out[EXECUTE])
  );

  memory_access memory_access_inst(
    .clk(clk),
    .memory_out(memory_out),
    .memory_byte_enable(memory_byte_enable),
    .memory_write(memory_write),
    .memory_we(memory_we),
    .memory_address(memory_address),
    .stage_in(stages_in[ACCESS]),
    .stage_out(stages_out[ACCESS])
  );

  writeback writeback_inst(
    .clk(clk),
    .reg_a_write(reg_a_w),
    .reg_we(reg_we),
    .reg_write(reg_write),
    .stage_in(stages_in[WRITEBACK])
  );

  register_file #(.WIDTH(WIDTH), .ADDRESS_LENGTH(5)) register_file_inst(
    .clk(clk),
    .a1(reg_a_1),
    .a2(reg_a_2),
    .a3(reg_a_w),
    .we3(reg_we),
    .wd3(reg_write),
    .rd1(reg_rd1),
    .rd2(reg_rd2)
  );

  program_counter program_counter_inst(
    .clk(clk),
    .rst_n(rst_n),
    .pc(pc[11:0]),
    .pc_next(pc_next[11:0])
  );
endmodule
Do not follow this link