blob: e87a90ad4cd7d8e1ffe4a90b08d42049b82120a3 [file] [log] [blame]
Matt Venndfc149e2022-11-24 16:39:10 +01001///////////////////////////////////////////////////////////////////////////
2// M0 - 16-bit serial SUBLEQ processor
3//
4// Copyright 2022 William Moyes
5//
6// The M0 is a 16-bit, bit serial microprocessor based upon the SUBLEQ
7// architecture. The only external devices needed for operation are a SPI
8// RAM, SPI ROM, and clock source. The entire ROM and RAM are available for
9// user code. All registers and logic are contained within the M0 itself.
10// A transmit UART is included for serial output.
11//
12// See README.md at https://github.com/moyesw/TT02-M0/blob/main/README.md
13// for more information on the M0 architecture.
14//
15// The M0 microarchitecture
16// --------------------------
17// PC - Program counter shift register
18// ADR - Address shift register
19// TMP - Temporary shift register
20//
21// The M0 has a six phase exeuction sequence. Each phase performs
22// one 16-bit access to the SPI bus:
23// Phase 0: ADR <-- mem[PC++]
24// Phase 1: TMP <-- mem[ADR]
25// Phase 2: ADR <-- mem[PC++]
26// Phase 3: TMP <-- mem[ADR] - TMP ;checks if result <= 0
27// Phase 4: mem[ADR] <-- TMP
28// Phase 5: PC <-- mem[PC++] or PC++
29//
30
31`default_nettype none
32`timescale 100us/10ps
33
34
35///////////////////////////////////////////////////////////////////////////
36// SPI Controller
37//
38// 16-bit Address + 16-bit Data controller and timing generator
39//
40module SPIController (
41 // System Interfaces
42 input wire clk,
43 input wire rst,
44
45 // SPI Bus Interfaces
46 output reg CS0,
47 output reg CS1,
48 output reg SPICLK,
49 output reg MOSI,
50 input wire MISO,
51
52 // Input Signals
53 input wire Addr15, // Sampled on Phase 01
54 input wire Read_notWrite, // Sampled on Phase 16
55 input wire Addr, // Sampled on Phase 18[bit0/LSB], 20[bit1], ..., 44[bit13], 46[bit14/MSB], bit 15 not sampled (see Addr15)
56 input wire Data, // Sampled on Phase 50[bit0/LSB], 52[bit1], ..., 78[bit14], 80[bit15/MSB]
57
58
59 // Timing Output Signals
60 output reg ShiftAddr, // Asserted when the Address should be shifted
61 output reg ShiftDataRead, // Asserted when the data register collecting data read from memory should be shifted
62 output reg ShiftDataWrite, // Asserted when the data regsiter providing data to be written to memory should be shifted
63 output reg PresetCarry, // Asserted the clock before data motion starts
64 output reg EndOfPhase, //
65 output reg PrepOutput
66);
67
68 // SPI sequencer
69 reg [6:0] SPIphase;
70 always @(posedge clk) begin
71 if (rst)
72 SPIphase <= 0;
73 else if (SPIphase == 83)
74 SPIphase <= 0;
75 else
76 SPIphase <= SPIphase + 1;
77 end
78
79 // SPI bus signal generator
80 always @(posedge clk) begin
81 if (SPIphase <= 1) begin
82 CS0 <= 1;
83 CS1 <= 1;
84 SPICLK <= 0;
85 MOSI <= 0;
86 end else begin
87 CS0 <= CSreg;
88 CS1 <= !CSreg;
89 if (SPIphase <= 81)
90 SPICLK <= SPIphase[0];
91 else
92 SPICLK <= 0;
93
94 if (SPIphase <= 13)
95 MOSI <= 0;
96 else if (SPIphase <= 15)
97 MOSI <= 1;
98 else if (SPIphase <= 17) begin
99 if (SPIphase[0] == 0)
100 MOSI <= Read_notWrite;
101 end else if (SPIphase <= 47) begin
102 if (SPIphase[0] == 0)
103 MOSI <= Addr;
104 end else if (SPIphase <= 49)
105 MOSI <= 0;
106 else begin
107 if (Read_notWrite)
108 MOSI <= 0;
109 else begin
110 if (SPIphase[0] == 0)
111 MOSI <= Data;
112 end
113 end
114 end
115 end
116
117 // Generate Address Shift Enable Signals
118 always @(posedge clk) begin
119 ShiftAddr <= ((SPIphase >= 18) && (SPIphase <= 48) && (SPIphase[0] == 0));
120 ShiftDataRead <= ((SPIphase >= 51) && (SPIphase <= 81) && (SPIphase[0] == 1) && Read_notWrite);
121 ShiftDataWrite <= ((SPIphase >= 50) && (SPIphase <= 80) && (SPIphase[0] == 0) && !Read_notWrite);
122 PresetCarry <= (SPIphase == 17);
123 EndOfPhase <= (SPIphase == 83);
124 PrepOutput <= (SPIphase == 49);
125 end
126
127 reg CSreg;
128 always @(posedge clk) begin
129 if (SPIphase == 1)
130 CSreg <= Addr15;
131 end
132
133endmodule
134
135
136
137///////////////////////////////////////////////////////////////////////////
138// M0 top level
139//
140module moyes0_top_module (
141 input [7:0] io_in,
142 output [7:0] io_out
143);
144
145 // --- ASIC Inputs ---
146 wire clk = io_in[0]; // System clock (~6000 Hz)
147 wire rst = io_in[1]; // Reset line, active high
148 wire spi_miso= io_in[2]; // SPI bus, ASIC input, target output
149 wire uart_rx = io_in[3]; // Serial port, ASIC Receive
150 wire in4 = io_in[4];
151 wire in5 = io_in[5];
152 wire in6 = io_in[6];
153 wire in7 = io_in[7];
154
155 // --- ASIC Outputs ---
156 wire spi_cs0;
157 wire spi_cs1;
158 wire spi_clk;
159 wire spi_mosi;
160 wire uart_tx;
161 wire out5;
162 wire out6;
163 wire out7;
164
165 wire [7:0] io_out;
166 assign io_out[0] = spi_cs0; // SPI bus, Chip Select for RAM, Words 0000-7FFF
167 assign io_out[1] = spi_cs1; // SPI bus, Chip Select for ROM, Words 8000-FFFF
168 assign io_out[2] = spi_clk; // SPI bus, Clock
169 assign io_out[3] = spi_mosi; // SPI bus, ASIC output, target input
170 assign io_out[4] = uart_tx; // Serial port, ASIC Transmit
171 assign io_out[5] = out5;
172 assign io_out[6] = out6;
173 assign io_out[7] = out7;
174
175 // --- Internal Timing Signals ---
176 wire ShiftAddr;
177 wire ShiftDataRead;
178 wire ShiftDataWrite;
179 wire PresetCarry;
180 wire EndOfPhase;
181 wire PrepOutput;
182
183 // --- SPI Control Signals
184 wire Addr15;
185 wire Read_notWrite;
186 wire SPIAddr;
187 wire SPIDataIn;
188
189 // --- CPU Registers ---
190 reg [15:0] PC;
191 reg [15:0] TMP;
192 reg [15:0] ADR;
193 reg PCCarry;
194 reg TBorrow;
195 reg TZero;
196 reg LEQ;
197
198 assign out7 = !in7; // For bring-up testing, out7 = !in7. No other internal connections
199
200 SPIController spi (
201 // System Interfaces
202 .clk(clk),
203 .rst(rst),
204
205 // SPI Bus Interfaces
206 .CS0(spi_cs0),
207 .CS1(spi_cs1),
208 .SPICLK(spi_clk),
209 .MOSI(spi_mosi),
210 .MISO(spi_miso),
211
212 // Input Signals
213 .Addr15(Addr15),
214 .Read_notWrite(Read_notWrite),
215 .Addr(SPIAddr),
216 .Data(SPIDataIn),
217
218 // Timing Output Signals
219 .ShiftAddr(ShiftAddr),
220 .ShiftDataRead(ShiftDataRead),
221 .ShiftDataWrite(ShiftDataWrite),
222 .PresetCarry(PresetCarry),
223 .EndOfPhase(EndOfPhase),
224 .PrepOutput(PrepOutput)
225 );
226
227 reg [2:0] CPUphase;
228 always @(posedge clk) begin
229 if (rst)
230 CPUphase <= 3'd0;
231 else if (!EndOfPhase)
232 CPUphase <= CPUphase;
233 else begin
234 if (CPUphase == 3'd5)
235 CPUphase <= 3'd0;
236 else
237 CPUphase <= CPUphase + 3'd1;
238 end
239 end
240
241 wire PCphase = (CPUphase == 0) || (CPUphase == 2) || (CPUphase == 5);
242
243 assign Addr15 = PCphase ? PC[15] : ADR[15];
244
245 assign Read_notWrite = (CPUphase != 4);
246
247 always @(posedge clk) begin
248
249 if (rst)
250 PC <= 16'h8000;
251 else begin
252 if (PresetCarry)
253 PCCarry <= 1;
254
255 if (PCphase && ShiftAddr) begin
256 PCCarry <= PC[0] & PCCarry;
257 PC <= {PC[0] ^ PCCarry, PC[15:1]};
258 end
259
260 if ((CPUphase == 5) && ShiftDataRead) begin
261 PC <= {LEQ ? spi_miso : PC[0], PC[15:1]};
262 end
263 end
264 end
265
266 assign SPIAddr = PCphase ? PC[0] : ADR[0];
267
268 assign SPIDataIn = TMP[0];
269
270 wire ReadADR = (CPUphase == 0) || (CPUphase == 2);
271 wire ReadTMP = (CPUphase == 1) || (CPUphase == 3);
272
273 always @(posedge clk) begin
274 if (ReadADR & ShiftDataRead)
275 ADR <= {spi_miso, ADR[15:1]};
276
277 if (!PCphase & ShiftAddr)
278 ADR <= {ADR[0], ADR[15:1]};
279 end
280
281 // Transmit UART
282 reg BwasFFFF;
283 reg UARTout;
284 assign uart_tx = UARTout;
285 reg [4:0] UARTcount;
286 always @(posedge clk) begin
287 if (EndOfPhase) begin
288 BwasFFFF <= 1;
289 UARTout <= 1;
290 UARTcount <= 0;
291 end
292
293 if (ShiftAddr & !ADR[0])
294 BwasFFFF <= 0;
295
296 if (BwasFFFF & (CPUphase == 3)& PrepOutput) begin
297 UARTout <= 0;
298 UARTcount <= 9;
299 end
300
301 if ((UARTcount != 0) & ShiftDataRead) begin
302 UARTcount <= UARTcount - 1;
303 UARTout <= (UARTcount != 1) ? TMP[0] : 1;
304 end;
305
306 end
307
308
309 wire sub_b;
310 wire sub_r;
311 assign {sub_b, sub_r} = spi_miso - TMP[0] - TBorrow;
312
313 always @(posedge clk) begin
314 if (PresetCarry) begin
315 TBorrow <= 0;
316 TZero <= 1;
317 end
318
319 if ((CPUphase == 1) & ShiftDataRead)
320 TMP <= {spi_miso, TMP[15:1]};
321
322 if ((CPUphase == 3) & ShiftDataRead) begin
323 TBorrow <= sub_b;
324 TMP <= {sub_r, TMP[15:1]};
325 if (sub_r)
326 TZero <= 0;
327 end
328
329 if (!Read_notWrite & ShiftDataWrite)
330 TMP <= {TMP[0], TMP[15:1]};
331
332 end
333
334 always @(posedge clk) begin
335 if (EndOfPhase & (CPUphase == 3)) begin
336 LEQ <= TZero | TMP[15];
337 end
338 end
339
340
341
342endmodule