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
|
`include "core/uarch.sv"
module core_control_cycles
(
input logic clk,
rst_n,
halt,
mul,
ldst,
bubble,
exception,
mem_ready,
mul_add,
mul_long,
mul_ready,
pop_valid,
trivial_shift,
ldst_writeback,
data_snd_shift_by_reg,
output ctrl_cycle cycle,
next_cycle
);
/* qts-qii51007-recommended-hdl.pdf, p. 66
* In Quartus II integrated synthesis, the enumerated type that defines the states for the
* state machine must be of an unsigned integer type as in Example 13–52. If you do not
* specify the enumerated type as int unsigned, a signed int type is used by default. In
* this case, the Quartus II integrated synthesis synthesizes the design, but does not infer
* or optimize the logic as a state machine.
*/
enum int unsigned
{
ISSUE,
RD_INDIRECT_SHIFT,
WITH_SHIFT,
TRANSFER,
BASE_WRITEBACK,
EXCEPTION,
MUL,
MUL_ACC_LD,
MUL_HI_WB
} state, next_state;
// TODO: debe estar escrito de tal forma que Quartus infiera una FSM
assign cycle.issue = state == ISSUE;
assign cycle.rd_indirect_shift = state == RD_INDIRECT_SHIFT;
assign cycle.with_shift = state == WITH_SHIFT;
assign cycle.transfer = state == TRANSFER;
assign cycle.base_writeback = state == BASE_WRITEBACK;
assign cycle.exception = state == EXCEPTION;
assign cycle.mul = state == MUL;
assign cycle.mul_acc_ld = state == MUL_ACC_LD;
assign cycle.mul_hi_wb = state == MUL_HI_WB;
assign next_cycle.issue = next_state == ISSUE;
assign next_cycle.rd_indirect_shift = next_state == RD_INDIRECT_SHIFT;
assign next_cycle.with_shift = next_state == WITH_SHIFT;
assign next_cycle.transfer = next_state == TRANSFER;
assign next_cycle.base_writeback = next_state == BASE_WRITEBACK;
assign next_cycle.exception = next_state == EXCEPTION;
assign next_cycle.mul = next_state == MUL;
assign next_cycle.mul_acc_ld = next_state == MUL_ACC_LD;
assign next_cycle.mul_hi_wb = next_state == MUL_HI_WB;
always_comb begin
next_state = ISSUE;
unique case(state)
ISSUE:
if(exception)
next_state = EXCEPTION;
else if(halt)
next_state = ISSUE;
else if(mul)
next_state = mul_add ? MUL_ACC_LD : MUL;
else if(data_snd_shift_by_reg)
next_state = RD_INDIRECT_SHIFT;
else if(!trivial_shift)
next_state = WITH_SHIFT;
RD_INDIRECT_SHIFT:
if(!trivial_shift)
next_state = WITH_SHIFT;
TRANSFER:
if(!mem_ready || pop_valid)
next_state = TRANSFER;
else if(ldst_writeback)
next_state = BASE_WRITEBACK;
MUL:
if(!mul_ready)
next_state = MUL;
else if(mul_long)
next_state = MUL_HI_WB;
MUL_ACC_LD:
next_state = MUL;
/* Este default evita problemas de sintetizado, ya que Quartus
* asume que los casos mencionados son exhaustivos, provocando
* bugs muy difíciles de depurar. No es lo mismo que si se quita
* default.
*/
default: ;
endcase
if(bubble)
next_state = ISSUE;
else if(next_state == ISSUE && ldst) begin
next_state = TRANSFER;
end
end
always_ff @(posedge clk or negedge rst_n)
state <= !rst_n ? ISSUE : next_state;
endmodule
|