blob: 4cd5f3818bfec528a623b623ae10ef3544675559 [file] [log] [blame]
matt venne0c3e642022-12-04 18:21:36 +01001/* browndeer_rv8u.v
2 *
3 * Copyright (c) 2022 Brown Deer Technology, LLC. (www.browndeertechnology.com)
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/* DAR */
19
20/*
21 * RV8U - 8-bit RISC-V Microcore Processor
22 *
23 * The rv8u (Barentsburg core) is a custom 8-bit RISC-V core supporting
24 * 8-bit data operations with instructions encoded into 16-bit double-words.
25 * The core supports the full RISC-V base ISA with the following exceptions.
26 * Register file is reduced to 8 registers, with rs2 access limited to x0-x3.
27 * Additionally the auipc instruction was removed. The non-standard ISA
28 * designation 'u' was chosen to mean 'microcore' since the core is very small.
29 * Programming is supported by a custom assembler we use for developing custom
30 * RISC-V cores. A simple post-processor could be written for other assemblers
31 * to directly map instructions generated for the rv32i base ISA, if the
32 * assembly instrucitons comply with the reduced rv8u ISA limitations.
33 *
34 * Pin definitions:
35 * input in_clk base serdes clock
36 * input io_in[1] reset
37 * input io_in[7:2] 6-bit serdes input
38 * output io_out[7:0] 8-bit serdes output
39 *
40 */
41
42//module barentsburg_core(
43module browndeer_rv8u(
44
45// input in_clk,
46// input [7:1] io_in,
47 input [7:0] io_in, // ZZZ
48 output [7:0] io_out
49
50// output [BITS-3:0] debug_pc,
51// output [IBITS-1:0] debug_instr,
52// output [3:0] debug_valid_out,
53//
54// input [RBITS-1:0] debug_reg_sel,
55// output reg [BITS-1:0] debug_reg_dout
56
57);
58
59 wire in_clk; // ZZZ
60
61 ///////////////////////////////////////////////////////////////////////////
62
63 ////////////////////////////////
64 ////////// Parameters //////////
65 ////////////////////////////////
66
67 parameter BITS = 8;
68 parameter IBITS = 16;
69 parameter RBITS = 3;
70 parameter NREG = 8;
71
72 ///////////////////////////////////////////////////////////////////////////
73
74 //////////////////////////////////
75 ////////// Declarations //////////
76 //////////////////////////////////
77
78 /// pipeline control
79 wire inval;
80 wire valid_out0;
81
82 wire valid_out1;
83
84 reg valid_out3;
85
86 /// flow control
87 reg [BITS-3:0] pc;
88 reg [BITS-3:0] pc_1;
89 reg [BITS-3:0] pc_2;
90 wire pc_jump;
91 reg [BITS-3:0] jump_addr;
92
93 /// instr
94 reg [IBITS-1:0] instr;
95 reg [IBITS-1:0] instr_2;
96
97 /// hazard
98 reg [NREG-1:0] ldr_hzd;
99
100 /// reg control
101 wire [RBITS-1:0] rd;
102 wire [RBITS-1:0] rs1;
103 wire [RBITS-1:0] rs2;
104 wire reg_we;
105 wire reg_we_arb;
106 reg [BITS-1:0] rd_din;
107 reg [BITS-1:0] nxt_rd_din;
108 reg [RBITS-1:0] rd_sel_arb;
109 reg [BITS-1:0] rs1_dout;
110 reg [BITS-1:0] rs2_dout;
111 reg [RBITS-1:0] rd_3;
112
113 /// imm operand
114 wire ri;
115 reg [BITS-1:0] imm;
116
117 /// reg dependency
118 wire use_rd_e1;
119 wire use_rd_e2;
120 wire use_rs1;
121 wire use_rs2;
122
123 /// IALU
124 reg [3:0] op;
125 wire [BITS-1:0] op_result;
126 wire cc_zero;
127 wire cc_neg;
128 wire cc_v;
129
130 /// ins_
131 wire reg_wen;
132 wire ins_br;
133 wire ins_jal;
134 wire ins_jalr;
135 wire ins_str;
136 wire ins_ldr;
137 wire ins_halt;
138 wire ins_lui;
139 reg ins_ldr_3;
140
141 reg ri_3;
142
143 /// bits alias probably not necessary
144 wire [2:0] funct3;
145
146 ///////////////////////////////////////////////////////
147 ////////// Declarations PIPELINE_STAGE_0_ILR //////////
148 ///////////////////////////////////////////////////////
149
150 // pipeline control
151 reg nxt_valid0;
152
153 // flow control
154 reg [BITS-3:0] pc0;
155 reg [BITS-3:0] nxt_pc, nxt_pc0;
156
157 reg valid0;
158
159 ///////////////////////////////////////////////////////
160 /////////// Declarations PIPELINE STAGE 1 IL //////////
161 ///////////////////////////////////////////////////////
162
163 wire [IBITS-1:0] nxt_instr;
164 reg valid1;
165
166 ///////////////////////////////////////////////////////////////////////////
167 ////////// Declarations PIPELINE STAGE 2 ID ///////////////////////////////
168 ///////////////////////////////////////////////////////////////////////////
169
170 wire en2;
171
172 reg [3:0] imm3210;
173
174 reg valid2;
175
176 ///////////////////////////////////////////////////////////////////////////
177 ////////// Pipeline Stage 3 E1 Declarations ///////////////////////////////
178 ///////////////////////////////////////////////////////////////////////////
179
180 wire [BITS-1:0] arg0;
181 reg [BITS-1:0] arg1;
182
183 reg stall;
184
185 reg ben;
186
187 ///////////////////////////////////////////////////////////////////////////
188 ////////// Pipeline Stage 4 E2 Declarations ///////////////////////////////
189 ///////////////////////////////////////////////////////////////////////////
190
191 wire en4;
192
193 //////////////////////////////////////////////
194 ////////// ISA Decoder Declarations //////////
195 //////////////////////////////////////////////
196
197 wire rv_itype, rv_stype, rv_btype;
198 wire rv_op, rv_op_imm;
199
200 ///////////////////////////////////////
201 ////////// IALU Declarations //////////
202 ///////////////////////////////////////
203
204 wire [BITS-1:0] a_result_sub;
205 wire [BITS-1:0] a_result_srl;
206 reg [BITS-1:0] a_result;
207 reg [7:0] a_sx;
208 reg [BITS-1:0] a_sign_extend;
209 wire [4:0] a_shamt;
210
211 wire run;
212 wire run_not_stall;
213
214 assign run = (~ rst);
215 assign run_not_stall = run & (~ stall);
216
217
218 /////////////////////////
219 ////////// DES //////////
220 /////////////////////////
221
222 wire des_clk_out;
223 wire [5:0] des_sin;
224 wire [7:0] des_sout;
225 wire [31:0] des_din;
226 wire [23:0] des_dout;
227
228 //////////////////////////
229 ////////// core //////////
230 //////////////////////////
231
232 wire clk;
233 wire rst;
234 reg halt;
235 wire [BITS-3:0] imem_addr;
236 wire [IBITS-1:0] imem_dout;
237 wire [BITS-1:0] dmem_addr;
238 wire [BITS-1:0] dmem_din;
239 wire [BITS-1:0] dmem_dout;
240 wire dmem_we;
241 wire dmem_en;
242
243
244 ///////////////////////////////////////////////////////////////////////////
245
246 ///////////////////////////////////////////////////////////////////////////
247 ////////// DES ////////////////////////////////////////////////////////
248 ///////////////////////////////////////////////////////////////////////////
249
250 des des(
251 .in_clk (in_clk),
252 .rst (rst),
253 .des_sin (des_sin),
254 .des_sout (des_sout),
255 .des_din (des_din),
256 .des_dout (des_dout),
257 .des_clk_out (des_clk_out)
258 );
259
260 assign in_clk = io_in[0]; // ZZZ
261 assign rst = io_in[1];
262 assign des_sin = io_in[7:2];
263
264 assign io_out = des_sout;
265
266
267 assign clk = des_clk_out;
268
269 assign imem_dout[15:0] = des_dout[15:0];
270 assign dmem_dout = des_dout[23:16];
271
272 assign des_din[5:0] = imem_addr;
273 assign des_din[13:6] = dmem_addr;
274 assign des_din[21:14] = dmem_din;
275 assign des_din[22] = dmem_we;
276 assign des_din[23] = dmem_en;
277 assign des_din[24] = halt;
278
279 assign des_din[31:25] = 7'd0;
280
281 ///////////////////////////////////////////////////////////////////////////
282
283 ///////////////////////////////////////////////////////////////////////////
284 ////////// PIPELINE STAGE 0 (ILR) /////////////////////////////////////
285 ///////////////////////////////////////////////////////////////////////////
286
287 /// pipeline control ///
288
289 assign valid_out0 = valid0 & ~ inval;
290
291 always @ (posedge clk)
292 begin
293 if (rst) begin
294 valid0 <= 0;
295 end
296 else if (run) begin
297 if (stall)
298 valid0 <= valid_out0;
299 else
300 valid0 <= 1;
301 end
302 else begin
303 valid0 <= valid_out0;
304 end
305 end
306
307
308 /// flow control ///
309
310 always @ (*)
311 begin
312 if (pc_jump) begin
313 nxt_pc0 = jump_addr;
314 nxt_pc = jump_addr + 1;
315 end
316 else if (stall) begin
317 nxt_pc0 = pc0;
318 nxt_pc = pc;
319 end
320 else begin
321 nxt_pc0 = pc;
322 nxt_pc = pc + 1;
323 end
324 end
325 assign imem_addr = nxt_pc0;
326
327 always @ (posedge clk)
328 begin
329 if (rst) begin
330 pc0 <= 0;
331 pc <= 0;
332 end
333 else if (run) begin
334 pc0 <= nxt_pc0;
335 pc <= nxt_pc;
336 end
337 else begin
338 pc0 <= pc0;
339 pc <= pc;
340 end
341 end
342
343
344 ///////////////////////////////////////////////////////////////////////////
345 ////////// PIPELINE STAGE 1 (IL) //////////////////////////////////////
346 ///////////////////////////////////////////////////////////////////////////
347
348 /// pipeline control ///
349
350 assign valid_out1 = valid1 & ~ inval;
351
352 always @ (posedge clk)
353 begin
354 if (rst) begin
355 valid1 <= 0;
356 pc_1 <= 0;
357 end
358 else if (run_not_stall) begin
359 valid1 <= valid_out0;
360 pc_1 <= pc;
361 end
362 else begin
363 valid1 <= valid_out1;
364 pc_1 <= pc_1;
365 end
366 end
367
368
369 /// generate instruction ///
370
371 assign nxt_instr = imem_dout[IBITS-1:0];
372
373 always @ (posedge clk)
374 begin
375 if (rst)
376 instr <= 0;
377 else if (run_not_stall & valid_out0)
378 instr <= nxt_instr;
379 else
380 instr <= instr;
381 end
382
383
384 ///////////////////////////////////////////////////////////////////////////
385 ////////// PIPELINE STAGE 2 (ID) //////////////////////////////////////
386 ///////////////////////////////////////////////////////////////////////////
387
388 /// pipeline control ///
389
390 assign en2 = valid_out1;
391
392 always @ (posedge clk)
393 begin
394 if (rst) begin
395 valid2 <= 0;
396 end
397 else if (run_not_stall) begin
398 valid2 <= valid_out1;
399 end
400 else begin
401 valid2 <= valid2;
402 end
403 end
404
405
406 /// pc, instr data flow
407
408 always @ (posedge clk)
409 begin
410 if (rst) begin
411 pc_2 <= 0;
412 instr_2 <= 0;
413 end
414 else if (run_not_stall) begin
415 pc_2 <= pc_1;
416 if (valid_out1)
417 instr_2 <= instr;
418 else
419 instr_2 <= 16'hffff;
420 end
421 else begin
422 pc_2 <= pc_2;
423 instr_2 <= instr_2;
424 end
425 end
426
427
428 ///////////////////////////////////////////////////////////////////////////
429 ////////// PIPELINE STAGE 3 (E1) //////////////////////////////////////
430 ///////////////////////////////////////////////////////////////////////////
431
432
433 always @ (posedge clk)
434 begin
435 if (rst)
436 valid_out3 <= 0;
437 else if (run_not_stall)
438 valid_out3 <= valid2;
439 else if (run & en4)
440 valid_out3 <= 0;
441 else
442 valid_out3 <= valid_out3;
443 end
444
445 assign rd = instr_2[5:3];
446 assign funct3 = instr_2[8:6];
447 assign rs1 = instr_2[11:9];
448 assign rs2[1:0] = instr_2[13:12];
449 assign rs2[2] = 0;
450
451 assign ins_lui = (instr_2[2:0] == 3'b111);
452 assign ins_jal = (instr_2[2:0] == 3'b110);
453 assign ins_jalr = (instr_2[2:0] == 3'b100);
454 assign rv_op_imm = (instr_2[2:0] == 3'b001);
455 assign rv_op = (instr_2[2:0] == 3'b011);
456 assign ins_br = (instr_2[2:0] == 3'b010);
457 assign ins_ldr = ((instr_2[2:0] == 3'b000) & (~ funct3[2]));
458 assign ins_str = ((instr_2[2:0] == 3'b000) & funct3[2]);
459
460 assign use_rd_e1 = reg_wen | ins_jal | ins_jalr | ins_lui;
461 assign use_rd_e2 = (~ funct3[2]) & ins_ldr;
462 assign use_rs1 = ins_ldr | reg_wen | ins_jalr | ins_br | ins_str;
463 assign use_rs2 = (reg_wen & ~ ri_3) | ins_br | ins_str;
464
465 assign ins_halt = (instr_2[2:0] == 3'b000) & (funct3 == 3'b000);
466
467 assign rv_itype = ins_ldr | rv_op_imm | ins_jalr;
468 assign rv_stype = ins_str;
469 assign rv_btype = ins_br;
470
471 assign ri = rv_itype | rv_stype;
472 assign reg_wen = rv_op | rv_op_imm;
473
474 always @ (*)
475 begin
476 if (ins_str | ins_ldr | ins_br)
477 op[2:0] = 3'b000;
478 else
479 op[2:0] = funct3;
480
481 op[3] = ins_br | ((rv_op | ( rv_op_imm & funct3[2])) & instr_2[15]);
482 end
483
484 always @ (*)
485 begin
486 if (rv_itype)
487 imm3210 = { instr_2[15:12] };
488 else
489 imm3210 = { instr_2[14], instr_2[5:3] };
490 end
491
492 always @ (*)
493 begin
494 if (rv_itype|rv_btype|rv_stype)
495 imm = { instr_2[15], instr_2[15], instr_2[15], instr_2[15], imm3210 };
496 else
497 imm = instr_2[13:6];
498 end
499
500
501 assign reg_we = valid2
502 & (reg_wen|ins_jal|ins_jalr|ins_lui) & (~ stall);
503
504 assign dmem_we = valid2 & ins_str & (~ stall);
505
506 assign arg0 = rs1_dout;
507
508 always @ (*)
509 begin
510 if (ri) begin
511 arg1 = imm[BITS-1:0];
512 end
513 else
514 arg1 = rs2_dout;
515 end
516
517
518 /// IALU ///
519
520 assign a_shamt = arg1[4:0];
521
522 assign a_result_sub = arg0 - arg1;
523
524 assign a_result_srl = arg0 >> a_shamt;
525
526 always @ (*)
527 begin
528 case (arg1[2:0])
529 3'b000: a_sx = 8'b00000000;
530 3'b001: a_sx = 8'b10000000;
531 3'b010: a_sx = 8'b11000000;
532 3'b011: a_sx = 8'b11100000;
533 3'b100: a_sx = 8'b11110000;
534 3'b101: a_sx = 8'b11111000;
535 3'b110: a_sx = 8'b11111100;
536 3'b111: a_sx = 8'b11111110;
537 endcase
538 if (arg0[BITS-1])
539 a_sign_extend = a_sx;
540 else
541 a_sign_extend = 8'd0;
542 end
543
544
545 always @ (*)
546 begin
547 case (op[2:0])
548
549 3'b000: begin
550 if (op[3])
551 a_result = a_result_sub;
552 else
553 a_result = arg0 + arg1;
554 end
555
556 3'b001: begin
557 a_result = arg0 << a_shamt; // sll
558 end
559
560 3'b010: begin
561 a_result = { 7'd0, cc_neg }; // slt
562 end
563
564 3'b011: begin
565 a_result = { 7'd0, cc_v}; // sltu
566 end
567
568 3'b100: begin
569 a_result = arg0 ^ arg1; // xor
570 end
571
572 3'b101: begin
573 if (op[3])
574 a_result = a_sign_extend | a_result_srl; // sra
575 else
576 a_result = a_result_srl; // srl
577 end
578
579 3'b110: begin
580 a_result = arg0 | arg1;
581 end
582
583 3'b111: begin
584 a_result = arg0 & arg1;
585 end
586
587 endcase
588 end
589
590 assign cc_neg = a_result_sub[BITS-1];
591 assign cc_zero = (a_result_sub == 0);
592 assign cc_v = ( cc_neg & ~(arg0[BITS-1] ^ arg1[BITS-1]))
593 | ((~arg0[BITS-1]) & arg1[BITS-1] );
594
595 assign op_result = a_result;
596
597
598 assign dmem_addr = op_result[BITS-1:0];
599 assign dmem_din[BITS-1:0] = rs2_dout;
600 assign dmem_en = (ins_str | ins_ldr) & valid2 & (~ stall);
601
602 always @ (*)
603 begin
604 if (ins_lui)
605 rd_din = { imm[4:0], 3'd0 };
606 else if (ins_jal|ins_jalr)
607 rd_din = { 2'b00, pc_2 };
608 else
609 rd_din = op_result;
610 end
611
612 always @ (*)
613 begin
614 case(funct3)
615 3'b000 : ben = cc_zero; // eq
616 3'b001 : ben = (~cc_zero); // ne
617 3'b010 : ben = 0;
618 3'b011 : ben = 0;
619 3'b100 : ben = cc_neg; // lt
620 3'b101 : ben = (cc_zero | (~cc_neg)); // ge
621 3'b110 : ben = cc_v; // ltu
622 3'b111 : ben = (cc_zero | (~cc_v)); // geu
623 endcase
624 end
625
626
627 always @ (*)
628 begin
629 if (ins_jalr)
630 jump_addr = op_result[BITS-3:0];
631 else
632 jump_addr = pc_2 + { imm[BITS-3:0] };
633 end
634 assign pc_jump = valid2 & ((ben & ins_br) | ins_jal | ins_jalr);
635
636 assign inval = pc_jump & (~ stall);
637
638 always @ (posedge clk)
639 begin
640 if (rst) begin
641 halt <= 0;
642 end
643 else if (run_not_stall & valid2) begin
644 halt <= ins_halt;
645 end
646 else begin
647 halt <= halt;
648 end
649 end
650
651 always @ (posedge clk)
652 begin
653 if (rst) begin
654 ins_ldr_3 <= 0;
655 rd_3 <= 0;
656 ri_3 <= 0;
657 end
658 else if (run_not_stall) begin
659 ins_ldr_3 <= ins_ldr;
660 rd_3 <= rd;
661 ri_3 <= ri;
662 end
663 else begin
664 ins_ldr_3 <= ins_ldr_3;
665 rd_3 <= rd_3;
666 ri_3 <= ri_3;
667 end
668 end
669
670 always @ (*)
671 begin
672
673 if ( ldr_hzd == 'd0 )
674 stall = 0;
675 else if ( (use_rs1 & ldr_hzd[rs1]) | (use_rs2 & ldr_hzd[rs2])) // RAW HZD
676 stall = 1;
677 else if ( (use_rd_e2 & ldr_hzd[rd]) | (use_rd_e1) ) // WAW conflict
678 stall = 1;
679 else
680 stall = 0;
681
682 end
683
684
685 ///////////////////////////////////////////////////////////////////////////
686 ////////// PIPELINE STAGE 4 (E2) //////////////////////////////////////
687 ///////////////////////////////////////////////////////////////////////////
688
689 assign en4 = valid_out3 & (ins_ldr_3 );
690
691 always @ (*)
692 begin
693
694 if (en4 & ins_ldr_3) begin
695 rd_sel_arb = rd_3;
696 end
697 else begin
698 rd_sel_arb = rd;
699 end
700
701 end
702 assign reg_we_arb = reg_we | (en4 & ins_ldr_3);
703
704
705 ///////////////////////////////////////////////////////////////////////////
706 ////////// REGISTERS //////////////////////////////////////////////////////
707 ///////////////////////////////////////////////////////////////////////////
708
709 /// write register
710
711 always @ (*)
712 begin
713 if (en4 & ins_ldr_3) begin
714 nxt_rd_din = dmem_dout[BITS-1:0];
715 end
716 else begin
717 nxt_rd_din = rd_din;
718 end
719 end
720
721 registers registers(
722 .clk (clk),
723 .run (run),
724 .we (reg_we_arb),
725 .rd (rd_sel_arb),
726 .rs1 (rs1),
727 .rs2 (rs2),
728 .rd_din (nxt_rd_din),
729 .rs1_dout (rs1_dout),
730 .rs2_dout (rs2_dout)
731
732// .debug_reg_sel (debug_reg_sel),
733// .debug_reg_dout (debug_reg_dout)
734 );
735
736 ///////////////////////////////////////////////////////////////////////////
737
738 /////////////////////////////
739 //////// Hazard ////////
740 /////////////////////////////
741
742 always @ (posedge clk)
743 begin
744 if (rst) begin
745 ldr_hzd <= 0;
746 end
747 else if (run)
748 if (( ~(rd==0)) & (ins_ldr ) & ~ stall) begin
749 ldr_hzd <= ('d1 << rd);
750 end
751 else begin
752 ldr_hzd <= 0;
753 end
754 else begin
755 ldr_hzd <= ldr_hzd;
756 end
757 end
758
759
760 ///////////////////////////////////////////////////////////////////////////
761
762 ///////////////////////////
763 //////// DEBUG ////////
764 ///////////////////////////
765
766// assign debug_pc = pc_2;
767// assign debug_instr[15:0] = instr_2;
768// assign debug_valid_out = { valid_out0, valid_out1, valid2, valid_out3 };
769
770endmodule