§ Программа на Verilog

Здесь будут коды процессора.
Ревизия #5 :: 17 авг 2024 + INC, DEC d
Ревизия #6 :: 20 авг 2024 + ROR d,u; ROR d,i
1/* verilator lint_off WIDTHTRUNC */
2/* verilator lint_off WIDTHEXPAND */
3/* verilator lint_off CASEX */
4/* verilator lint_off CASEINCOMPLETE */
5
6module core
7(
8    input               clock,          // Тактовая частота 25 мгц
9    input               reset_n,        // Сброс процессора
10    input               ce,             // ChipEnabled
11    output      [7:0]   address,        // Адрес
12    input       [7:0]   in,             // Данные
13    output reg  [7:0]   wb,             // Что писать в память или регистр
14    output reg          we,             // Запрос записи в память
15    output reg          rr              // Запрос чтения из памяти
16);
17
18assign address = mm ? cp : pc;
19
20localparam
21
22    ADD = 2'b00, SUB = 2'b01, AND = 2'b10, XOR = 2'b11,
23    TST = 2'b00, ORI = 2'b01;
24
25// Список всех регистров
26// ---------------------------------------------------------------------
27reg [1:0]   t;
28reg         mm, rw;
29reg [1:0]   rn;             // Номер регистра для записи
30reg [7:0]   opc, pc, cp;    // Опкод, Program Counter, Current Pointer
31reg [7:0]   a  = 8'h71,
32            b  = 8'h23,
33            x  = 8'h52,
34            y  = 8'hAF;
35reg         zf = 1'b0,      // Флаг нуля
36            cf = 1'b0;      // Флаг переноса
37
38// Предвычисления
39// ---------------------------------------------------------------------
40wire [7:0]  opcode  = t ? opc : in;
41wire [7:0]  pcn     = pc + 1;
42
43// Именование проводов
44wire [1:0]  dst = opcode[1:0],
45            src = opcode[3:2],
46            o54 = opcode[5:4];
47wire        o0  = opcode[0], o1 = opcode[1], o2 = opcode[2],
48            o3  = opcode[3], o4 = opcode[4], o5 = opcode[5],
49            o7  = opcode[7];
50
51// Регистр слева
52wire [7:0]  rd = dst == 2'b00 ? a : dst == 2'b01 ? b : dst == 2'b10 ? x : y;
53wire [7:0]  rs = src == 2'b00 ? a : src == 2'b01 ? b : src == 2'b10 ? x : y;
54wire [8:0] alu = o54 == ADD ? (rd + rs) : o54 == SUB ? (rd - rs) : o54 == AND ? (rd & rs) : (rd ^ rs);
55wire [8:0] asb = src == ADD ? (rd + in) : rd - in;
56wire [7:0] lgc = src == ORI ? (rd | in) : src == XOR ? (rd ^ in) : (rd & in);
57wire [8:0] inc = o2 ? rd - 1 : rd + 1;
58
59// ROR d,s :: ROR d,u
60wire [16:0] ror = {rd, rd, rd[0]} >> (o7 ? in[2:0] : rs[2:0]);
61// ---------------------------------------------------------------------
62
63always @(posedge clock)
64if (reset_n == 1'b0) begin
65
66    t  <= 0;
67    pc <= 0;
68    mm <= 0;
69    rw <= 0;
70    rr <= 0;
71
72end
73// Исполнение опкодов
74else if (ce) begin
75
76    we <= 0;
77    rw <= 0;
78    rr <= 0;
79    rn <= dst;
80
81    // Сохранить опкод
82    if (t == 0) opc <= in;
83
84    casex (opcode)
85
86    // 1T 00 MOV d, s
87    // 2T 01 MOV d, [s]
88    // 3T 10 MOV [d], s
89    // 3T 11 MOV [d], [s]
90    8'b00xx_xxxx: case (t)
91
92        0: begin
93
94            t  <= |o54;         // Если есть обращение к памяти
95            mm <= |o54;         // То установить указатель
96            rw <= o54 == 0;     // Если нет памяти, то регистр S => D
97            rr <= o4;           // Запрос чтения из памяти
98            cp <= rs;           // Указатель на чтение из памяти
99            wb <= rs;           // Либо запись в регистр, если RW=1
100            pc <= pcn;
101
102        end
103
104        1: begin
105
106            t  <= o5 ? 2 : 0;   // Запись и убрать MM
107            wb <= o4 ? in : rs; // Что писать
108            mm <=  o5;          // Убрать mm, если в регистр
109            we <=  o5;          // Либо в память
110            rw <= !o5;          // Запись в регистр
111            cp <=  rd;          // И куда писать в память
112
113        end
114
115        2: begin t <= 0; mm <= 0; end
116
117    endcase
118
119    // 2T 00 MOV d,u
120    // 3T 01 MOV d,[u]
121    // 4T 10 MOV [d],u
122    // 4T 11 MOV [d],[u]
123    8'b0100_xxxx: case (t)
124
125        0: begin t <= o2 ? 1 : 2; pc <= pcn; end
126        1: begin t <= 2; mm <= 1; cp <= in; rr <= 1; end
127        2: begin
128
129            t  <= src ? 3 : 0;      // Выбрана память
130            rw <= !o3;              // Запись в регистр
131            mm <=  o3;              // Выбрать cp, если есть запись
132            we <=  o3;              // Или запись в память
133            wb <=  in;              // Что писать
134            cp <=  rd;              // Запись в [d]
135            pc <= pcn;
136
137        end
138
139        3: begin t <= 0; mm <= 0; end
140
141    endcase
142
143    // 3T 0 MOV [u],d
144    // 4T 1 MOV [u],[d]
145    8'b0101_1xxx: case (t)
146
147        0: begin t <= o2 ? 1 : 2; pc <= pcn; end
148        1: begin t <= 2; mm <= 1; cp <= rd;  wb <= in; rr <= 1; end
149        2: begin
150
151            t  <= 3;
152            mm <= 1;
153            we <= 1;
154            wb <= o2 ? in : rd; // [d] или d
155            cp <= o2 ? wb : in; // [u]
156            pc <= pcn;
157
158        end
159        3: begin t <= 0; mm <= 0; end
160
161    endcase
162
163    // 2T ADD d, u
164    // 2T CMP d, u
165    8'b0101_0xxx: case (t)
166
167        0: begin t <= 1; pc <= pcn; end
168        1: begin t <= 0; pc <= pcn; rw <= !o2; wb <= asb; {cf, zf} <= {asb[8], asb[7:0] == 0}; end
169
170    endcase
171
172    // 1T ROR d, s
173    8'b0110_xxxx: begin
174
175        rw <= 1;                // Запись в регистр
176        pc <= pcn;
177        wb <= ror[8:1];         // Результат сдвига
178        zf <= ror[8:1] == 0;    // Если 0
179        cf <= ror[0];           // Есть перенос
180
181    end
182
183    // 2T TST, ORI, AND, XOR d, u
184    8'b0111_xxxx: case (t)
185
186        0: begin t <= 1; pc <= pcn; end
187        1: begin
188
189            t  <= 0;
190            pc <= pcn;
191            rw <= |src;             // Пишется все, кроме TST
192            wb <= lgc;
193            zf <= lgc == 0;
194            cf <= lgc[7];           // Копировать знак => CF
195
196        end
197
198    endcase
199
200    // 1T ADD, SUB, AND, XOR
201    8'b10xx_xxxx: begin
202
203        rw <= 1;
204        pc <= pcn;
205        wb <= alu;                  // Записать результат в регистр
206        cf <= alu[o5 ? 7 : 8];      // Логические копируют 7й бит
207        zf <= alu[7:0] == 0;        // Всем проставлять ZF
208
209    end
210
211    // 2T Jcc u
212    // 2T JMP u
213    // 2T JMP d, u
214    8'b1100_00xx,
215    8'b1100_1000,
216    8'b1100_11xx: case (t)
217
218        0: begin t <= 1; pc <= pcn; end
219        1: begin
220
221            t  <= 0;
222            pc <= ((o1 ? zf : cf) == o0) || o3 ? in : pcn;
223            rw <= &src;
224            wb <= pcn;
225
226        end
227
228    endcase
229
230    // 1T JMP d
231    8'b1100_01xx: begin pc <= rd; end
232
233    // CLC, CMC
234    8'b1100_1010: begin cf <= cf & 0; end
235    8'b1100_1011: begin cf <= cf ^ 1; end
236
237    // 1T INC|DEC d
238    8'b1101_0xxx: begin
239
240        pc <= pcn;
241        rw <= 1;
242        wb <= inc[7:0];
243        cf <= inc[8];
244        zf <= inc[7:0] == 0;
245
246    end
247
248    // 2T ROR d,u
249    // 3T ROR d,[u]
250    8'b1101_10xx: case (t)
251
252        0: begin t <= o2 ? 1 : 2; pc <= pcn; end
253        1: begin t <= 2; mm <= 1; cp <= in; end
254        2: begin
255
256            t  <= 0;
257            rw <= 1;
258            pc <= pcn;
259            wb <= ror[8:1];
260            zf <= ror[8:1] == 0;
261            cf <= ror[0];
262
263        end
264
265    endcase
266
267    endcase
268
269end
270
271// Запись в регистры
272always @(negedge clock)
273begin
274
275    if (rw)
276    case (rn)
277    2'b00: a <= wb; 2'b01: b <= wb;
278    2'b10: x <= wb; 2'b11: y <= wb;
279    endcase
280
281end
282
283endmodule