switch over to pyramiden core
diff --git a/info.yaml b/info.yaml index 99c6ae6..362c3af 100644 --- a/info.yaml +++ b/info.yaml
@@ -3,10 +3,10 @@ project: wokwi_id: 0 # If using wokwi, set this to your project's ID source_files: # If using an HDL, set wokwi_id as 0 and uncomment and list your source files here. Source files must be in ./src - - verilog/rtl/browndeer_rv8u.v + - verilog/rtl/pyramiden_core.v - verilog/rtl/des.v - verilog/rtl/registers.v - top_module: "browndeer_rv8u" # put the name of your top module here, make it unique by prepending your github username + top_module: "pyramiden_core" # put the name of your top module here, make it unique by prepending your github username # As everyone will have access to all designs, try to make it easy for someone new to your design to know what # it does and how to operate it. @@ -17,8 +17,8 @@ documentation: author: "David Richie" # Your name discord: "" # Your discord handle - title: "RV8U - 8-bit RISC-V Microcore Processor" # Project title - description: "8-bit processor based on RISC-V ISA" # Short description of what your project does + title: "RV16U - 16-bit RISC-V Microcore Processor" # Project title + description: "16-bit processor based on RISC-V ISA" # Short description of what your project does how_it_works: "Executes reduced RISC-V based ISA" # Longer description of how the project works how_to_test: "Requires interfacing to external memory" # Instructions on how someone could test your project, include things like what buttons do what and how to set the clock if needed external_hw: "" # Describe any external hardware needed @@ -29,14 +29,27 @@ inputs: # a description of what the inputs do - clock - reset + - reserved + - reserved - serdes input bit 0 - serdes input bit 1 - serdes input bit 2 - serdes input bit 3 - serdes input bit 4 - serdes input bit 5 - - run + - serdes input bit 6 + - serdes input bit 7 + - serdes input bit 8 + - serdes input bit 9 + - serdes input bit 10 + - serdes input bit 11 + - serdes input bit 12 + - serdes input bit 13 + - serdes input bit 14 + - serdes input bit 15 outputs: + - halt + - reserved - serdes output bit 0 - serdes output bit 1 - serdes output bit 2 @@ -45,4 +58,12 @@ - serdes output bit 5 - serdes output bit 6 - serdes output bit 7 + - serdes output bit 8 + - serdes output bit 9 + - serdes output bit 10 + - serdes output bit 11 + - serdes output bit 12 + - serdes output bit 13 + - serdes output bit 14 + - serdes output bit 15
diff --git a/src/browndeer_rv8u.v b/src/browndeer_rv8u.v deleted file mode 100644 index 0dd82cb..0000000 --- a/src/browndeer_rv8u.v +++ /dev/null
@@ -1,772 +0,0 @@ -/* browndeer_rv8u.v - * - * Copyright (c) 2022 Brown Deer Technology, LLC. (www.browndeertechnology.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* DAR */ - -/* - * RV8U - 8-bit RISC-V Microcore Processor - * - * The rv8u (Barentsburg core) is a custom 8-bit RISC-V core supporting - * 8-bit data operations with instructions encoded into 16-bit double-words. - * The core supports the full RISC-V base ISA with the following exceptions. - * Register file is reduced to 8 registers, with rs2 access limited to x0-x3. - * Additionally the auipc instruction was removed. The non-standard ISA - * designation 'u' was chosen to mean 'microcore' since the core is very small. - * Programming is supported by a custom assembler we use for developing custom - * RISC-V cores. A simple post-processor could be written for other assemblers - * to directly map instructions generated for the rv32i base ISA, if the - * assembly instrucitons comply with the reduced rv8u ISA limitations. - * - * Pin definitions: - * input in_clk base serdes clock - * input io_in[1] reset - * input io_in[7:2] 6-bit serdes input - * output io_out[7:0] 8-bit serdes output - * - */ - -//module barentsburg_core( -module browndeer_rv8u( - -// input in_clk, -// input [7:1] io_in, -// input [7:0] io_in, // ZZZ - input [8:0] io_in, // ZZZ - output [7:0] io_out - -// output [BITS-3:0] debug_pc, -// output [IBITS-1:0] debug_instr, -// output [3:0] debug_valid_out, -// -// input [RBITS-1:0] debug_reg_sel, -// output reg [BITS-1:0] debug_reg_dout - -); - - wire in_clk; // ZZZ - - /////////////////////////////////////////////////////////////////////////// - - //////////////////////////////// - ////////// Parameters ////////// - //////////////////////////////// - - parameter BITS = 8; - parameter IBITS = 16; - parameter RBITS = 3; - parameter NREG = 8; - - /////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////// - ////////// Declarations ////////// - ////////////////////////////////// - - /// pipeline control - wire inval; - wire valid_out0; - - wire valid_out1; - - reg valid_out3; - - /// flow control - reg [BITS-3:0] pc; - reg [BITS-3:0] pc_1; - reg [BITS-3:0] pc_2; - wire pc_jump; - reg [BITS-3:0] jump_addr; - - /// instr - reg [IBITS-1:0] instr; - reg [IBITS-1:0] instr_2; - - /// hazard - reg [NREG-1:0] ldr_hzd; - - /// reg control - wire [RBITS-1:0] rd; - wire [RBITS-1:0] rs1; - wire [RBITS-1:0] rs2; - wire reg_we; - wire reg_we_arb; - reg [BITS-1:0] rd_din; - reg [BITS-1:0] nxt_rd_din; - reg [RBITS-1:0] rd_sel_arb; - reg [BITS-1:0] rs1_dout; - reg [BITS-1:0] rs2_dout; - reg [RBITS-1:0] rd_3; - - /// imm operand - wire ri; - reg [BITS-1:0] imm; - - /// reg dependency - wire use_rd_e1; - wire use_rd_e2; - wire use_rs1; - wire use_rs2; - - /// IALU - reg [3:0] op; - wire [BITS-1:0] op_result; - wire cc_zero; - wire cc_neg; - wire cc_v; - - /// ins_ - wire reg_wen; - wire ins_br; - wire ins_jal; - wire ins_jalr; - wire ins_str; - wire ins_ldr; - wire ins_halt; - wire ins_lui; - reg ins_ldr_3; - - reg ri_3; - - /// bits alias probably not necessary - wire [2:0] funct3; - - /////////////////////////////////////////////////////// - ////////// Declarations PIPELINE_STAGE_0_ILR ////////// - /////////////////////////////////////////////////////// - - // pipeline control - reg nxt_valid0; - - // flow control - reg [BITS-3:0] pc0; - reg [BITS-3:0] nxt_pc, nxt_pc0; - - reg valid0; - - /////////////////////////////////////////////////////// - /////////// Declarations PIPELINE STAGE 1 IL ////////// - /////////////////////////////////////////////////////// - - wire [IBITS-1:0] nxt_instr; - reg valid1; - - /////////////////////////////////////////////////////////////////////////// - ////////// Declarations PIPELINE STAGE 2 ID /////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - wire en2; - - reg [3:0] imm3210; - - reg valid2; - - /////////////////////////////////////////////////////////////////////////// - ////////// Pipeline Stage 3 E1 Declarations /////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - wire [BITS-1:0] arg0; - reg [BITS-1:0] arg1; - - reg stall; - - reg ben; - - /////////////////////////////////////////////////////////////////////////// - ////////// Pipeline Stage 4 E2 Declarations /////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - wire en4; - - ////////////////////////////////////////////// - ////////// ISA Decoder Declarations ////////// - ////////////////////////////////////////////// - - wire rv_itype, rv_stype, rv_btype; - wire rv_op, rv_op_imm; - - /////////////////////////////////////// - ////////// IALU Declarations ////////// - /////////////////////////////////////// - - wire [BITS-1:0] a_result_sub; - wire [BITS-1:0] a_result_srl; - reg [BITS-1:0] a_result; - reg [7:0] a_sx; - reg [BITS-1:0] a_sign_extend; - wire [4:0] a_shamt; - - wire run; - wire run_not_stall; - -// assign run = (~ rst); - assign run = io_in[8]; - assign run_not_stall = run & (~ stall); - - - ///////////////////////// - ////////// DES ////////// - ///////////////////////// - - wire des_clk_out; - wire [5:0] des_sin; - wire [7:0] des_sout; - wire [31:0] des_din; - wire [23:0] des_dout; - - ////////////////////////// - ////////// core ////////// - ////////////////////////// - - wire clk; - wire rst; - reg halt; - wire [BITS-3:0] imem_addr; - wire [IBITS-1:0] imem_dout; - wire [BITS-1:0] dmem_addr; - wire [BITS-1:0] dmem_din; - wire [BITS-1:0] dmem_dout; - wire dmem_we; - wire dmem_en; - - - /////////////////////////////////////////////////////////////////////////// - - /////////////////////////////////////////////////////////////////////////// - ////////// DES //////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - des des( - .in_clk (in_clk), - .rst (rst), - .des_sin (des_sin), - .des_sout (des_sout), - .des_din (des_din), - .des_dout (des_dout), - .des_clk_out (des_clk_out) - ); - - assign in_clk = io_in[0]; // ZZZ - assign rst = io_in[1]; - assign des_sin = io_in[7:2]; - - assign io_out = des_sout; - - - assign clk = des_clk_out; - - assign imem_dout[15:0] = des_dout[15:0]; - assign dmem_dout = des_dout[23:16]; - - assign des_din[5:0] = imem_addr; - assign des_din[13:6] = dmem_addr; - assign des_din[21:14] = dmem_din; - assign des_din[22] = dmem_we; - assign des_din[23] = dmem_en; - assign des_din[24] = halt; - - assign des_din[31:25] = 7'd0; - - /////////////////////////////////////////////////////////////////////////// - - /////////////////////////////////////////////////////////////////////////// - ////////// PIPELINE STAGE 0 (ILR) ///////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - /// pipeline control /// - - assign valid_out0 = valid0 & ~ inval; - - always @ (posedge clk) - begin - if (rst) begin - valid0 <= 0; - end - else if (run) begin - if (stall) - valid0 <= valid_out0; - else - valid0 <= 1; - end - else begin - valid0 <= valid_out0; - end - end - - - /// flow control /// - - always @ (*) - begin - if (pc_jump) begin - nxt_pc0 = jump_addr; - nxt_pc = jump_addr + 1; - end - else if (stall) begin - nxt_pc0 = pc0; - nxt_pc = pc; - end - else begin - nxt_pc0 = pc; - nxt_pc = pc + 1; - end - end - assign imem_addr = nxt_pc0; - - always @ (posedge clk) - begin - if (rst) begin - pc0 <= 0; - pc <= 0; - end - else if (run) begin - pc0 <= nxt_pc0; - pc <= nxt_pc; - end - else begin - pc0 <= pc0; - pc <= pc; - end - end - - - /////////////////////////////////////////////////////////////////////////// - ////////// PIPELINE STAGE 1 (IL) ////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - /// pipeline control /// - - assign valid_out1 = valid1 & ~ inval; - - always @ (posedge clk) - begin - if (rst) begin - valid1 <= 0; - pc_1 <= 0; - end - else if (run_not_stall) begin - valid1 <= valid_out0; - pc_1 <= pc; - end - else begin - valid1 <= valid_out1; - pc_1 <= pc_1; - end - end - - - /// generate instruction /// - - assign nxt_instr = imem_dout[IBITS-1:0]; - - always @ (posedge clk) - begin - if (rst) - instr <= 0; - else if (run_not_stall & valid_out0) - instr <= nxt_instr; - else - instr <= instr; - end - - - /////////////////////////////////////////////////////////////////////////// - ////////// PIPELINE STAGE 2 (ID) ////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - /// pipeline control /// - - assign en2 = valid_out1; - - always @ (posedge clk) - begin - if (rst) begin - valid2 <= 0; - end - else if (run_not_stall) begin - valid2 <= valid_out1; - end - else begin - valid2 <= valid2; - end - end - - - /// pc, instr data flow - - always @ (posedge clk) - begin - if (rst) begin - pc_2 <= 0; - instr_2 <= 0; - end - else if (run_not_stall) begin - pc_2 <= pc_1; - if (valid_out1) - instr_2 <= instr; - else - instr_2 <= 16'hffff; - end - else begin - pc_2 <= pc_2; - instr_2 <= instr_2; - end - end - - - /////////////////////////////////////////////////////////////////////////// - ////////// PIPELINE STAGE 3 (E1) ////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - - always @ (posedge clk) - begin - if (rst) - valid_out3 <= 0; - else if (run_not_stall) - valid_out3 <= valid2; - else if (run & en4) - valid_out3 <= 0; - else - valid_out3 <= valid_out3; - end - - assign rd = instr_2[5:3]; - assign funct3 = instr_2[8:6]; - assign rs1 = instr_2[11:9]; - assign rs2[1:0] = instr_2[13:12]; - assign rs2[2] = 0; - - assign ins_lui = (instr_2[2:0] == 3'b111); - assign ins_jal = (instr_2[2:0] == 3'b110); - assign ins_jalr = (instr_2[2:0] == 3'b100); - assign rv_op_imm = (instr_2[2:0] == 3'b001); - assign rv_op = (instr_2[2:0] == 3'b011); - assign ins_br = (instr_2[2:0] == 3'b010); - assign ins_ldr = ((instr_2[2:0] == 3'b000) & (~ funct3[2])); - assign ins_str = ((instr_2[2:0] == 3'b000) & funct3[2]); - - assign use_rd_e1 = reg_wen | ins_jal | ins_jalr | ins_lui; - assign use_rd_e2 = (~ funct3[2]) & ins_ldr; - assign use_rs1 = ins_ldr | reg_wen | ins_jalr | ins_br | ins_str; - assign use_rs2 = (reg_wen & ~ ri_3) | ins_br | ins_str; - - assign ins_halt = (instr_2[2:0] == 3'b000) & (funct3 == 3'b000); - - assign rv_itype = ins_ldr | rv_op_imm | ins_jalr; - assign rv_stype = ins_str; - assign rv_btype = ins_br; - - assign ri = rv_itype | rv_stype; - assign reg_wen = rv_op | rv_op_imm; - - always @ (*) - begin - if (ins_str | ins_ldr | ins_br) - op[2:0] = 3'b000; - else - op[2:0] = funct3; - - op[3] = ins_br | ((rv_op | ( rv_op_imm & funct3[2])) & instr_2[15]); - end - - always @ (*) - begin - if (rv_itype) - imm3210 = { instr_2[15:12] }; - else - imm3210 = { instr_2[14], instr_2[5:3] }; - end - - always @ (*) - begin - if (rv_itype|rv_btype|rv_stype) - imm = { instr_2[15], instr_2[15], instr_2[15], instr_2[15], imm3210 }; - else - imm = instr_2[13:6]; - end - - - assign reg_we = valid2 - & (reg_wen|ins_jal|ins_jalr|ins_lui) & (~ stall); - - assign dmem_we = valid2 & ins_str & (~ stall); - - assign arg0 = rs1_dout; - - always @ (*) - begin - if (ri) begin - arg1 = imm[BITS-1:0]; - end - else - arg1 = rs2_dout; - end - - - /// IALU /// - - assign a_shamt = arg1[4:0]; - - assign a_result_sub = arg0 - arg1; - - assign a_result_srl = arg0 >> a_shamt; - - always @ (*) - begin - case (arg1[2:0]) - 3'b000: a_sx = 8'b00000000; - 3'b001: a_sx = 8'b10000000; - 3'b010: a_sx = 8'b11000000; - 3'b011: a_sx = 8'b11100000; - 3'b100: a_sx = 8'b11110000; - 3'b101: a_sx = 8'b11111000; - 3'b110: a_sx = 8'b11111100; - 3'b111: a_sx = 8'b11111110; - endcase - if (arg0[BITS-1]) - a_sign_extend = a_sx; - else - a_sign_extend = 8'd0; - end - - - always @ (*) - begin - case (op[2:0]) - - 3'b000: begin - if (op[3]) - a_result = a_result_sub; - else - a_result = arg0 + arg1; - end - - 3'b001: begin - a_result = arg0 << a_shamt; // sll - end - - 3'b010: begin - a_result = { 7'd0, cc_neg }; // slt - end - - 3'b011: begin - a_result = { 7'd0, cc_v}; // sltu - end - - 3'b100: begin - a_result = arg0 ^ arg1; // xor - end - - 3'b101: begin - if (op[3]) - a_result = a_sign_extend | a_result_srl; // sra - else - a_result = a_result_srl; // srl - end - - 3'b110: begin - a_result = arg0 | arg1; - end - - 3'b111: begin - a_result = arg0 & arg1; - end - - endcase - end - - assign cc_neg = a_result_sub[BITS-1]; - assign cc_zero = (a_result_sub == 0); - assign cc_v = ( cc_neg & ~(arg0[BITS-1] ^ arg1[BITS-1])) - | ((~arg0[BITS-1]) & arg1[BITS-1] ); - - assign op_result = a_result; - - - assign dmem_addr = op_result[BITS-1:0]; - assign dmem_din[BITS-1:0] = rs2_dout; - assign dmem_en = (ins_str | ins_ldr) & valid2 & (~ stall); - - always @ (*) - begin - if (ins_lui) - rd_din = { imm[4:0], 3'd0 }; - else if (ins_jal|ins_jalr) - rd_din = { 2'b00, pc_2 }; - else - rd_din = op_result; - end - - always @ (*) - begin - case(funct3) - 3'b000 : ben = cc_zero; // eq - 3'b001 : ben = (~cc_zero); // ne - 3'b010 : ben = 0; - 3'b011 : ben = 0; - 3'b100 : ben = cc_neg; // lt - 3'b101 : ben = (cc_zero | (~cc_neg)); // ge - 3'b110 : ben = cc_v; // ltu - 3'b111 : ben = (cc_zero | (~cc_v)); // geu - endcase - end - - - always @ (*) - begin - if (ins_jalr) - jump_addr = op_result[BITS-3:0]; - else - jump_addr = pc_2 + { imm[BITS-3:0] }; - end - assign pc_jump = valid2 & ((ben & ins_br) | ins_jal | ins_jalr); - - assign inval = pc_jump & (~ stall); - - always @ (posedge clk) - begin - if (rst) begin - halt <= 0; - end - else if (run_not_stall & valid2) begin - halt <= ins_halt; - end - else begin - halt <= halt; - end - end - - always @ (posedge clk) - begin - if (rst) begin - ins_ldr_3 <= 0; - rd_3 <= 0; - ri_3 <= 0; - end - else if (run_not_stall) begin - ins_ldr_3 <= ins_ldr; - rd_3 <= rd; - ri_3 <= ri; - end - else begin - ins_ldr_3 <= ins_ldr_3; - rd_3 <= rd_3; - ri_3 <= ri_3; - end - end - - always @ (*) - begin - - if ( ldr_hzd == 'd0 ) - stall = 0; - else if ( (use_rs1 & ldr_hzd[rs1]) | (use_rs2 & ldr_hzd[rs2])) // RAW HZD - stall = 1; - else if ( (use_rd_e2 & ldr_hzd[rd]) | (use_rd_e1) ) // WAW conflict - stall = 1; - else - stall = 0; - - end - - - /////////////////////////////////////////////////////////////////////////// - ////////// PIPELINE STAGE 4 (E2) ////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - assign en4 = valid_out3 & (ins_ldr_3 ); - - always @ (*) - begin - - if (en4 & ins_ldr_3) begin - rd_sel_arb = rd_3; - end - else begin - rd_sel_arb = rd; - end - - end - assign reg_we_arb = reg_we | (en4 & ins_ldr_3); - - - /////////////////////////////////////////////////////////////////////////// - ////////// REGISTERS ////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - /// write register - - always @ (*) - begin - if (en4 & ins_ldr_3) begin - nxt_rd_din = dmem_dout[BITS-1:0]; - end - else begin - nxt_rd_din = rd_din; - end - end - - registers registers( - .clk (clk), - .run (run), - .we (reg_we_arb), - .rd (rd_sel_arb), - .rs1 (rs1), - .rs2 (rs2), - .rd_din (nxt_rd_din), - .rs1_dout (rs1_dout), - .rs2_dout (rs2_dout) - -// .debug_reg_sel (debug_reg_sel), -// .debug_reg_dout (debug_reg_dout) - ); - - /////////////////////////////////////////////////////////////////////////// - - ///////////////////////////// - //////// Hazard //////// - ///////////////////////////// - - always @ (posedge clk) - begin - if (rst) begin - ldr_hzd <= 0; - end - else if (run) - if (( ~(rd==0)) & (ins_ldr ) & ~ stall) begin - ldr_hzd <= ('d1 << rd); - end - else begin - ldr_hzd <= 0; - end - else begin - ldr_hzd <= ldr_hzd; - end - end - - - /////////////////////////////////////////////////////////////////////////// - - /////////////////////////// - //////// DEBUG //////// - /////////////////////////// - -// assign debug_pc = pc_2; -// assign debug_instr[15:0] = instr_2; -// assign debug_valid_out = { valid_out0, valid_out1, valid2, valid_out3 }; - -endmodule
diff --git a/src/des.v b/src/des.v deleted file mode 100644 index c0ca4cc..0000000 --- a/src/des.v +++ /dev/null
@@ -1,79 +0,0 @@ -/* des.v - * - * Copyright (c) 2022 Brown Deer Technology, LLC. (www.browndeertechnology.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* DAR */ - -module des( - input in_clk, - input rst, - - input [5:0] des_sin, - output reg [7:0] des_sout, - - input [31:0] des_din, - output reg [23:0] des_dout, - - output reg des_clk_out -); - - reg [2:0] des_counter; - - always @ (posedge in_clk, posedge rst) - begin - if (rst) - des_counter <= 3'b111; - else if (des_counter == 3'b111) - des_counter <= 3'b000; - else - des_counter <= des_counter + 1; - end - - always @ (posedge(in_clk), posedge(rst)) - begin - if (rst == 1'b1) - des_clk_out <= 0; - else if (des_counter[1:0] == 2'b11) - des_clk_out <= ~ des_clk_out; - else - des_clk_out <= des_clk_out; - end - - always @ (posedge in_clk) - begin - case (des_counter) - 3'b000: des_dout[5:0] <= des_sin; - 3'b001: des_dout[11:6] <= des_sin; - 3'b010: des_dout[17:12] <= des_sin; - 3'b011: des_dout[23:18] <= des_sin; - 3'b100: begin end - 3'b101: begin end - 3'b110: begin end - 3'b111: begin end - endcase - end - - always @ (*) - begin - case (des_counter[1:0]) - 2'b00: des_sout = des_din[7:0]; - 2'b01: des_sout = des_din[15:8]; - 2'b10: des_sout = des_din[23:16]; - 2'b11: des_sout = des_din[31:24]; - endcase - end - -endmodule
diff --git a/src/registers.v b/src/registers.v deleted file mode 100644 index bdb6a06..0000000 --- a/src/registers.v +++ /dev/null
@@ -1,115 +0,0 @@ -/* registers.v - * - * Copyright (c) 2022 Brown Deer Technology, LLC. (www.browndeertechnology.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* DAR */ - -module registers( - input clk, - input run, - input we, - input [RBITS-1:0] rd, - input [RBITS-1:0] rs1, - input [RBITS-1:0] rs2, - input [BITS-1:0] rd_din, - output reg [BITS-1:0] rs1_dout, - output reg [BITS-1:0] rs2_dout - -// input [RBITS-1:0] debug_reg_sel, -// output reg [BITS-1:0] debug_reg_dout -); - - parameter BITS = 8; - parameter RBITS = 3; - - reg [BITS-1:0] r1; - reg [BITS-1:0] r2; - reg [BITS-1:0] r3; - reg [BITS-1:0] r4; - reg [BITS-1:0] r5; - reg [BITS-1:0] r6; - reg [BITS-1:0] r7; - - always @ (posedge clk) - begin - - if (run & we & (rd==3'b001)) - r1 <= rd_din; - else - r1 <= r1; - - if (run & we & (rd==3'b010)) - r2 <= rd_din; - else - r2 <= r2; - - if (run & we & (rd==3'b011)) - r3 <= rd_din; - else - r3 <= r3; - - if (run & we & (rd==3'b100)) - r4 <= rd_din; - else - r4 <= r4; - - if (run & we & (rd==3'b101)) - r5 <= rd_din; - else - r5 <= r5; - - if (run & we & (rd==3'b110)) - r6 <= rd_din; - else - r6 <= r6; - - if (run & we & (rd==3'b111)) - r7 <= rd_din; - else - r7 <= r7; - end - - - /// read register - - always @ (*) - begin - case (rs2[1:0]) - 2'b00: rs2_dout = 'd0; - 2'b01: rs2_dout = r1; - 2'b10: rs2_dout = r2; - 2'b11: rs2_dout = r3; - endcase - - case (rs1) - 3'b000: rs1_dout = 'd0; - 3'b001: rs1_dout = r1; - 3'b010: rs1_dout = r2; - 3'b011: rs1_dout = r3; - 3'b100: rs1_dout = r4; - 3'b101: rs1_dout = r5; - 3'b110: rs1_dout = r6; - 3'b111: rs1_dout = r7; - endcase - - end - -// always @ (*) -// begin -// debug_reg_dout = r[debug_reg_sel]; -// end - -endmodule
diff --git a/verilog/rtl/browndeer_rv8u.v b/verilog/rtl/browndeer_rv8u.v deleted file mode 100644 index 0dd82cb..0000000 --- a/verilog/rtl/browndeer_rv8u.v +++ /dev/null
@@ -1,772 +0,0 @@ -/* browndeer_rv8u.v - * - * Copyright (c) 2022 Brown Deer Technology, LLC. (www.browndeertechnology.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* DAR */ - -/* - * RV8U - 8-bit RISC-V Microcore Processor - * - * The rv8u (Barentsburg core) is a custom 8-bit RISC-V core supporting - * 8-bit data operations with instructions encoded into 16-bit double-words. - * The core supports the full RISC-V base ISA with the following exceptions. - * Register file is reduced to 8 registers, with rs2 access limited to x0-x3. - * Additionally the auipc instruction was removed. The non-standard ISA - * designation 'u' was chosen to mean 'microcore' since the core is very small. - * Programming is supported by a custom assembler we use for developing custom - * RISC-V cores. A simple post-processor could be written for other assemblers - * to directly map instructions generated for the rv32i base ISA, if the - * assembly instrucitons comply with the reduced rv8u ISA limitations. - * - * Pin definitions: - * input in_clk base serdes clock - * input io_in[1] reset - * input io_in[7:2] 6-bit serdes input - * output io_out[7:0] 8-bit serdes output - * - */ - -//module barentsburg_core( -module browndeer_rv8u( - -// input in_clk, -// input [7:1] io_in, -// input [7:0] io_in, // ZZZ - input [8:0] io_in, // ZZZ - output [7:0] io_out - -// output [BITS-3:0] debug_pc, -// output [IBITS-1:0] debug_instr, -// output [3:0] debug_valid_out, -// -// input [RBITS-1:0] debug_reg_sel, -// output reg [BITS-1:0] debug_reg_dout - -); - - wire in_clk; // ZZZ - - /////////////////////////////////////////////////////////////////////////// - - //////////////////////////////// - ////////// Parameters ////////// - //////////////////////////////// - - parameter BITS = 8; - parameter IBITS = 16; - parameter RBITS = 3; - parameter NREG = 8; - - /////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////// - ////////// Declarations ////////// - ////////////////////////////////// - - /// pipeline control - wire inval; - wire valid_out0; - - wire valid_out1; - - reg valid_out3; - - /// flow control - reg [BITS-3:0] pc; - reg [BITS-3:0] pc_1; - reg [BITS-3:0] pc_2; - wire pc_jump; - reg [BITS-3:0] jump_addr; - - /// instr - reg [IBITS-1:0] instr; - reg [IBITS-1:0] instr_2; - - /// hazard - reg [NREG-1:0] ldr_hzd; - - /// reg control - wire [RBITS-1:0] rd; - wire [RBITS-1:0] rs1; - wire [RBITS-1:0] rs2; - wire reg_we; - wire reg_we_arb; - reg [BITS-1:0] rd_din; - reg [BITS-1:0] nxt_rd_din; - reg [RBITS-1:0] rd_sel_arb; - reg [BITS-1:0] rs1_dout; - reg [BITS-1:0] rs2_dout; - reg [RBITS-1:0] rd_3; - - /// imm operand - wire ri; - reg [BITS-1:0] imm; - - /// reg dependency - wire use_rd_e1; - wire use_rd_e2; - wire use_rs1; - wire use_rs2; - - /// IALU - reg [3:0] op; - wire [BITS-1:0] op_result; - wire cc_zero; - wire cc_neg; - wire cc_v; - - /// ins_ - wire reg_wen; - wire ins_br; - wire ins_jal; - wire ins_jalr; - wire ins_str; - wire ins_ldr; - wire ins_halt; - wire ins_lui; - reg ins_ldr_3; - - reg ri_3; - - /// bits alias probably not necessary - wire [2:0] funct3; - - /////////////////////////////////////////////////////// - ////////// Declarations PIPELINE_STAGE_0_ILR ////////// - /////////////////////////////////////////////////////// - - // pipeline control - reg nxt_valid0; - - // flow control - reg [BITS-3:0] pc0; - reg [BITS-3:0] nxt_pc, nxt_pc0; - - reg valid0; - - /////////////////////////////////////////////////////// - /////////// Declarations PIPELINE STAGE 1 IL ////////// - /////////////////////////////////////////////////////// - - wire [IBITS-1:0] nxt_instr; - reg valid1; - - /////////////////////////////////////////////////////////////////////////// - ////////// Declarations PIPELINE STAGE 2 ID /////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - wire en2; - - reg [3:0] imm3210; - - reg valid2; - - /////////////////////////////////////////////////////////////////////////// - ////////// Pipeline Stage 3 E1 Declarations /////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - wire [BITS-1:0] arg0; - reg [BITS-1:0] arg1; - - reg stall; - - reg ben; - - /////////////////////////////////////////////////////////////////////////// - ////////// Pipeline Stage 4 E2 Declarations /////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - wire en4; - - ////////////////////////////////////////////// - ////////// ISA Decoder Declarations ////////// - ////////////////////////////////////////////// - - wire rv_itype, rv_stype, rv_btype; - wire rv_op, rv_op_imm; - - /////////////////////////////////////// - ////////// IALU Declarations ////////// - /////////////////////////////////////// - - wire [BITS-1:0] a_result_sub; - wire [BITS-1:0] a_result_srl; - reg [BITS-1:0] a_result; - reg [7:0] a_sx; - reg [BITS-1:0] a_sign_extend; - wire [4:0] a_shamt; - - wire run; - wire run_not_stall; - -// assign run = (~ rst); - assign run = io_in[8]; - assign run_not_stall = run & (~ stall); - - - ///////////////////////// - ////////// DES ////////// - ///////////////////////// - - wire des_clk_out; - wire [5:0] des_sin; - wire [7:0] des_sout; - wire [31:0] des_din; - wire [23:0] des_dout; - - ////////////////////////// - ////////// core ////////// - ////////////////////////// - - wire clk; - wire rst; - reg halt; - wire [BITS-3:0] imem_addr; - wire [IBITS-1:0] imem_dout; - wire [BITS-1:0] dmem_addr; - wire [BITS-1:0] dmem_din; - wire [BITS-1:0] dmem_dout; - wire dmem_we; - wire dmem_en; - - - /////////////////////////////////////////////////////////////////////////// - - /////////////////////////////////////////////////////////////////////////// - ////////// DES //////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - des des( - .in_clk (in_clk), - .rst (rst), - .des_sin (des_sin), - .des_sout (des_sout), - .des_din (des_din), - .des_dout (des_dout), - .des_clk_out (des_clk_out) - ); - - assign in_clk = io_in[0]; // ZZZ - assign rst = io_in[1]; - assign des_sin = io_in[7:2]; - - assign io_out = des_sout; - - - assign clk = des_clk_out; - - assign imem_dout[15:0] = des_dout[15:0]; - assign dmem_dout = des_dout[23:16]; - - assign des_din[5:0] = imem_addr; - assign des_din[13:6] = dmem_addr; - assign des_din[21:14] = dmem_din; - assign des_din[22] = dmem_we; - assign des_din[23] = dmem_en; - assign des_din[24] = halt; - - assign des_din[31:25] = 7'd0; - - /////////////////////////////////////////////////////////////////////////// - - /////////////////////////////////////////////////////////////////////////// - ////////// PIPELINE STAGE 0 (ILR) ///////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - /// pipeline control /// - - assign valid_out0 = valid0 & ~ inval; - - always @ (posedge clk) - begin - if (rst) begin - valid0 <= 0; - end - else if (run) begin - if (stall) - valid0 <= valid_out0; - else - valid0 <= 1; - end - else begin - valid0 <= valid_out0; - end - end - - - /// flow control /// - - always @ (*) - begin - if (pc_jump) begin - nxt_pc0 = jump_addr; - nxt_pc = jump_addr + 1; - end - else if (stall) begin - nxt_pc0 = pc0; - nxt_pc = pc; - end - else begin - nxt_pc0 = pc; - nxt_pc = pc + 1; - end - end - assign imem_addr = nxt_pc0; - - always @ (posedge clk) - begin - if (rst) begin - pc0 <= 0; - pc <= 0; - end - else if (run) begin - pc0 <= nxt_pc0; - pc <= nxt_pc; - end - else begin - pc0 <= pc0; - pc <= pc; - end - end - - - /////////////////////////////////////////////////////////////////////////// - ////////// PIPELINE STAGE 1 (IL) ////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - /// pipeline control /// - - assign valid_out1 = valid1 & ~ inval; - - always @ (posedge clk) - begin - if (rst) begin - valid1 <= 0; - pc_1 <= 0; - end - else if (run_not_stall) begin - valid1 <= valid_out0; - pc_1 <= pc; - end - else begin - valid1 <= valid_out1; - pc_1 <= pc_1; - end - end - - - /// generate instruction /// - - assign nxt_instr = imem_dout[IBITS-1:0]; - - always @ (posedge clk) - begin - if (rst) - instr <= 0; - else if (run_not_stall & valid_out0) - instr <= nxt_instr; - else - instr <= instr; - end - - - /////////////////////////////////////////////////////////////////////////// - ////////// PIPELINE STAGE 2 (ID) ////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - /// pipeline control /// - - assign en2 = valid_out1; - - always @ (posedge clk) - begin - if (rst) begin - valid2 <= 0; - end - else if (run_not_stall) begin - valid2 <= valid_out1; - end - else begin - valid2 <= valid2; - end - end - - - /// pc, instr data flow - - always @ (posedge clk) - begin - if (rst) begin - pc_2 <= 0; - instr_2 <= 0; - end - else if (run_not_stall) begin - pc_2 <= pc_1; - if (valid_out1) - instr_2 <= instr; - else - instr_2 <= 16'hffff; - end - else begin - pc_2 <= pc_2; - instr_2 <= instr_2; - end - end - - - /////////////////////////////////////////////////////////////////////////// - ////////// PIPELINE STAGE 3 (E1) ////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - - always @ (posedge clk) - begin - if (rst) - valid_out3 <= 0; - else if (run_not_stall) - valid_out3 <= valid2; - else if (run & en4) - valid_out3 <= 0; - else - valid_out3 <= valid_out3; - end - - assign rd = instr_2[5:3]; - assign funct3 = instr_2[8:6]; - assign rs1 = instr_2[11:9]; - assign rs2[1:0] = instr_2[13:12]; - assign rs2[2] = 0; - - assign ins_lui = (instr_2[2:0] == 3'b111); - assign ins_jal = (instr_2[2:0] == 3'b110); - assign ins_jalr = (instr_2[2:0] == 3'b100); - assign rv_op_imm = (instr_2[2:0] == 3'b001); - assign rv_op = (instr_2[2:0] == 3'b011); - assign ins_br = (instr_2[2:0] == 3'b010); - assign ins_ldr = ((instr_2[2:0] == 3'b000) & (~ funct3[2])); - assign ins_str = ((instr_2[2:0] == 3'b000) & funct3[2]); - - assign use_rd_e1 = reg_wen | ins_jal | ins_jalr | ins_lui; - assign use_rd_e2 = (~ funct3[2]) & ins_ldr; - assign use_rs1 = ins_ldr | reg_wen | ins_jalr | ins_br | ins_str; - assign use_rs2 = (reg_wen & ~ ri_3) | ins_br | ins_str; - - assign ins_halt = (instr_2[2:0] == 3'b000) & (funct3 == 3'b000); - - assign rv_itype = ins_ldr | rv_op_imm | ins_jalr; - assign rv_stype = ins_str; - assign rv_btype = ins_br; - - assign ri = rv_itype | rv_stype; - assign reg_wen = rv_op | rv_op_imm; - - always @ (*) - begin - if (ins_str | ins_ldr | ins_br) - op[2:0] = 3'b000; - else - op[2:0] = funct3; - - op[3] = ins_br | ((rv_op | ( rv_op_imm & funct3[2])) & instr_2[15]); - end - - always @ (*) - begin - if (rv_itype) - imm3210 = { instr_2[15:12] }; - else - imm3210 = { instr_2[14], instr_2[5:3] }; - end - - always @ (*) - begin - if (rv_itype|rv_btype|rv_stype) - imm = { instr_2[15], instr_2[15], instr_2[15], instr_2[15], imm3210 }; - else - imm = instr_2[13:6]; - end - - - assign reg_we = valid2 - & (reg_wen|ins_jal|ins_jalr|ins_lui) & (~ stall); - - assign dmem_we = valid2 & ins_str & (~ stall); - - assign arg0 = rs1_dout; - - always @ (*) - begin - if (ri) begin - arg1 = imm[BITS-1:0]; - end - else - arg1 = rs2_dout; - end - - - /// IALU /// - - assign a_shamt = arg1[4:0]; - - assign a_result_sub = arg0 - arg1; - - assign a_result_srl = arg0 >> a_shamt; - - always @ (*) - begin - case (arg1[2:0]) - 3'b000: a_sx = 8'b00000000; - 3'b001: a_sx = 8'b10000000; - 3'b010: a_sx = 8'b11000000; - 3'b011: a_sx = 8'b11100000; - 3'b100: a_sx = 8'b11110000; - 3'b101: a_sx = 8'b11111000; - 3'b110: a_sx = 8'b11111100; - 3'b111: a_sx = 8'b11111110; - endcase - if (arg0[BITS-1]) - a_sign_extend = a_sx; - else - a_sign_extend = 8'd0; - end - - - always @ (*) - begin - case (op[2:0]) - - 3'b000: begin - if (op[3]) - a_result = a_result_sub; - else - a_result = arg0 + arg1; - end - - 3'b001: begin - a_result = arg0 << a_shamt; // sll - end - - 3'b010: begin - a_result = { 7'd0, cc_neg }; // slt - end - - 3'b011: begin - a_result = { 7'd0, cc_v}; // sltu - end - - 3'b100: begin - a_result = arg0 ^ arg1; // xor - end - - 3'b101: begin - if (op[3]) - a_result = a_sign_extend | a_result_srl; // sra - else - a_result = a_result_srl; // srl - end - - 3'b110: begin - a_result = arg0 | arg1; - end - - 3'b111: begin - a_result = arg0 & arg1; - end - - endcase - end - - assign cc_neg = a_result_sub[BITS-1]; - assign cc_zero = (a_result_sub == 0); - assign cc_v = ( cc_neg & ~(arg0[BITS-1] ^ arg1[BITS-1])) - | ((~arg0[BITS-1]) & arg1[BITS-1] ); - - assign op_result = a_result; - - - assign dmem_addr = op_result[BITS-1:0]; - assign dmem_din[BITS-1:0] = rs2_dout; - assign dmem_en = (ins_str | ins_ldr) & valid2 & (~ stall); - - always @ (*) - begin - if (ins_lui) - rd_din = { imm[4:0], 3'd0 }; - else if (ins_jal|ins_jalr) - rd_din = { 2'b00, pc_2 }; - else - rd_din = op_result; - end - - always @ (*) - begin - case(funct3) - 3'b000 : ben = cc_zero; // eq - 3'b001 : ben = (~cc_zero); // ne - 3'b010 : ben = 0; - 3'b011 : ben = 0; - 3'b100 : ben = cc_neg; // lt - 3'b101 : ben = (cc_zero | (~cc_neg)); // ge - 3'b110 : ben = cc_v; // ltu - 3'b111 : ben = (cc_zero | (~cc_v)); // geu - endcase - end - - - always @ (*) - begin - if (ins_jalr) - jump_addr = op_result[BITS-3:0]; - else - jump_addr = pc_2 + { imm[BITS-3:0] }; - end - assign pc_jump = valid2 & ((ben & ins_br) | ins_jal | ins_jalr); - - assign inval = pc_jump & (~ stall); - - always @ (posedge clk) - begin - if (rst) begin - halt <= 0; - end - else if (run_not_stall & valid2) begin - halt <= ins_halt; - end - else begin - halt <= halt; - end - end - - always @ (posedge clk) - begin - if (rst) begin - ins_ldr_3 <= 0; - rd_3 <= 0; - ri_3 <= 0; - end - else if (run_not_stall) begin - ins_ldr_3 <= ins_ldr; - rd_3 <= rd; - ri_3 <= ri; - end - else begin - ins_ldr_3 <= ins_ldr_3; - rd_3 <= rd_3; - ri_3 <= ri_3; - end - end - - always @ (*) - begin - - if ( ldr_hzd == 'd0 ) - stall = 0; - else if ( (use_rs1 & ldr_hzd[rs1]) | (use_rs2 & ldr_hzd[rs2])) // RAW HZD - stall = 1; - else if ( (use_rd_e2 & ldr_hzd[rd]) | (use_rd_e1) ) // WAW conflict - stall = 1; - else - stall = 0; - - end - - - /////////////////////////////////////////////////////////////////////////// - ////////// PIPELINE STAGE 4 (E2) ////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - assign en4 = valid_out3 & (ins_ldr_3 ); - - always @ (*) - begin - - if (en4 & ins_ldr_3) begin - rd_sel_arb = rd_3; - end - else begin - rd_sel_arb = rd; - end - - end - assign reg_we_arb = reg_we | (en4 & ins_ldr_3); - - - /////////////////////////////////////////////////////////////////////////// - ////////// REGISTERS ////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - /// write register - - always @ (*) - begin - if (en4 & ins_ldr_3) begin - nxt_rd_din = dmem_dout[BITS-1:0]; - end - else begin - nxt_rd_din = rd_din; - end - end - - registers registers( - .clk (clk), - .run (run), - .we (reg_we_arb), - .rd (rd_sel_arb), - .rs1 (rs1), - .rs2 (rs2), - .rd_din (nxt_rd_din), - .rs1_dout (rs1_dout), - .rs2_dout (rs2_dout) - -// .debug_reg_sel (debug_reg_sel), -// .debug_reg_dout (debug_reg_dout) - ); - - /////////////////////////////////////////////////////////////////////////// - - ///////////////////////////// - //////// Hazard //////// - ///////////////////////////// - - always @ (posedge clk) - begin - if (rst) begin - ldr_hzd <= 0; - end - else if (run) - if (( ~(rd==0)) & (ins_ldr ) & ~ stall) begin - ldr_hzd <= ('d1 << rd); - end - else begin - ldr_hzd <= 0; - end - else begin - ldr_hzd <= ldr_hzd; - end - end - - - /////////////////////////////////////////////////////////////////////////// - - /////////////////////////// - //////// DEBUG //////// - /////////////////////////// - -// assign debug_pc = pc_2; -// assign debug_instr[15:0] = instr_2; -// assign debug_valid_out = { valid_out0, valid_out1, valid2, valid_out3 }; - -endmodule
diff --git a/verilog/rtl/des.v b/verilog/rtl/des.v index c0ca4cc..8aa8892 100644 --- a/verilog/rtl/des.v +++ b/verilog/rtl/des.v
@@ -21,11 +21,11 @@ input in_clk, input rst, - input [5:0] des_sin, - output reg [7:0] des_sout, + input [15:0] des_sin, + output reg [15:0] des_sout, - input [31:0] des_din, - output reg [23:0] des_dout, + input [63:0] des_din, + output reg [63:0] des_dout, output reg des_clk_out ); @@ -55,10 +55,10 @@ always @ (posedge in_clk) begin case (des_counter) - 3'b000: des_dout[5:0] <= des_sin; - 3'b001: des_dout[11:6] <= des_sin; - 3'b010: des_dout[17:12] <= des_sin; - 3'b011: des_dout[23:18] <= des_sin; + 3'b000: des_dout[15:0] <= des_sin; + 3'b001: des_dout[31:16] <= des_sin; + 3'b010: des_dout[47:32] <= des_sin; + 3'b011: des_dout[63:48] <= des_sin; 3'b100: begin end 3'b101: begin end 3'b110: begin end @@ -69,10 +69,10 @@ always @ (*) begin case (des_counter[1:0]) - 2'b00: des_sout = des_din[7:0]; - 2'b01: des_sout = des_din[15:8]; - 2'b10: des_sout = des_din[23:16]; - 2'b11: des_sout = des_din[31:24]; + 2'b00: des_sout = des_din[15:0]; + 2'b01: des_sout = des_din[31:16]; + 2'b10: des_sout = des_din[47:32]; + 2'b11: des_sout = des_din[63:48]; endcase end
diff --git a/verilog/rtl/pyramiden_core.v b/verilog/rtl/pyramiden_core.v new file mode 100644 index 0000000..5f758a8 --- /dev/null +++ b/verilog/rtl/pyramiden_core.v
@@ -0,0 +1,882 @@ +/* pyramiden_core.v + * + * Copyright (c) 2022 Brown Deer Technology, LLC. (www.browndeertechnology.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* DAR */ + +module pyramiden_core( + + input in_clk, + + input [19:1] io_in, + output [17:0] io_out + +// output [BITS-3:0] debug_pc, +// output [IBITS-1:0] debug_instr, +// +// input [RBITS-1:0] debug_reg_sel, +// output [BITS-1:0] debug_reg_dout + +); + +// wire in_clk; // ZZZ + + + /////////////////////////////////////////////////////////////////////////// + + //////////////////////////////// + ////////// Parameters ////////// + //////////////////////////////// + + parameter BITS = 16; + parameter IBITS = 18; + parameter RBITS = 3; + parameter NREG = 8; + + + /////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////// + ////////// Declarations ////////// + ////////////////////////////////// + + /// pipeline control + wire stall; + wire stall3; + wire stall_dmem_bsy; + wire ack3; + wire inval0; + wire valid_out0; + + wire inval1; + wire valid_out1; + + wire valid_out2; + + reg valid_out3; + + wire stall_imem; + + /// flow control + reg [BITS-3:0] pc; + reg [BITS-3:0] pc_1; + reg [BITS-3:0] pc_2; + wire pc_jump; + reg [BITS-3:0] rel_addr; + reg [BITS-3:0] jump_addr; + + /// instr + reg [IBITS-1:0] instr; + reg [IBITS-1:0] instr_2; + + /// hazard + reg [NREG-1:0] ldr_hzd; + + /// DMEM interface + wire mem_we; + + /// reg control + wire [RBITS-1:0] rd; + wire [RBITS-1:0] rs1; + wire [RBITS-1:0] rs2; + wire reg_we; + wire reg_we_arb; + reg [BITS-1:0] nxt_rd_din; + reg [BITS-1:0] rd_din; + reg [RBITS-1:0] rd_sel_arb; + reg [BITS-1:0] rd_din_arb; + reg [BITS-1:0] rs1_dout; + reg [BITS-1:0] rs2_dout; + reg [RBITS-1:0] rd_3; + + /// imm operand + wire ri; + reg [5:0] imm6; + reg [BITS-1:0] imm; + + /// reg dependency + wire use_rd_e1; + wire use_rd_e2; + wire use_rs1; + wire use_rs2; + + /// IALU + reg [3:0] op; + reg [BITS-1:0] op_result; + wire cc_zero; + wire cc_neg; + wire cc_v; + + /// ins_ + wire reg_wen; + wire ins_br; + wire ins_jal; + wire ins_jalr; + wire ins_str; + wire ins_ldr; + wire ins_halt; + wire ins_lui; + wire ins_auipc; + reg ins_ldr_3; + reg ri_3; + + /// bits alias probably not necessary + wire [2:0] funct3; + wire [2:0] funct7; + wire [2:0] opcode; + + /////////////////////////////////////////////////////// + ////////// Declarations PIPELINE_STAGE_0_ILR ////////// + /////////////////////////////////////////////////////// + + // pipeline control + wire stall0; + reg nxt_valid0; + + // flow control + reg [BITS-3:0] pc0; + reg [BITS-3:0] nxt_pc, nxt_pc0; + + reg valid0; + + /////////////////////////////////////////////////////// + /////////// Declarations PIPELINE STAGE 1 IL ////////// + /////////////////////////////////////////////////////// + + reg [IBITS-1:0] nxt_instr; + reg valid1; + + /////////////////////////////////////////////////////////////////////////// + ////////// Declarations PIPELINE STAGE 2 ID /////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + wire en2; + + reg valid2; + + /////////////////////////////////////////////////////////////////////////// + ////////// Pipeline Stage 3 E1 Declarations /////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + reg [BITS-1:0] arg0; + reg [BITS-1:0] arg1; + + reg stall_ldr; + + reg ben; + + wire stall2; + + /////////////////////////////////////////////////////////////////////////// + ////////// Pipeline Stage 4 E2 Declarations /////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + wire rdy; + wire en4; + + /// registers /// + + reg [BITS-1:0] r[0:NREG-1]; + + ////////////////////////////////////////////// + ////////// ISA Decoder Declarations ////////// + ////////////////////////////////////////////// + + wire rv_itype, rv_stype, rv_btype; + + wire [15:6] s; + + wire rv_op, rv_op_imm; + + /////////////////////////////////////// + ////////// IALU Declarations ////////// + /////////////////////////////////////// + + reg [BITS-1:0] a_result_sub; + reg [BITS-1:0] a_result_srl; + reg [BITS-1:0] a_result; + reg [1:0] a_result_sel; + wire a_s; + reg [7:0] a_s8; + reg [7:0] a_sx; + reg [BITS-1:0] a_sign_extend; + wire [3:0] a_shamt; + + ///////////////////////// + ////////// DES ////////// + ///////////////////////// + + wire des_clk_out; + wire [15:0] des_sin; + wire [15:0] des_sout; + wire [63:0] des_din; + wire [63:0] des_dout; + + ////////////////////////// + ////////// core ////////// + ////////////////////////// + + wire clk; + wire rst; + wire run; + reg halt; + reg [BITS-3:0] imem_addr; + wire imem_rdy; + wire [IBITS-1:0] imem_dout; + wire [BITS-1:0] dmem_addr; + wire dmem_bsy; + wire dmem_rdy; + wire [BITS-1:0] dmem_din; + wire [BITS-1:0] dmem_dout; + wire dmem_we; + wire dmem_en; + + + /////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// + ////////// IO ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + +// assign in_clk = io_in[0]; // ZZZ + assign rst = io_in[1]; + assign run = (~ rst); //io_in[2]; +// assign ??? = io_in[3]; + assign des_sin = io_in[19:4]; + + assign io_out[0] = halt; +// assign io_out[1] = ??? + assign io_out[17:2] = des_sout; + + + /////////////////////////////////////////////////////////////////////////// + ////////// DES //////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + des des( + .in_clk (in_clk), + .rst (rst), + .des_sin (des_sin), + .des_sout (des_sout), + .des_din (des_din), + .des_dout (des_dout), + .des_clk_out (des_clk_out) + ); + + assign clk = des_clk_out; + + assign imem_dout = des_dout[17:0]; + assign dmem_dout = des_dout[33:18]; + assign imem_rdy = 1; //des_dout[34]; + assign dmem_bsy = 0; //des_dout[35]; + assign dmem_rdy = 1; //des_dout[36]; + + assign des_din[6:0] = imem_addr[6:0]; + assign des_din[13:7] = dmem_addr[6:0]; + assign des_din[29:14] = dmem_din; + assign des_din[30] = dmem_we; + assign des_din[31] = dmem_en; + assign des_din[38:32] = imem_addr[13:7]; + assign des_din[47:39] = dmem_addr[15:7]; + + + /////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// + ////////// PIPELINE STAGE 0 (ILR) ///////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + /// pipeline control /// + + assign stall0 = stall | stall_imem; + assign valid_out0 = valid0 & ~ inval0; + + always @ (posedge clk) + begin + if (rst) begin + valid0 <= 0; + end + else if (run) begin + if (stall0) + valid0 <= valid0 & ~ inval0; + else + valid0 <= 1; + end + else begin + valid0 <= valid0 & ~ inval0; + end + end + + + /// flow control /// + + always @ (*) + begin + if (pc_jump) begin + imem_addr = jump_addr; + nxt_pc0 = jump_addr; + nxt_pc = jump_addr + 1; + end + else if (stall0) begin + imem_addr = pc0; + nxt_pc0 = pc0; + nxt_pc = pc; + end + else begin + imem_addr = pc; + nxt_pc0 = pc; + nxt_pc = pc + 1; + end + end + + always @ (posedge clk) + begin + if (rst) begin + pc0 <= 0; + pc <= 0; + end + else if (run) begin + pc0 <= nxt_pc0; + pc <= nxt_pc; + end + else begin + pc0 <= pc0; + pc <= pc; + end + end + + assign stall_imem = (~ imem_rdy) & valid_out0; + + + /////////////////////////////////////////////////////////////////////////// + ////////// PIPELINE STAGE 1 (IL) ////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + /// pipeline control /// + + assign valid_out1 = valid1 & ~ inval1; + + always @ (posedge clk) + begin + if (rst) begin + valid1 <= 0; + pc_1 <= 0; + end + else if (run & ~ stall) begin + valid1 <= valid_out0; + pc_1 <= pc; + end + else begin + valid1 <= valid1 & ~ inval1; + pc_1 <= pc_1; + end + end + + + /// generate instruction /// + + always @ (*) + begin + if (imem_rdy) + nxt_instr = imem_dout[IBITS-1:0]; + else + nxt_instr = 18'h3ffff; + end + + always @ (posedge clk) + begin + if (rst) + instr <= 0; + else if (run & valid_out0 & ~ stall) + instr <= nxt_instr; + else + instr <= instr; + end + + + /////////////////////////////////////////////////////////////////////////// + ////////// PIPELINE STAGE 2 (ID) ////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + /// pipeline control /// + + assign en2 = valid_out1; + assign valid_out2 = valid2; + + always @ (posedge clk) + begin + if (rst) begin + valid2 <= 0; + end + else if (run & ~ stall) begin + valid2 <= valid_out1; + end + else begin + valid2 <= valid2; + end + end + + + /// pc, instr data flow + + always @ (posedge clk) + begin + if (rst) begin + pc_2 <= 0; + instr_2 <= 0; + end + else if (run & ~ stall) begin + pc_2 <= pc_1; + if (valid_out1) + instr_2 <= instr; + else + instr_2 <= 18'h3ffff; + end + else begin + pc_2 <= pc_2; + instr_2 <= instr_2; + end + end + + + /////////////////////////////////////////////////////////////////////////// + ////////// PIPELINE STAGE 3 (E1) ////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + assign stall = stall2; + + always @ (posedge clk) + begin + if (rst) + valid_out3 <= 0; + else if (run & ~ stall2) + valid_out3 <= valid_out2; + else if (run & ack3) + valid_out3 <= 0; + else + valid_out3 <= valid_out3; + end + +/////////////////////// + + + assign opcode = instr_2[2:0]; + assign rd = instr_2[5:3]; + assign funct3 = instr_2[8:6]; + assign rs1 = instr_2[11:9]; + assign rs2 = instr_2[14:12]; + assign funct7 = instr_2[17:15]; + + assign rv_op_imm = (opcode == 3'b001); + assign rv_op = (opcode == 3'b011); + assign ins_ldr = ((opcode == 3'b000) & (~ funct3[2])); + assign ins_br = (opcode == 3'b010); + assign ins_jal = (opcode == 3'b110); + assign ins_jalr = (opcode == 3'b100); + assign ins_str = ((opcode == 3'b000) & funct3[2]); + assign ins_halt = (opcode == 3'b000) & (funct3 == 3'b000); + assign ins_lui = (opcode == 3'b111); + assign ins_auipc = (opcode == 3'b101); + + assign reg_wen = rv_op | rv_op_imm; + + assign use_rd_e1 = reg_wen | ins_jal | ins_jalr | ins_lui | ins_auipc; + + assign use_rd_e2 = (~ funct3[2]) & ins_ldr; + + assign use_rs1 = ins_ldr | reg_wen | ins_jalr | ins_br | ins_str; + + assign use_rs2 = (reg_wen & ~ ri_3) | ins_br | ins_str; + + + always @ (*) + begin + if (ins_str | ins_ldr | ins_br | ins_auipc) + op[2:0] = 3'b000; + else + op[2:0] = funct3; + + op[3] = ins_br | ((rv_op | ( rv_op_imm & funct3[2])) & funct7[1]); + end + + assign rv_itype = ins_ldr | rv_op_imm | ins_jalr; + assign rv_stype = ins_str; + assign rv_btype = ins_br; + + assign ri = rv_itype | rv_stype; + + assign s[15] = instr_2[17]; + assign s[14] = instr_2[17]; + assign s[13] = instr_2[17]; + assign s[12] = instr_2[17]; + assign s[11] = instr_2[17]; + assign s[10] = instr_2[17]; + assign s[9] = instr_2[17]; + assign s[8] = instr_2[17]; + assign s[7] = instr_2[17]; + assign s[6] = instr_2[17]; + + assign opcode = instr_2[2:0]; + assign rd = instr_2[5:3]; + assign funct3 = instr_2[8:6]; + assign rs1 = instr_2[11:9]; + assign rs2 = instr_2[14:12]; + assign funct7 = instr_2[17:15]; + + always @ (*) + begin + if (rv_itype) + imm6 = { instr_2[17:12] }; + else + imm6 = { instr_2[17:15], instr_2[5:3] }; + end + + always @ (*) + begin + if (rv_itype|rv_stype|rv_btype) + imm = { s[15:6], imm6 }; + else + imm = { s[15:12], instr_2[17:6] }; + end + + +/////////////////////// + + assign reg_we = valid_out2 + & (reg_wen|ins_jal|ins_jalr|ins_lui|ins_auipc) & ~ stall2; + + assign mem_we = valid_out2 & ins_str & ~ stall2; + + always @ (*) + begin + if (ins_auipc) begin + arg0 = { 2'b00, pc_2 }; + end + else + arg0 = rs1_dout; + end + + always @ (*) + begin + if (ins_auipc) + arg1 = { imm[BITS-6:0], 5'd0}; + else if (ri) + arg1 = imm[BITS-1:0]; + else + arg1 = rs2_dout; + end + + + /// IALU /// + + assign a_shamt = arg1[3:0]; + + always @ (*) + begin + a_result_sub = arg0 - arg1; + end + + always @ (*) + begin + a_result_srl = arg0 >> a_shamt; + end + + assign a_s = arg0[BITS-1]; + + always @ (*) + begin + case (arg1[2:0]) + 3'b000: a_sx = { 8'b00000000 }; + 3'b001: a_sx = { a_s, 7'b0000000 }; + 3'b010: a_sx = { a_s, a_s, 6'b000000 }; + 3'b011: a_sx = { a_s, a_s, a_s, 5'b00000 }; + 3'b100: a_sx = { a_s, a_s, a_s, a_s, 4'b0000 }; + 3'b101: a_sx = { a_s, a_s, a_s, a_s, a_s, 3'b000 }; + 3'b110: a_sx = { a_s, a_s, a_s, a_s, a_s, a_s, 2'b00 }; + 3'b111: a_sx = { a_s, a_s, a_s, a_s, a_s, a_s, a_s, 1'b0 }; + endcase + a_s8 = { a_s, a_s, a_s, a_s, a_s, a_s, a_s, a_s }; + end + + always @ (*) + begin + case (arg1[4:3]) + 2'b00: a_sign_extend = { a_sx, 8'd0 }; + 2'b01: a_sign_extend = { a_s8, a_sx }; + 2'b10: a_sign_extend = { a_s8, a_s8 }; + 2'b11: a_sign_extend = { a_s8, a_s8 }; + endcase + end + + always @ (*) + begin + case (op[2:0]) + + 3'b000: begin + + if (op[3]) + a_result = a_result_sub; + else + a_result = arg0 + arg1; + + a_result_sel = 2'b00; + + end + + 3'b001: begin + a_result = arg0 << a_shamt; // sll + a_result_sel = 2'b00; + end + + 3'b010: begin + a_result = a_result_sub; // slt + a_result_sel = 2'b01; + end + + 3'b011: begin + a_result = a_result_sub; // sltu + a_result_sel = 2'b10; + end + + 3'b100: begin + a_result = arg0 ^ arg1; // xor + a_result_sel = 2'b00; + end + + 3'b101: begin + + if (op[3]) + a_result = a_sign_extend | a_result_srl; // sra + else + a_result = a_result_srl; // srl + + a_result_sel = 2'b00; + + end + + 3'b110: begin + a_result = arg0 | arg1; + a_result_sel = 2'b00; + end + + 3'b111: begin + a_result = arg0 & arg1; + a_result_sel = 2'b00; + end + + endcase + end + + assign cc_neg = a_result[BITS-1]; + + assign cc_zero = (a_result == 0); + + assign cc_v = ( cc_neg & ~(arg0[BITS-1] ^ arg1[BITS-1])) + | ((~arg0[BITS-1]) & arg1[BITS-1] ); + + always @ (*) + begin + case (a_result_sel) + 2'b00: op_result = a_result; + 2'b01: op_result = { 15'd0, cc_neg }; + 2'b10: op_result = { 15'd0, cc_v}; + 2'b11: op_result = 16'hffff; // unused + endcase + end + + + assign dmem_addr = { op_result[BITS-1:0] }; + assign dmem_din[BITS-1:0] = rs2_dout; // XXX + assign dmem_we = mem_we; + assign dmem_en = (ins_str | ins_ldr) & valid_out2 & ~ stall2; + + always @ (*) + begin + if (ins_lui) + rd_din = { imm[BITS-6:0], 5'd0 }; + else if (ins_jal|ins_jalr) begin + rd_din = { 2'b00, pc_2 }; + end + else + rd_din = op_result; + end + + always @ (*) + begin + case(funct3) + 3'b000 : ben = ins_br & cc_zero; // eq + 3'b001 : ben = ins_br & (~cc_zero); // ne + 3'b010 : ben = 0; + 3'b011 : ben = 0; + 3'b100 : ben = ins_br & cc_neg; // lt + 3'b101 : ben = ins_br & (cc_zero | (~cc_neg)); // ge + 3'b110 : ben = ins_br & cc_v; // ltu + 3'b111 : ben = ins_br & (cc_zero | (~cc_v)); // geu + endcase + end + + + always @ (*) + begin + + if (ins_jalr) + jump_addr = op_result[BITS-3:0]; + else + jump_addr = pc_2 + { imm[BITS-3:0] }; + end + assign pc_jump = valid_out2 & (ben | ins_jal | ins_jalr); + + assign inval0 = pc_jump & (~ stall2); + assign inval1 = pc_jump & (~ stall2); + + always @ (posedge clk) + begin + if (rst) begin + halt <= 0; + end + else if (run & valid_out2 & ~ stall2) begin + halt <= ins_halt; + end + else begin + halt <= halt; + end + end + + always @ (posedge clk) + begin + if (rst) begin + ins_ldr_3 <= 0; + rd_3 <= 0; + ri_3 <= 0; + end + else if (run & ~ stall2) begin + ins_ldr_3 <= ins_ldr; + rd_3 <= rd; + ri_3 <= ri; + end + else begin + ins_ldr_3 <= ins_ldr_3; + rd_3 <= rd_3; + ri_3 <= ri_3; + end + end + + always @ (*) + begin + + if ( ldr_hzd == 'd0 ) + stall_ldr = 0; + else if ( (use_rs1 & ldr_hzd[rs1]) | (use_rs2 & ldr_hzd[rs2])) // RAW HZD + stall_ldr = 1; + else if ( (use_rd_e2 & ldr_hzd[rd]) | (use_rd_e1) ) // WAW conflict + stall_ldr = 1; + else + stall_ldr = 0; + + end + assign stall_dmem_bsy = ((ins_str | ins_ldr) & dmem_bsy); + assign stall2 = stall_ldr | stall3 | stall_dmem_bsy; + + + /////////////////////////////////////////////////////////////////////////// + ////////// PIPELINE STAGE 4 (E2) ////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + assign en4 = valid_out3 & (ins_ldr_3 ) & rdy; + + always @ (*) + begin + + if (en4 & ins_ldr_3) begin + rd_sel_arb = rd_3; + rd_din_arb = dmem_dout[BITS-1:0]; + end + else begin + rd_sel_arb = rd; + rd_din_arb = rd_din; + end + + end + assign reg_we_arb = reg_we | (en4 & ins_ldr_3); + + + assign rdy = ( (~ins_ldr_3) | (ins_ldr_3 & dmem_rdy) ); + assign stall3 = valid_out3 & (~rdy); + assign ack3 = en4; + + + /////////////////////////////////////////////////////////////////////////// + ////////// REGISTERS ////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + always @ (*) + begin + if (en4 & ins_ldr_3) begin + nxt_rd_din = dmem_dout[BITS-1:0]; + end + else begin + nxt_rd_din = rd_din; + end + end + + registers registers( + .clk (clk), + .run (run), + .we (reg_we_arb), + .rd (rd_sel_arb), + .rs1 (rs1), + .rs2 (rs2), + .rd_din (nxt_rd_din), + .rs1_dout (rs1_dout), + .rs2_dout (rs2_dout) + +// .debug_reg_sel (debug_reg_sel), +// .debug_reg_dout (debug_reg_dout) + ); + + + /////////////////////////////////////////////////////////////////////////// + + ///////////////////////////// + //////// Hazard //////// + ///////////////////////////// + + always @ (posedge clk) + begin + if (rst) begin + ldr_hzd <= 0; + end + else if (run & (~ stall3) & (~ stall_dmem_bsy)) + if (( ~(rd==0)) & (ins_ldr ) & ~ stall) + ldr_hzd <= ('d1 << rd); + else + ldr_hzd <= 0; + else begin + ldr_hzd <= ldr_hzd; + end + end + + + /////////////////////////////////////////////////////////////////////////// + + /////////////////////////// + //////// DEBUG //////// + /////////////////////////// + +// assign debug_pc = pc_2; +// assign debug_instr = instr_2; + +endmodule
diff --git a/verilog/rtl/registers.v b/verilog/rtl/registers.v index bdb6a06..f9e1df4 100644 --- a/verilog/rtl/registers.v +++ b/verilog/rtl/registers.v
@@ -32,8 +32,9 @@ // output reg [BITS-1:0] debug_reg_dout ); - parameter BITS = 8; + parameter BITS = 16; parameter RBITS = 3; + parameter NREG = 8; reg [BITS-1:0] r1; reg [BITS-1:0] r2; @@ -45,7 +46,6 @@ always @ (posedge clk) begin - if (run & we & (rd==3'b001)) r1 <= rd_din; else @@ -87,12 +87,6 @@ always @ (*) begin - case (rs2[1:0]) - 2'b00: rs2_dout = 'd0; - 2'b01: rs2_dout = r1; - 2'b10: rs2_dout = r2; - 2'b11: rs2_dout = r3; - endcase case (rs1) 3'b000: rs1_dout = 'd0; @@ -105,11 +99,33 @@ 3'b111: rs1_dout = r7; endcase + case (rs2) + 3'b000: rs2_dout = 'd0; + 3'b001: rs2_dout = r1; + 3'b010: rs2_dout = r2; + 3'b011: rs2_dout = r3; + 3'b100: rs2_dout = r4; + 3'b101: rs2_dout = r5; + 3'b110: rs2_dout = r6; + 3'b111: rs2_dout = r7; + endcase + end -// always @ (*) -// begin -// debug_reg_dout = r[debug_reg_sel]; -// end +/* + always @ (*) + begin + case(debug_reg_sel) + 3'b000: debug_reg_dout = 'd0; + 3'b001: debug_reg_dout = r1; + 3'b010: debug_reg_dout = r2; + 3'b011: debug_reg_dout = r3; + 3'b100: debug_reg_dout = r4; + 3'b101: debug_reg_dout = r5; + 3'b110: debug_reg_dout = r6; + 3'b111: debug_reg_dout = r7; + endcase + end +*/ endmodule