aboutsummaryrefslogtreecommitdiffstats
path: root/sources/hdl/verilog/register_file.v
blob: 2d3b6933703b6a9895b7085f7ac5a2f13cd6bb87 (plain) (blame)
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
`include "parameters.vh"

/* 
 * An 8 read 8 write port reg file
 * satisfying ddr pipeline's needs
 */
module register_file(

  // common signals
  input           clk,
  input           rst,

  // execute stage <-> reg file if
  input                                rf_wide_wen,
  input   [3:0]                        rf_wide_offset,
  output  [511:0]                      rf_wide_data,
  output  [32*8-1:0]                   rf_rdata,
  input   [32*8-1:0]                   rf_wdata,
  input   [7:0]                        rf_wen,
  input   [4*8-1:0]                    rf_raddr,
  input   [4*8-1:0]                    rf_waddr,
  output  [`COL_WIDTH-1:0]             casr,
  output  [`BANK_WIDTH+`BG_WIDTH-1:0]  basr,
  output  [`ROW_WIDTH-1:0]             rasr,
  // update stride registers, wen is OH (3'b001 = update rasr)
  input   [31:0]                       srf_value,
  input   [2:0]                        srf_wen
  );

  // Stride registers
  reg [31:0] casr_r, basr_r, rasr_r;

  assign casr = casr_r;
  assign basr = basr_r;
  assign rasr = rasr_r;

  // Update stride registers
  always @(posedge clk) begin
    if(srf_wen[0]) begin
      casr_r <= srf_value;
    end
    if(srf_wen[1]) begin
      basr_r <= srf_value;
    end
    if(srf_wen[2]) begin
      rasr_r <= srf_value;
    end
  end

  // General purpose registers
  reg [31:0] reg_file [15:0];
  
  // split r&w data signals into human readable form
  // also drive rdata with appropriate register values
  wire [31:0] wdata [7:0];
  wire        wen   [7:0];
  wire [3:0]  waddr [7:0];
  wire [3:0]  raddr [7:0];
  genvar i;
  generate
    for(i = 0 ; i < 8 ; i = i + 1) begin: gen_ports
      assign wdata[i] = rf_wdata[32*i +: 32];
      assign wen[i]   = rf_wen[i];
      assign waddr[i] = rf_waddr[4*i +: 4];
      assign raddr[i] = rf_raddr[4*i +: 4];
      // TODO will this compile?
      assign rf_rdata[32*i +: 32] = raddr[i] == 0 ? casr_r : 
        raddr[i] == 1 ? basr_r : 
        raddr[i] == 2 ? rasr_r : reg_file[raddr[i]];
    end
  endgenerate

  integer j;
  // Write to the register file
  always @(posedge clk) begin
    for(j = 0 ; j < 8 ; j = j+1) begin: regfile_write
      if(wen[j])
        reg_file[waddr[j]] <= wdata[j];
    end
  end
  
  // DDR4 8-burst write data register
  reg [511:0] wide_reg;
  always @(posedge clk) begin
    // TODO this probably won't compile
    if(rf_wide_wen)
      wide_reg[rf_wide_offset*32 +: 32] <= wdata[0];
  end
 
  assign rf_wide_data = wide_reg; 

endmodule