blob: ad0fd52def6c35747f67199a467c3122dd47f9bd (
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
`timescale 1us/1us
`include "eater_types.sv"
module eater_decoder (
input clk_i,
input wire [7:0] instruction_i,
output CpuControlFlags flags_o
);
CpuState internal_state /* verilator public_flat_rd */;
CpuState next_state;
CpuControlFlags internal_flags;
wire [3:0] actual_instruction = instruction_i[7:4];
assign flags_o = internal_flags;
initial begin
internal_state = INIT;
next_state = INIT;
// assigned in always_comb
// internal_flags = '{default: '0};
end
function CpuState insdep_state;
case (actual_instruction)
NOP: insdep_state = PC_to_MAR;
LDA: insdep_state = LDA_INS_to_MAR;
ADD: insdep_state = ADD_INS_to_MAR;
SUB: insdep_state = SUB_INS_to_MAR;
OUT: insdep_state = OUT_A_to_OUT;
HALT_op: insdep_state = HALT_st;
default: insdep_state = INIT;
endcase
endfunction
// next-state machine
always @(posedge clk_i) begin
next_state = INIT;
case (internal_state)
INIT: next_state = PC_to_MAR;
PC_to_MAR: next_state = MEM_to_INS;
MEM_to_INS: next_state = PC_inc;
PC_inc: next_state = insdep_state();
LDA_INS_to_MAR: next_state = LDA_MEM_to_A;
LDA_MEM_to_A: next_state = PC_to_MAR;
ADD_INS_to_MAR: next_state = ADD_MEM_to_B;
ADD_MEM_to_B: next_state = ADD_ALU_to_A;
ADD_ALU_to_A: next_state = PC_to_MAR;
SUB_INS_to_MAR: next_state = SUB_MEM_to_B;
SUB_MEM_to_B: next_state = SUB_ALU_to_A;
SUB_ALU_to_A: next_state = PC_to_MAR;
OUT_A_to_OUT: next_state = PC_to_MAR;
HALT_st: next_state = HALT_st;
default: begin
next_state = INIT;
end
endcase
internal_state <= next_state;
end
// current-state-to-flags machine
// TODO: This is kinda weird, I *can* set "all flags" to zero "in the beginning",
// and then only set the required flags "later".
// how does that work combinatorically???
always_comb begin
`ifdef IVERILOG
internal_flags = 'b0;
`else
internal_flags = '{default: '0};
`endif
case (internal_state)
// INIT: // left out
PC_to_MAR: begin
internal_flags.PC_out = 1;
internal_flags.MAR_in = 1;
end
MEM_to_INS: begin
internal_flags.RAM_out = 1;
internal_flags.INS_in = 1;
end
PC_inc: begin
internal_flags.PC_count = 1;
end
LDA_INS_to_MAR: begin
internal_flags.INS_out = 1;
internal_flags.MAR_in = 1;
end
LDA_MEM_to_A: begin
internal_flags.RAM_out = 1;
internal_flags.A_in = 1;
end
ADD_INS_to_MAR: begin
internal_flags.INS_out = 1;
internal_flags.MAR_in = 1;
end
ADD_MEM_to_B: begin
internal_flags.RAM_out = 1;
internal_flags.B_in = 1;
end
ADD_ALU_to_A: begin
internal_flags.ALU_out = 1;
internal_flags.A_in = 1;
end
SUB_INS_to_MAR: begin
internal_flags.INS_out = 1;
internal_flags.MAR_in = 1;
end
SUB_MEM_to_B: begin
internal_flags.RAM_out = 1;
internal_flags.B_in = 1;
end
SUB_ALU_to_A: begin
internal_flags.ALU_out = 1;
internal_flags.ALU_subtract_nadd = 1;
internal_flags.A_in = 1;
end
OUT_A_to_OUT: begin
internal_flags.A_out = 1;
internal_flags.OUT_in = 1;
end
HALT_st: begin
internal_flags.halt = 1;
end
default: begin
end
endcase
end
endmodule
|