~ruther/verilog-riscv-semestral-project

ref: 79c7be5c1c8ae2aea07f48d32abca650d24e8045 verilog-riscv-semestral-project/src/cpu.sv -rw-r--r-- 3.5 KiB
79c7be5c — Rutherther chore: remove unnecessary executable flags 1 year, 3 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
148
149
import cpu_types::*;

module cpu(
  input             clk,
  input             rst_n,

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

  // ram
  output [31:0]     memory_address,
  input [31:0]      memory_read,
  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_rs1, reg_rs2;
  reg [31:0]  reg_write;
  wire        reg_we;

  reg        all_stages_ready;

  wire        jump;
  wire [31:0] jumping_pc_next;

  stage_status_t fetch_out;
  stage_status_t decode_out;
  stage_status_t execute_out;
  stage_status_t memory_access_out;

  stage_status_t decode_in;
  stage_status_t execute_in;
  stage_status_t memory_access_in;
  stage_status_t writeback_in;

  assign ebreak = memory_access_out.instruction.ebreak;

  // stage registers
  always_ff @(posedge clk) begin
    if (rst_n == 0) begin
      decode_in.data.target = 0;
      execute_in.data.target = 0;
      memory_access_in.data.target = 0;
      writeback_in.data.target = 0;
    end
    else begin
      if (decode_out.ready && execute_out.ready && memory_access_out.ready)
        decode_in = fetch_out;
      if (execute_out.ready && memory_access_out.ready)
        execute_in = decode_out;
      if (memory_access_out.ready)
        memory_access_in = execute_out;
      writeback_in = memory_access_out;
    end
  end

  assign all_stages_ready = fetch_out.ready && decode_out.ready && execute_out.ready && memory_access_out.ready;

  always_comb begin
    if (!all_stages_ready)
      pc_next = pc;
    else if (jump)
      pc_next = jumping_pc_next;
    else // assume no jump. If jump, if result will be thrown out
      pc_next = fetch_out.pc_plus_4;
  end

  // data for forwarding from the stages
  // Note: this is a record instead of an array
  // just because verilator didn't like it as an array
  // consider switching back to array.
  forwarding_data_status_t data_in_pipeline;
  assign data_in_pipeline.execute_out = execute_out.data;
  assign data_in_pipeline.access_out = memory_access_out.data;
  assign data_in_pipeline.writeback_in = writeback_in.data;

  fetch fetch_inst(
    .clk(clk),
    .pc(pc),
    .flush(jump),
    .mem_instruction(instruction),
    .stage_out(fetch_out)
  );

  decode decode_inst(
    .clk(clk),
    .flush(jump),
    .data_in_pipeline(data_in_pipeline),
    .reg_a_1(reg_a_1),
    .reg_a_2(reg_a_2),
    .reg_rs1(reg_rs1),
    .reg_rs2(reg_rs2),
    .stage_in(decode_in),
    .stage_out(decode_out)
  );

  execute execute_inst(
    .clk(clk),
    .jump(jump),
    .jump_pc(jumping_pc_next),
    .stage_in(execute_in),
    .stage_out(execute_out)
  );

  memory_access memory_access_inst(
    .clk(clk),
    .memory_read(memory_read),
    .memory_byte_enable(memory_byte_enable),
    .memory_write(memory_write),
    .memory_we(memory_we),
    .memory_address(memory_address),
    .stage_in(memory_access_in),
    .stage_out(memory_access_out)
  );

  writeback writeback_inst(
    .clk(clk),
    .reg_a_write(reg_a_w),
    .reg_we(reg_we),
    .reg_write(reg_write),
    .stage_in(writeback_in)
  );

  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_rs1),
    .rd2(reg_rs2)
  );

  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