summaryrefslogtreecommitdiff
path: root/rtl/core/control/writeback.sv
blob: 15b17ee944ab895475b212c14d3df9fd0293f24e (plain)
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
`include "core/uarch.sv"

module core_control_writeback
(
	input  logic           clk,

	input  datapath_decode dec,
	input  data_decode     dec_data,

	input  ctrl_cycle      cycle,
	                       next_cycle,
	input  word            saved_base,
	                       mem_data_rd,
	                       vector,
	                       q_alu,
	input  psr_flags       alu_flags,
	input  reg_num         ra,
	                       popped,
	input  logic           pop_valid,
	                       issue,
	                       mem_ready,
	                       mem_write,

	output reg_num         rd,
	                       final_rd,
	output logic           writeback,
	                       final_writeback,
	                       update_flags,
	                       final_update_flags,
	output word            wr_value,
	output psr_flags       wb_alu_flags
);

	always_ff @(posedge clk) begin
		wb_alu_flags <= alu_flags;

		unique0 case(next_cycle)
			TRANSFER:
				if(mem_ready)
					rd <= final_rd;

			ISSUE, BASE_WRITEBACK:
				rd <= final_rd;

			EXCEPTION:
				rd <= `R15;
		endcase

		unique0 case(next_cycle)
			ISSUE:
				if(issue)
					final_rd <= dec_data.rd;

			TRANSFER:
				if((cycle != TRANSFER || mem_ready) && pop_valid)
					final_rd <= popped;

			BASE_WRITEBACK:
				final_rd <= ra;

			EXCEPTION:
				final_rd <= `R14;
		endcase

		writeback <= 0;
		unique0 case(next_cycle)
			ISSUE:
				writeback <= final_writeback;

			TRANSFER:
				writeback <= mem_ready && !mem_write;

			BASE_WRITEBACK:
				writeback <= !mem_write;

			EXCEPTION:
				writeback <= 1;
		endcase

		unique0 case(next_cycle)
			ISSUE:
				final_writeback <= issue && dec.writeback;

			EXCEPTION:
				final_writeback <= 1;
		endcase

		unique case(cycle)
			TRANSFER:       wr_value <= mem_data_rd;
			BASE_WRITEBACK: wr_value <= saved_base;
			default:        wr_value <= q_alu;
		endcase

		update_flags <= 0;
		unique0 case(next_cycle)
			ISSUE:
				update_flags <= final_update_flags;

			EXCEPTION:
				final_update_flags <= 0;
		endcase

		unique0 case(next_cycle)
			ISSUE:
				final_update_flags <= issue && dec.update_flags;

			EXCEPTION:
				final_update_flags <= 0;
		endcase

		unique0 case(next_cycle)
			TRANSFER:
				if(mem_ready)
					wr_value <= mem_data_rd;

			BASE_WRITEBACK:
				wr_value <= mem_data_rd;

			EXCEPTION:
				wr_value <= vector;
		endcase
	end

	initial begin
		rd = 0;
		final_rd = 0;

		writeback = 0;
		final_writeback = 0;

		update_flags = 0;
		final_update_flags = 0;

		wr_value = 0;
		wb_alu_flags = {$bits(wb_alu_flags){1'b0}};
	end

endmodule