summaryrefslogtreecommitdiff
path: root/rtl/core/control/data.sv
blob: cc83336e666a2fc37285ae4e5eb9abccb52ea05a (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
`include "core/uarch.sv"

module core_control_data
(
	input  logic           clk,

	input  data_decode     dec_data,
	input  snd_decode      dec_snd,
	input  word            rd_value_a,
	                       rd_value_b,
	input  logic           mem_ready,
	input  word            q_alu,
	                       q_shifter,
	input  logic           c_shifter,

	input  ctrl_cycle      cycle,
	                       next_cycle,
	input  logic           issue,
	input  ptr             pc,
	input  word            mem_offset,
	input  psr_flags       flags,

	output alu_op          alu,
	output word            alu_a,
	                       alu_b,
	                       saved_base,
	output shifter_control shifter,
	output logic[7:0]      shifter_shift,
	output logic           c_in,
	                       trivial_shift,
	                       data_snd_shift_by_reg
);

	logic data_snd_is_imm;
	logic[5:0] data_shift_imm;
	logic[11:0] data_imm;

	assign trivial_shift = shifter_shift == 0;

	always_comb begin
		unique case(cycle)
			RD_INDIRECT_SHIFT: shifter_shift = rd_value_b[7:0];
			default:           shifter_shift = {2'b00, data_shift_imm};
		endcase

		unique case(cycle)
			TRANSFER:  alu_a = saved_base;
			EXCEPTION: alu_a = {pc, 2'b00};
			default:   alu_a = rd_value_a;
		endcase

		unique case(cycle)
			RD_INDIRECT_SHIFT, WITH_SHIFT:
				alu_b = saved_base;

			TRANSFER:
				alu_b = mem_offset;

			default:
				if(data_snd_is_imm)
					alu_b = {{20{1'b0}}, data_imm};
				else
					alu_b = rd_value_b;
		endcase
	end

	always @(posedge clk)
		unique0 case(next_cycle)
			ISSUE:
				if(issue) begin
					alu <= dec_data.op;
					c_in <= flags.c;

					data_snd_is_imm <= dec_snd.is_imm;
					data_snd_shift_by_reg <= dec_snd.shift_by_reg;
					data_imm <= dec_snd.imm;
					data_shift_imm <= dec_snd.shift_imm;

					shifter.shr <= dec_snd.shr;
					shifter.ror <= dec_snd.ror;
					shifter.put_carry <= dec_snd.put_carry;
					shifter.sign_extend <= dec_snd.sign_extend;
				end

			RD_INDIRECT_SHIFT: begin
				saved_base <= rd_value_b;
				data_snd_shift_by_reg <= 0;
			end

			WITH_SHIFT: begin
				c_in <= c_shifter;
				saved_base <= q_shifter;
			end

			TRANSFER:
				if(cycle != TRANSFER || mem_ready)
					saved_base <= q_alu;

			EXCEPTION: begin
				alu <= `ALU_ADD;
				data_imm <= 12'd4;
				data_snd_is_imm <= 1;
			end
		endcase

	initial begin
		alu = {$bits(alu){1'b0}};
		c_in = 0;
		shifter = {$bits(shifter){1'b0}};
		data_imm = {$bits(data_imm){1'b0}};
		data_shift_imm = {$bits(data_shift_imm){1'b0}};
		data_snd_is_imm = 0;
		data_snd_shift_by_reg = 0;
	end

endmodule