├── Example_code ├── Examples │ ├── rocket_core_bypass.scala │ ├── typecast.scala │ ├── counter.scala │ └── rocket_core.scala ├── Lab11 │ ├── abstract_class1.scala │ ├── abstract_class2.scala │ ├── list_lookup.scala │ ├── rocket_bypass.scala │ ├── caseClass2.scala │ ├── caseClass.scala │ ├── rocket_control.scala │ ├── map.scala │ ├── map_flatMap.scala │ ├── unapply.scala │ ├── map_flatMap2.scala │ ├── pattern_match.scala │ └── mapMap.scala ├── Lab15 │ ├── pApply.scala │ ├── coreMixin.scala │ ├── param.scala │ ├── config.scala │ ├── miniConfig.scala │ ├── miniConfig_slides.scala │ └── xbar.scala ├── Lab14 │ ├── getMethodNames.scala │ ├── val.scala │ ├── lazyval.scala │ ├── vecMap.scala │ ├── vecMapView.scala │ ├── implictClass.scala │ ├── scaling.scala │ └── implictFunction.scala ├── Lab4 │ ├── initializer.scala │ ├── dontTouch2.scala │ ├── MuxTreeTest2.scala │ ├── dontTouch1.scala │ ├── DUT.scala │ ├── Tester.scala │ ├── dontTouch.scala │ ├── MuxTree.scala │ ├── aluTest_body2.scala │ ├── MuxTreeTest1.scala │ ├── options.scala │ ├── MuxTreeTest.scala │ ├── aluTest_body1.scala │ ├── aluTest_body.scala │ ├── aluTest.scala │ └── ALU.scala ├── Lab9 │ ├── lists3.scala │ ├── Seq_example.scala │ ├── set1.scala │ ├── muxlookup_load.scala │ ├── list_lookup.scala │ ├── lists.scala │ ├── control_signals.scala │ ├── lists2.scala │ ├── CSR_Seq.scala │ ├── Set_example.scala │ ├── control_ListLookUp.scala │ ├── Map_example.scala │ └── control_table.scala ├── Lab3 │ ├── ReadyValidData.scala │ ├── traitConfig.scala │ ├── dataValid1.scala │ ├── switch_syntax.scala │ ├── dataValid2.scala │ ├── switch_manual_portion.scala │ ├── when_syntax.scala │ ├── decoder_with_valid_skeleton.scala │ ├── switch.scala │ ├── alu_IO.scala │ ├── Valid_Interf.scala │ ├── when.scala │ ├── aluOp.scala │ ├── Right_Or.scala │ ├── Left_Or.scala │ ├── Immediate_Extension_Skeleton.scala │ ├── Decoder_switch_statement.scala │ ├── Decoder_using_when.scala │ ├── Encoder_switch_statement.scala │ ├── Encoder_whenelse_statement.scala │ ├── alu_MuxLookUp.scala │ ├── Branch_Control_skeleton.scala │ ├── Branch_Control.scala │ ├── alu_mux.scala │ ├── alu.scala │ ├── advance_alu.scala │ ├── Immediate_using_switch.scala │ └── Mux_Based_Alu.scala ├── Lab5 │ ├── data_class.scala │ ├── operator_and.scala │ ├── operator_add.scala │ ├── eMux.scala │ ├── Assignment1_skeleton.scala │ ├── eMux_illustrate.scala │ ├── operator.scala │ ├── Assignment2_skeleton.scala │ ├── Advance_param.scala │ ├── type_param.scala │ ├── Bundle_param_mux.scala │ ├── bundle_param.scala │ ├── Func_param_eMux.scala │ ├── func_param.scala │ ├── 2_to_2_line_switch.scala │ ├── Assignment2_skeleton .scala │ ├── Assignment2_skeleton2.scala │ ├── Module_param_Crossbar.scala │ ├── module_param.scala │ ├── Counter_param.scala │ ├── counter.scala │ ├── classAsParam.scala │ ├── operatorComplete.scala │ ├── classAsParam1.scala │ ├── cloneType.scala │ ├── parameter_module.scala │ ├── ALU_Param.scala │ ├── rocket_alu.scala │ └── ALU_Tester_64.scala ├── Lab8 │ ├── tile.scala │ ├── Assignment.scala │ ├── arbiter.scala │ ├── arbitor.scala │ ├── RRarbiter.scala │ ├── instMem.scala │ ├── masking.scala │ ├── regFile.scala │ ├── texput.log │ ├── parameterized_mem.scala │ ├── dataMemMask.scala │ ├── forwarding.scala │ ├── mem.scala │ └── dataMem.scala ├── Lab6 │ ├── shift_reg_sipo.scala │ ├── BBAdder.scala │ ├── RegInit.scala │ ├── Assignment1_skeleton.scala │ ├── Reg.scala │ ├── ShiftRegister.scala │ ├── one_shot.scala │ ├── counter-with-XOR-skeleton.scala │ ├── counter-with-xor.scala │ ├── up_down_counter_skeleton.scala │ ├── pwm.scala │ ├── BBAdderInline.scala │ ├── shift_reg.scala │ ├── shift_register.scala │ ├── queue.scala │ ├── up_down_counter.scala │ ├── one_shot_timer.scala │ ├── shift_reg_with_parallel_load_Skeleton.scala │ ├── shift_reg_with_parallel_load_skeleton(1)(1).scala │ ├── shift_reg_with_parallel_load_skeleton(1).scala │ ├── shift_reg_with_parallel_load_skeleton(1)(1)(1).scala │ ├── shift_reg_with_parallel_load.scala │ ├── counter.scala │ └── regFile.scala ├── Lab1 │ ├── counterScala.scala │ ├── classExample_verilog.scala │ ├── counterChisel1.scala │ ├── literals.scala │ ├── literal_typecast.scala │ ├── counterChisel2.scala │ ├── Assignment_skeleton.scala │ ├── typecast1.scala │ ├── counter.scala │ ├── datatypes.scala │ ├── object_typecast.scala │ └── classExample.scala ├── Lab10 │ ├── hiding.scala │ ├── rocket_core.scala │ ├── function1.scala │ ├── multiList.scala │ ├── match.scala │ ├── placeHolder.scala │ ├── reduce.scala │ ├── foldAve.scala │ ├── reduceAve.scala │ ├── function_higherOrder.scala │ ├── apply_old.scala │ ├── foldOrder.scala │ ├── zip.scala │ ├── reduceOrder.scala │ ├── function.scala │ ├── rocket_rf.scala │ └── apply.scala ├── Lab16 │ ├── Client.scala │ ├── Manager.scala │ ├── Client_param.scala │ ├── Manager_param.scala │ ├── Node.scala │ └── lm_tilelink3.scala ├── Lab7 │ ├── Assignment1_skeleton.scala │ ├── edge_detect.scala │ ├── arbiter.scala │ ├── RRarbiter.scala │ ├── Queue_Single.scala │ ├── Pipe.scala │ ├── Valid_Interf.scala │ ├── stateMachine.scala │ ├── CounterUpDownTest.scala │ ├── edge_detectMoore.scala │ ├── Queue_Double.scala │ ├── Assignment2_skeleton.scala │ ├── FSM_Seq_D.scala │ ├── CounterUpDown.scala │ ├── FSM_Manchester_Tester.scala │ ├── FSM_FR.scala │ ├── FSM_Manchester.scala │ └── UARTTx_chisel3.scala ├── Lab12 │ ├── isr.s │ ├── main.c │ ├── test_main.c │ ├── test_make.bat │ ├── make.bat │ └── startup.s ├── Lab2 │ ├── bitPat.scala │ ├── arithmetic.scala │ ├── muxOnehot_slides.scala │ ├── muxlookup_load.scala │ ├── Mux_5x1.scala │ ├── Barrel_skeleton.scala │ ├── mux2to1v.scala │ ├── mux2to1s.scala │ ├── mux4to1.scala │ ├── mux_onehot.scala │ ├── muxTree_slides.scala │ ├── bitField.scala │ ├── Mux_8x1.scala │ ├── muxCase_slides.scala │ ├── mux_Tree.scala │ ├── mux_Lookup.scala │ ├── mux_Case.scala │ ├── Bundle_Vec.scala │ ├── Bundle_Vec_slides.scala │ ├── Flipped_Bulk_slides.scala │ ├── Flipped_Bulk.scala │ └── Flipped_Bulk1.scala └── Lab13 │ ├── partialFunction.scala │ ├── traitOutput.scala │ ├── trait.scala │ └── parameterize.scala ├── Lecture_slides ├── fsm.pdf ├── Project.pdf ├── Scala2.pdf ├── memory.pdf ├── scala1.pdf ├── scala3.pdf ├── scala4.pdf ├── sequential.pdf ├── Introduction.pdf ├── Chisel_testers.pdf ├── combinational.pdf ├── Scala_collections.pdf ├── parameterization.pdf ├── tilelink_diplomacy.pdf └── control_combinational.pdf ├── Lab_Manual └── Chisel_Lab_manual.pdf └── README.md /Example_code/Examples/rocket_core_bypass.scala: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Example_code/Lab11/abstract_class1.scala: -------------------------------------------------------------------------------- 1 | abstract class Data_buffer { 2 | def contents: Array[String] 3 | } -------------------------------------------------------------------------------- /Example_code/Lab15/pApply.scala: -------------------------------------------------------------------------------- 1 | val xlen = p(XLEN) 2 | // is equivalent to 3 | val xlen = p.apply(XLEN, p) 4 | -------------------------------------------------------------------------------- /Lecture_slides/fsm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lampro-Mellon/Chisel-Training/HEAD/Lecture_slides/fsm.pdf -------------------------------------------------------------------------------- /Example_code/Lab14/getMethodNames.scala: -------------------------------------------------------------------------------- 1 | val s = Map.apply() 2 | s.getClass.getMethods.map(_.getName) foreach println -------------------------------------------------------------------------------- /Lecture_slides/Project.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lampro-Mellon/Chisel-Training/HEAD/Lecture_slides/Project.pdf -------------------------------------------------------------------------------- /Lecture_slides/Scala2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lampro-Mellon/Chisel-Training/HEAD/Lecture_slides/Scala2.pdf -------------------------------------------------------------------------------- /Lecture_slides/memory.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lampro-Mellon/Chisel-Training/HEAD/Lecture_slides/memory.pdf -------------------------------------------------------------------------------- /Lecture_slides/scala1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lampro-Mellon/Chisel-Training/HEAD/Lecture_slides/scala1.pdf -------------------------------------------------------------------------------- /Lecture_slides/scala3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lampro-Mellon/Chisel-Training/HEAD/Lecture_slides/scala3.pdf -------------------------------------------------------------------------------- /Lecture_slides/scala4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lampro-Mellon/Chisel-Training/HEAD/Lecture_slides/scala4.pdf -------------------------------------------------------------------------------- /Lecture_slides/sequential.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lampro-Mellon/Chisel-Training/HEAD/Lecture_slides/sequential.pdf -------------------------------------------------------------------------------- /Lecture_slides/Introduction.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lampro-Mellon/Chisel-Training/HEAD/Lecture_slides/Introduction.pdf -------------------------------------------------------------------------------- /Example_code/Lab15/coreMixin.scala: -------------------------------------------------------------------------------- 1 | abstract trait CoreParams { 2 | implicit val p: Parameters 3 | val xlen = p(XLEN) 4 | } 5 | -------------------------------------------------------------------------------- /Lab_Manual/Chisel_Lab_manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lampro-Mellon/Chisel-Training/HEAD/Lab_Manual/Chisel_Lab_manual.pdf -------------------------------------------------------------------------------- /Lecture_slides/Chisel_testers.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lampro-Mellon/Chisel-Training/HEAD/Lecture_slides/Chisel_testers.pdf -------------------------------------------------------------------------------- /Lecture_slides/combinational.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lampro-Mellon/Chisel-Training/HEAD/Lecture_slides/combinational.pdf -------------------------------------------------------------------------------- /Lecture_slides/Scala_collections.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lampro-Mellon/Chisel-Training/HEAD/Lecture_slides/Scala_collections.pdf -------------------------------------------------------------------------------- /Lecture_slides/parameterization.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lampro-Mellon/Chisel-Training/HEAD/Lecture_slides/parameterization.pdf -------------------------------------------------------------------------------- /Lecture_slides/tilelink_diplomacy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lampro-Mellon/Chisel-Training/HEAD/Lecture_slides/tilelink_diplomacy.pdf -------------------------------------------------------------------------------- /Lecture_slides/control_combinational.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lampro-Mellon/Chisel-Training/HEAD/Lecture_slides/control_combinational.pdf -------------------------------------------------------------------------------- /Example_code/Lab11/abstract_class2.scala: -------------------------------------------------------------------------------- 1 | class Data_buffer_fill(data: Array[String]) extends Data_buffer { 2 | def contents: Array[String] = data 3 | } -------------------------------------------------------------------------------- /Example_code/Lab4/initializer.scala: -------------------------------------------------------------------------------- 1 | object MuxMain extends App { 2 | iotesters.Driver.execute(args, () => new Mux_for_tester) { 3 | c => new Tester_Mux(c) 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /Example_code/Lab9/lists3.scala: -------------------------------------------------------------------------------- 1 | val lst = (1::2::3::4::5:: Nil) 2 | val first_element = lst.head //returns first element 3 | println( s"First element of lst is = ${first_element}") -------------------------------------------------------------------------------- /Example_code/Lab3/ReadyValidData.scala: -------------------------------------------------------------------------------- 1 | class ReadyValidIO[T <: Data](gen: T) extends Bundle { 2 | val ready = Input(Bool()) 3 | val valid = Output(Bool()) 4 | val bits = Output(gen) 5 | } 6 | -------------------------------------------------------------------------------- /Example_code/Lab5/data_class.scala: -------------------------------------------------------------------------------- 1 | // class definition for complex data type 2 | class ComplexData extends Bundle { 3 | val data = UInt(16.W) 4 | val addr = UInt(8.W) 5 | val flag = Bool() 6 | } 7 | 8 | -------------------------------------------------------------------------------- /Example_code/Lab8/tile.scala: -------------------------------------------------------------------------------- 1 | object Generate_ProcessorTile extends App { 2 | var initFile = "src/test/resources/main.txt" 3 | 4 | chisel3.Driver.execute(args, () => new ProcessorTile(initFile)) 5 | } 6 | -------------------------------------------------------------------------------- /Example_code/Lab5/operator_and.scala: -------------------------------------------------------------------------------- 1 | // Implement AND operation 2 | object UserOperator2 extends App { 3 | println((new chisel3.stage.ChiselStage).emitVerilog(new Operator(3, UInt(8.W))(_ & _))) 4 | } 5 | 6 | -------------------------------------------------------------------------------- /Example_code/Lab3/traitConfig.scala: -------------------------------------------------------------------------------- 1 | trait Config { 2 | // word length configuration parameter 3 | val WLEN = 32 4 | 5 | // ALU operation control signal width 6 | val ALUOP_SIG_LEN = 4 7 | } 8 | -------------------------------------------------------------------------------- /Example_code/Lab5/operator_add.scala: -------------------------------------------------------------------------------- 1 | // Implement addition operation 2 | object UserOperator1 extends App { 3 | println((new chisel3.stage.ChiselStage).emitVerilog(new Operator(2, UInt(16.W))(_ + _))) 4 | } 5 | 6 | -------------------------------------------------------------------------------- /Example_code/Lab4/dontTouch2.scala: -------------------------------------------------------------------------------- 1 | module DontTouch( 2 | input clock, 3 | input reset, 4 | input [31:0] io_a, 5 | output [31:0] io_b 6 | ); 7 | assign io_b = io_a; //@[main.scala 12:8] 8 | endmodule -------------------------------------------------------------------------------- /Example_code/Lab5/eMux.scala: -------------------------------------------------------------------------------- 1 | // parametrized Mux 2 | def eMux[T <: Data](select: Bool, in_t: T, in_f: T): T = { 3 | val ret = Wire(in_f.cloneType) 4 | ret := in_f 5 | when (select) { 6 | ret := in_t 7 | } 8 | ret // retuen value 9 | } -------------------------------------------------------------------------------- /Example_code/Lab6/shift_reg_sipo.scala: -------------------------------------------------------------------------------- 1 | // shift register (serial in and parallel out) 2 | val shiftReg = RegInit(0.U(n.W)) 3 | 4 | // shift register implementation 5 | shiftReg := Cat(data_in , shiftReg (n-1, 1)) 6 | val Q = shiftReg 7 | -------------------------------------------------------------------------------- /Example_code/Lab3/dataValid1.scala: -------------------------------------------------------------------------------- 1 | // data bits without valid signal 2 | class DataWithoutValid extends Bundle { 3 | val data_bits = Output(UInt(8.W)) 4 | } 5 | 6 | // data bits with valid signal 7 | val DataWithValid = Valid(new DataWithoutValid) -------------------------------------------------------------------------------- /Example_code/Lab1/counterScala.scala: -------------------------------------------------------------------------------- 1 | class Counter(counterBits: Int) { 2 | val max = (1 << counterBits) - 1 3 | var count = 0 4 | 5 | if(count == max) {count = 0} 6 | else {count = count + 1} 7 | println(s"counter created with max value $max") 8 | } 9 | -------------------------------------------------------------------------------- /Example_code/Lab4/MuxTreeTest2.scala: -------------------------------------------------------------------------------- 1 | // object for tester class 2 | object MuxT_Main extends App { 3 | iotesters.Driver.execute(Array("--is-verbose", "--generate-vcd-output", 4 | "on"), () => new MuxTree) { 5 | c => new TestMuxT(c) 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Example_code/Lab6/BBAdder.scala: -------------------------------------------------------------------------------- 1 | class BlackBoxAdder extends BlackBox with HasBlackBoxResource { 2 | val io = IO(new Bundle() { 3 | val in1 = Input(UInt(32.W)) 4 | val in2 = Input(UInt(32.W)) 5 | val out = Output(UInt(33.W)) 6 | }) 7 | setResource("/Adder.v") 8 | } -------------------------------------------------------------------------------- /Example_code/Lab10/hiding.scala: -------------------------------------------------------------------------------- 1 | import chisel3.util.{MuxCase => _ , _} 2 | 3 | io.out := MuxCase(false.B, Array( 4 | (io.sel === 0.U) -> io.in0, 5 | (io.sel === 1.U) -> io.in1, 6 | (io.sel === 2.U) -> io.in2, 7 | (io.sel === 3.U) -> io.in3 ) 8 | ) 9 | -------------------------------------------------------------------------------- /Example_code/Lab6/RegInit.scala: -------------------------------------------------------------------------------- 1 | // following uses of RegInit are valid 2 | val reg1 = RegInit(24.U(8.W)) 3 | val reg2 = Reg(UInt(8.W)) 4 | val reg3 = RegInit(reg2) 5 | 6 | // following uses are invalid 7 | val reg1 = RegInit(0.U(UInt(8.W))) 8 | val reg2 = RegInit(UInt(8.W)) -------------------------------------------------------------------------------- /Example_code/Lab16/Client.scala: -------------------------------------------------------------------------------- 1 | class MyClient(implicit p: Parameters) extends LazyModule { 2 | val node = TLHelper.makeClientNode(TLClientParameters()) 3 | lazy val module = new LazyModuleImp(this) { 4 | val (tl, edge) = node.out(0) 5 | // Rest of code here 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /Example_code/Lab3/switch_syntax.scala: -------------------------------------------------------------------------------- 1 | switch (state) { 2 | is(state1){ 3 | // logic implementation which runs when state === state1 4 | } 5 | is(state2){ 6 | // logic implementation which runs when state === state1 7 | } 8 | // what about the default state 9 | } -------------------------------------------------------------------------------- /Example_code/Lab6/Assignment1_skeleton.scala: -------------------------------------------------------------------------------- 1 | package Lab6 2 | import chisel3._ 3 | import chisel3.util._ 4 | import chisel3.iotesters.{ChiselFlatSpec,Driver,PeekPokeTester} 5 | 6 | class My_Queue extends Module{ 7 | // your code begin 8 | 9 | // your code end here 10 | } 11 | -------------------------------------------------------------------------------- /Example_code/Lab3/dataValid2.scala: -------------------------------------------------------------------------------- 1 | // data bits without valid signal 2 | class DataWithoutValid extends Bundle { 3 | val data_bits = Output(UInt(8.W)) 4 | } 5 | 6 | class DataWithValid extends Bundle { 7 | val valid = Output(Bool()) 8 | val data = Output(new DataWithoutValid) 9 | } -------------------------------------------------------------------------------- /Example_code/Lab7/Assignment1_skeleton.scala: -------------------------------------------------------------------------------- 1 | package Lab7 2 | import chisel3._ 3 | import chisel3.util._ 4 | import chisel3.iotesters.{ChiselFlatSpec,Driver,PeekPokeTester} 5 | 6 | class My_Queue extends Module{ 7 | ///your code begin 8 | 9 | 10 | 11 | ///your code end here 12 | } 13 | -------------------------------------------------------------------------------- /Example_code/Lab16/Manager.scala: -------------------------------------------------------------------------------- 1 | class MyManager(implicit p: Parameters) extends LazyModule { 2 | val node = TLHelper.makeManagerNode(beatBytes, TLManagerParameters()) 3 | lazy val module = new LazyModuleImp(this) { 4 | val (tl, edge) = node.in(0) 5 | //Reset of the code goes here 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Example_code/Lab14/val.scala: -------------------------------------------------------------------------------- 1 | // val evaluation illustration 2 | object valApp extends App{ 3 | val x = { println("x is initialized,"); 99 } 4 | println("before we access 'x'") 5 | println(x + 1) 6 | } 7 | 8 | // Output at the terminal 9 | x is initialized, 10 | before we access 'x' 11 | 100 -------------------------------------------------------------------------------- /Example_code/Lab9/Seq_example.scala: -------------------------------------------------------------------------------- 1 | val xseq = Seq(2 -> 'a', 5 -> 'b', 3 -> 'c') 2 | 3 | println(xseq(1)) 4 | println(xseq.apply(0)) 5 | println(xseq.length) 6 | println(xseq.toList) 7 | 8 | // following is printed to the terminal window 9 | (5,b) 10 | (2,a) 11 | 3 12 | List((2,a), (5,b), (3,c)) -------------------------------------------------------------------------------- /Example_code/Lab12/isr.s: -------------------------------------------------------------------------------- 1 | # RISC-V Interrupt Service Routines (ISRs) 2 | # ALL supported ISRs should be put here 3 | 4 | .section .text.isr 5 | 6 | # User interrupt handler 7 | .globl user_handler 8 | user_handler: 9 | nop 10 | # you can call user ISR here and then return using 'mret' 11 | mret 12 | -------------------------------------------------------------------------------- /Example_code/Lab12/main.c: -------------------------------------------------------------------------------- 1 | int add(int x, int y) { 2 | return x+y; 3 | } 4 | 5 | int main(void) { 6 | // declare some variables 7 | int x = 123, y = 987, z = 0; 8 | 9 | // call the user function 10 | z = add(x,y); 11 | 12 | // endless loop 13 | while(1){} 14 | } 15 | 16 | -------------------------------------------------------------------------------- /Example_code/Lab12/test_main.c: -------------------------------------------------------------------------------- 1 | int testfunction(int x, int y){ 2 | return x+y; 3 | } 4 | 5 | char main(void){ 6 | int x = 123, y = 987, z = 0; // declare some variables 7 | 8 | // call the user function 9 | z = myfunction(x,y); 10 | 11 | // endless loop 12 | while(1){} 13 | } 14 | -------------------------------------------------------------------------------- /Example_code/Lab4/dontTouch1.scala: -------------------------------------------------------------------------------- 1 | module DontTouch( 2 | input clock, 3 | input reset, 4 | input [31:0] io_a, 5 | output [31:0] io_b 6 | ); 7 | wire [31:0] unused; // @[main.scala 14:21] 8 | assign unused = io_a + 32`h12; 9 | assign io_b = io_a; // @[main.scala 12:8] 10 | endmodule -------------------------------------------------------------------------------- /Example_code/Lab6/Reg.scala: -------------------------------------------------------------------------------- 1 | // following uses of Reg and RegNext are valid 2 | val reg1 = Reg(UInt(8.W)) 3 | val reg2 = RegNext(reg1) // width is inferred from reg1 4 | val reg3 = RegNext(3.U(8.W)) // width is specified 5 | 6 | // following uses are invalid 7 | val reg4 = Reg(3.U(8.W)) 8 | val reg5 = RegNext(UInt(8.W)) -------------------------------------------------------------------------------- /Example_code/Lab7/edge_detect.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | 4 | class Edge_FSM extends Module { 5 | val io = IO(new Bundle{ 6 | val sin = Input(Bool()) 7 | val edge = Output(Bool()) 8 | }) 9 | 10 | // Detect the edge 11 | io.edge = !io.sin & RegNext(io.sin) 12 | } 13 | 14 | -------------------------------------------------------------------------------- /Example_code/Lab1/classExample_verilog.scala: -------------------------------------------------------------------------------- 1 | module AdderWithOffset( 2 | input clock, 3 | input reset, 4 | input [15:0] io_x, 5 | input [15:0] io_y, 6 | output [15:0] io_z 7 | ); 8 | wire [15:0] _T_2; 9 | assign _T_2 = $signed(io_x) - 16'sh9; 10 | assign io_z = _T_2 + io_y; 11 | endmodule 12 | -------------------------------------------------------------------------------- /Example_code/Lab5/Assignment1_skeleton.scala: -------------------------------------------------------------------------------- 1 | package Lab5 2 | import chisel3._ 3 | import chisel3.util._ 4 | import chisel3.iotesters.{ChiselFlatSpec,Driver,PeekPokeTester} 5 | 6 | class Adder(Width:Int) extends Module { 7 | require(Width >= 0) 8 | // your code begin from here 9 | 10 | // your code end here 11 | } 12 | 13 | 14 | -------------------------------------------------------------------------------- /Example_code/Lab4/DUT.scala: -------------------------------------------------------------------------------- 1 | >// 2 to 1 Mux for tester 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class Mux_for_tester extends Module { 6 | val io = IO(new Bundle{ 7 | val in = Vec(2,Input(Bool())) 8 | val sel = Input(Bool()) 9 | val out = Output(Bool()) 10 | }) 11 | io.out := Mux(io.sel, io.in(0), io.in(1)) 12 | } 13 | -------------------------------------------------------------------------------- /Example_code/Lab1/counterChisel1.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | 3 | class Counter(counterBits: UInt) extends Module { 4 | val max = (1.U << counterBits) - 1.U 5 | val count = RegInit(0.U(16.W)) 6 | 7 | when(count === max) { 8 | count := 0.U 9 | }.otherwise{ 10 | count := count + 1.U 11 | } 12 | println(s"counter created with max value $max") 13 | } -------------------------------------------------------------------------------- /Example_code/Lab1/literals.scala: -------------------------------------------------------------------------------- 1 | // constant/literal definitions 2 | 3 | val x1 = 23.S(32.W) // x1 = 0x0000 0017 4 | //.W with a constant value is used to define with of x1. If round backets are left empty then width will be inferred 5 | 6 | val y1 = (23.U).asSInt // y1 = 23, width inferred //.asSInt is used to convert into signed integer. 7 | -------------------------------------------------------------------------------- /Example_code/Lab14/lazyval.scala: -------------------------------------------------------------------------------- 1 | // lazy val illustration 2 | object lazyvalApp extends App{ 3 | lazy val x = { println("x is NOT initialized."); 99 } 4 | println("Unless we access 'x',") 5 | println(x + 1) 6 | println(x + 2) 7 | } 8 | 9 | // Output at the terminal 10 | Unless we access 'x', 11 | x is NOT initialized. 12 | 100 13 | 101 -------------------------------------------------------------------------------- /Example_code/Lab7/arbiter.scala: -------------------------------------------------------------------------------- 1 | val arb_priority = Module(new Arbiter(UInt(), 3)) 2 | 3 | // connect the inputs to different producers 4 | arb_priority.io.in(0) <> producer0.io.out 5 | arb_priority.io.in(1) <> producer1.io.out 6 | arb_priority.io.in(2) <> producer2.io.out 7 | 8 | // connect the output to consumer 9 | consumer.io.in <> arb_priority.io.out -------------------------------------------------------------------------------- /Example_code/Lab15/param.scala: -------------------------------------------------------------------------------- 1 | 2 | // Different parameters defined as case objects in core.scala 3 | case object XLEN extends Field[Int] 4 | case object Trace extends Field[Boolean] 5 | case object BuildALU extends Field[Parameters => ALU] 6 | case object BuildImmGen extends Field[Parameters => ImmGen] 7 | case object BuildBrCond extends Field[Parameters => BrCond] 8 | -------------------------------------------------------------------------------- /Example_code/Lab2/bitPat.scala: -------------------------------------------------------------------------------- 1 | // BitPat example 2 | // define partial opcodes for RISC V instructions 3 | def opCode_BEQ = BitPat("b000?????1100011") 4 | def opCode_BLT = BitPat("b100?????1100011") 5 | 6 | // opcode matching with don't care bits 7 | when(opCode_BEQ === "b000110001100011".U){ 8 | // above comparison evaluates to true.B 9 | // user code 10 | } -------------------------------------------------------------------------------- /Example_code/Lab7/RRarbiter.scala: -------------------------------------------------------------------------------- 1 | val arb_noPriority = Module(new RRArbiter(UInt(), 3)) 2 | 3 | // connect the inputs to different producers 4 | arb_noPriority.io.in(0) <> producer0.io.out 5 | arb_noPriority.io.in(1) <> producer1.io.out 6 | arb_noPriority.io.in(2) <> producer2.io.out 7 | 8 | // connect the output to consumer 9 | consumer.io.in <> arb_noPriority.io.out -------------------------------------------------------------------------------- /Example_code/Lab14/vecMap.scala: -------------------------------------------------------------------------------- 1 | val uVec = Vector(1 to 10: _*) 2 | 3 | // variant of expression uVec.map(_ + 1).map(_ * 2) 4 | val uVecMapped = uVec map(_ + 1) map (_ * 2) // syntactic sugar 5 | 6 | println(uVec) 7 | println(uVecMapped) 8 | 9 | // Output at the terminal 10 | Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 11 | Vector(4, 6, 8, 10, 12, 14, 16, 18, 20, 22) -------------------------------------------------------------------------------- /Example_code/Lab5/eMux_illustrate.scala: -------------------------------------------------------------------------------- 1 | // eMux illustration 2 | val in_t = Wire(new ComplexData) 3 | in_t.data := 3442.U 4 | in_t.addr := 120.U 5 | in_t.flag := true.B 6 | 7 | val in_f = Wire(new ComplexData) 8 | in_f.data := 45367.U 9 | in_f.addr := 170.U 10 | in_f.flag := false.B 11 | 12 | // The mulitplexer with complex data type 13 | val result = eMux(sel , in_t, in_f) -------------------------------------------------------------------------------- /Example_code/Lab9/set1.scala: -------------------------------------------------------------------------------- 1 | //The i in "iSet1" shows that it is immutable 2 | val iSet1 : Set[Int] = Set(1, 2, 3, 4, 5) 3 | val iSet2 : Set[Int] = Set(4, 5, 6, 7, 8) 4 | println(s"Union of both Sets are =${iSet1.++(iSet2)}") 5 | // Union of the two Sets = Set(5, 1, 6, 2, 7, 3, 8, 4) 6 | println(s"Intersection of both Sets are =${iSet1.&(iSet2)}") 7 | // Intersection of the two Sets = Set(5, 4) -------------------------------------------------------------------------------- /Example_code/Lab7/Queue_Single.scala: -------------------------------------------------------------------------------- 1 | class My_Queue extends Module{ 2 | val io = IO(new Bundle { 3 | val in = Flipped(Decoupled(UInt(8.W))) //valid = Input, ready = Output, bits = Input 4 | val out = Decoupled(UInt(8.W)) //valid = Output, ready = Input , bits = Output 5 | }) 6 | val queue = Queue(io.in, 5) // 5-element queue 7 | io.out <> queue} 8 | -------------------------------------------------------------------------------- /Example_code/Lab6/ShiftRegister.scala: -------------------------------------------------------------------------------- 1 | // ShiftRegister construct 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class shift_reg extends Module { 6 | val io = IO(new Bundle{ 7 | val out = Output(UInt(4.W)) 8 | val in = Input(UInt(4.W)) 9 | }) 10 | io.out := ShiftRegister(io.in, 2, true.B) 11 | } 12 | 13 | println((new chisel3.stage.ChiselStage).emitVerilog(new shift_reg)) 14 | -------------------------------------------------------------------------------- /Example_code/Lab2/arithmetic.scala: -------------------------------------------------------------------------------- 1 | // Arithmetic operations 2 | 3 | // Addition without width expansion 4 | val sum = x + y // OR 5 | val sum = x +%y 6 | 7 | // Addition with width expansion 8 | val sum = x +& y 9 | 10 | // Subtraction without width expansion 11 | val sum = x - y // OR 12 | val sum = x -%y 13 | 14 | // Subtraction with width expansion 15 | val sum = x -& y 16 | -------------------------------------------------------------------------------- /Example_code/Lab14/vecMapView.scala: -------------------------------------------------------------------------------- 1 | val uVec = Vector(1 to 10: _*) 2 | 3 | // view method and resulting view collection 4 | val uVecView = uVec.view 5 | val iView = uVecView map (_ + 1) map (_ * 2) filter (_ > 0) 6 | val uVecMapped = iView.force 7 | 8 | println(iView) 9 | println(uVecMapped) 10 | 11 | // Output at the terminal 12 | SeqViewMMF(...) 13 | Vector(4, 6, 8, 10, 12, 14, 16, 18, 20, 22) -------------------------------------------------------------------------------- /Example_code/Lab3/switch_manual_portion.scala: -------------------------------------------------------------------------------- 1 | when(/*condition for when*/) 2 | {/*do this when the upper when is true*/} 3 | .elsewhen(/*condition for elsewhen*/) 4 | {/*do this when the upper when is false and 5 | condition of .elsewhen is true*/} 6 | .otherwise 7 | {/*do this as a default condition, not .otherwise 8 | do not require a condition as it is the default 9 | if no condition is meet*/} 10 | -------------------------------------------------------------------------------- /Example_code/Lab15/config.scala: -------------------------------------------------------------------------------- 1 | // An instantiation of MiniConfig 2 | val params = (new MiniConfig).toInstance 3 | val chirrtl = firrtl.Parser.parse(chisel3.Driver.emit(() => new Tile(params))) 4 | 5 | 6 | // Tile top module 7 | class Tile(tileParams: Parameters) extends Module with TileBase { 8 | implicit val p = tileParams 9 | val io = IO(new TileIO) 10 | val core = Module(new Core) 11 | -------------------------------------------------------------------------------- /Example_code/Lab2/muxOnehot_slides.scala: -------------------------------------------------------------------------------- 1 | // Mux-Onehot example 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class Encoder_4to2 extends Module { 6 | val io = IO(new Bundle{ 7 | val in = Input(UInt(4.W)) 8 | val out = Output(UInt(4.W)) 9 | }) 10 | io.out := Mux1H(io.in,Seq(0.U,1.U,2.U,3.U)) 11 | } 12 | 13 | println((new chisel3.stage.ChiselStage).emitVerilog(new Encoder_4to2())) 14 | -------------------------------------------------------------------------------- /Example_code/Lab6/one_shot.scala: -------------------------------------------------------------------------------- 1 | // one shot timer implementation 2 | val timer_count = RegInit(0.U(8.W)) 3 | val done = timer_count === 0.U 4 | val next = WireInit(0.U) 5 | 6 | when (reload){ 7 | next := din // load the data from input 8 | } 9 | .elsewhen (!done){ 10 | next := timer_count - 1.U // decrement the timer 11 | } 12 | timer_count := next // update the timer 13 | -------------------------------------------------------------------------------- /Example_code/Lab5/operator.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | 3 | // class definition with function as parameter 4 | class Operator[T <: Data](n: Int, generic: T)(op: (T, T) => T) extends Module { 5 | require(n > 0) // "reduce only works on non-empty Vecs" 6 | 7 | val io = IO(new Bundle { 8 | val in = Input(Vec(n, generic)) 9 | val out = Output(generic) 10 | }) 11 | 12 | io.out := io.in.reduce(op) 13 | } 14 | -------------------------------------------------------------------------------- /Example_code/Lab11/list_lookup.scala: -------------------------------------------------------------------------------- 1 | class Control extends Module { 2 | val io = IO(new ControlSignals) 3 | val ctrlSignals = ListLookup(io.inst, Control.default, Control.map) 4 | 5 | // Control signals for Fetch 6 | io.pc_sel := ctrlSignals(0) 7 | io.inst_kill := ctrlSignals(6).toBool 8 | 9 | // Control signals for Execute 10 | io.A_sel := ctrlSignals(1) 11 | io.B_sel := ctrlSignals(2) 12 | ... -------------------------------------------------------------------------------- /Example_code/Lab5/Assignment2_skeleton.scala: -------------------------------------------------------------------------------- 1 | package Lab5 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | import chisel3.iotesters.{ChiselFlatSpec,Driver,PeekPokeTester} 6 | 7 | // your code for Transaction_in class 8 | 9 | 10 | // your code for Transaction_out class 11 | 12 | class Router[T<:Data](gen:T) extends Module{ 13 | // your code begin 14 | 15 | 16 | // your code end 17 | } 18 | 19 | 20 | -------------------------------------------------------------------------------- /Example_code/Lab10/rocket_core.scala: -------------------------------------------------------------------------------- 1 | // Exception checking in rocket core 2 | def checkExceptions(x: Seq[(Bool, UInt)]): (Bool, UInt) = 3 | // Seq of exception flags, cause of exception 4 | (x.map(_._1).reduce(_||_), PriorityMux(x)) 5 | 6 | // Hazard checking in rocket core 7 | def checkHazards(targets: Seq[(Bool, UInt)], cond: UInt => Bool): Bool = 8 | targets.map(h => h._1 && cond(h._2)).reduce(_||_) 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example_code/Lab2/muxlookup_load.scala: -------------------------------------------------------------------------------- 1 | // MuxLookup example 2 | val raw_data = io.dmem.rdata 3 | val load_data = MuxLookup(ld_type, 0.U, 4 | Seq(LD_LW -> raw_data.zext, 5 | LD_LH -> raw_data(15, 0).asSInt, 6 | LD_LB -> raw_data(7, 0).asSInt, 7 | LD_LHU -> raw_data(15, 0).zext, 8 | LD_LBU -> raw_data(7, 0).zext)) -------------------------------------------------------------------------------- /Example_code/Lab3/when_syntax.scala: -------------------------------------------------------------------------------- 1 | when(/* condition for when */){ 2 | /* do this if the condition for when is true */ 3 | } 4 | .elsewhen(/* condition for elsewhen */){ 5 | /* do this if the when is false and 6 | condition for .elsewhen is true. */ 7 | } 8 | .otherwise{ 9 | /* do this as a default condition, .otherwise 10 | do not require a condition as it is the default 11 | when no previous condition is met. */ 12 | } 13 | -------------------------------------------------------------------------------- /Example_code/Lab5/Advance_param.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | 3 | class Operator [T <: Data](n:Int,generic:T)(op:(T,T) =>T) extends Module { 4 | 5 | require (n > 0) // " reduce only works on non - empty Vecs " 6 | 7 | val io = IO(new Bundle { 8 | val in = Input(Vec(n,generic)) 9 | val out = Output(generic) 10 | }) 11 | io.out := io.in.reduce(op) 12 | } 13 | 14 | println(chisel3.Driver.emitVerilog(new Operator(3,UInt(8.W))(_&_))) 15 | 16 | -------------------------------------------------------------------------------- /Example_code/Lab10/function1.scala: -------------------------------------------------------------------------------- 1 | // assigning a function to val 2 | val f_max = scala.math.max _ 3 | val f_abs = scala.math.abs _ 4 | 5 | // calling the function 6 | val max_value = f_max(1, 5) 7 | val abs_value = f_abs(-123) 8 | 9 | println(s"The maximum value is = $max_value") 10 | println(s"The absolute value is = $abs_value") 11 | 12 | // The output at the terminal 13 | The maximum value is = 5 14 | The absolute value is = 123 -------------------------------------------------------------------------------- /Example_code/Lab6/counter-with-XOR-skeleton.scala: -------------------------------------------------------------------------------- 1 | // Counter with XOR example 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class counter_with_xor(val max: Int = 1) extends Module { 6 | val io = IO(new Bundle{ 7 | val out = Output(UInt((log2Ceil(max).W))) 8 | }) 9 | // Start Coding here 10 | 11 | // End your code here 12 | } 13 | println((new chisel3.stage.ChiselStage).emitVerilog(new counter_with_xor(n))) 14 | -------------------------------------------------------------------------------- /Example_code/Examples/typecast.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.stage.ChiselStage 3 | 4 | class Adder extends Module { 5 | val io = IO(new Bundle { 6 | val x = Input(SInt(16.W)) 7 | val y = Input(UInt(16.W)) 8 | val z = Output(UInt(16.W)) 9 | }) 10 | 11 | val in1 = Wire(SInt()) 12 | in1 := io.x + 1.S 13 | io.z := in1.asUInt + io.y // Typecast SInt to UInt 14 | } 15 | 16 | println((new ChiselStage).emitVerilog(new Adder)) -------------------------------------------------------------------------------- /Example_code/Lab1/literal_typecast.scala: -------------------------------------------------------------------------------- 1 | val f: Float = 34.6F; 2 | val c: Char = 'c'; 3 | 4 | val ccast = c.asInstanceOf[Int]; 5 | val fcast = f.asInstanceOf[Int]; 6 | 7 | display("Char ", c); 8 | display("Char to Int ", ccast); 9 | 10 | display("Float ", f); 11 | display("Float to Int ", fcast); 12 | 13 | def display[A](y: String, x: A): Unit = { 14 | println( 15 | y + " = " + x + " is of type " + 16 | x.getClass 17 | ); 18 | } -------------------------------------------------------------------------------- /Example_code/Lab3/decoder_with_valid_skeleton.scala: -------------------------------------------------------------------------------- 1 | package lab3 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class LM_IO_Interface_decoder_with_valid extends Bundle { 6 | val in = Input(UInt(2.W)) 7 | val out = Valid(Output(UInt(4.W))) 8 | } 9 | 10 | class decoder_with_valid extends Module { 11 | val io = IO(new LM_IO_Interface_decoder_with_valid) 12 | 13 | // Start coding here 14 | 15 | // End coding here 16 | } 17 | -------------------------------------------------------------------------------- /Example_code/Lab3/switch.scala: -------------------------------------------------------------------------------- 1 | class DecoderIO extends Bundle { 2 | val in = Input(UInt(2.W)) 3 | val out = Output(UInt(4.W)) 4 | } 5 | 6 | class Decoder2to4 extends Module { 7 | val io = IO(new DecoderIO) 8 | io.out := 0.U 9 | switch (io.in) { 10 | is ("b00".U) {io.out := "b0001".U} 11 | is ("b01".U) {io.out := "b0010".U} 12 | is ("b10".U) {io.out := "b0100".U} 13 | is ("b11".U) {io.out := "b1000".U} 14 | }} 15 | 16 | -------------------------------------------------------------------------------- /Example_code/Lab1/counterChisel2.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | 3 | class Counter(counterBits: UInt) extends Module { 4 | val io = IO(new Bundle { 5 | val result = Output(Bool()) 6 | }) 7 | 8 | val max = (1.U << counterBits) - 1.U 9 | val count = RegInit(0.U(16.W)) 10 | 11 | when(count === max) { 12 | count := 0.U 13 | }.otherwise{ 14 | count := count + 1.U 15 | } 16 | io.result := count(15.U) 17 | println(s"counter created with max value $max") 18 | } -------------------------------------------------------------------------------- /Example_code/Lab6/counter-with-xor.scala: -------------------------------------------------------------------------------- 1 | // Counter with XOR example 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class counter_with_xor(val max: Int = 1) extends Module { 6 | val io = IO(new Bundle{ 7 | val out = Output(UInt((log2Ceil(max).W))) 8 | }) 9 | val counter = RegInit(0.U((log2Ceil(max)+1).W)) 10 | val inter = Mux(counter(log2Ceil(max))^true.B, 0.U, counter+1.U) 11 | counter := inter 12 | io.out := counter 13 | } 14 | 15 | 16 | -------------------------------------------------------------------------------- /Example_code/Lab9/muxlookup_load.scala: -------------------------------------------------------------------------------- 1 | // Seq and MuxLookup for indexing load opeartion 2 | val raw_data = io.dmem.rdata 3 | val ld_data = MuxLookup(ld_type, 0.U, 4 | Seq(LD_LW -> raw_data.zext, 5 | LD_LH -> raw_data(15, 0).asSInt, 6 | LD_LB -> raw_data(7, 0).asSInt, 7 | LD_LHU -> raw_data(15, 0).zext, 8 | LD_LBU -> raw_data(7, 0).zext)) -------------------------------------------------------------------------------- /Example_code/Lab6/up_down_counter_skeleton.scala: -------------------------------------------------------------------------------- 1 | // Up-down counter example 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class up_down_counter(val max: Int = 10) extends Module { 6 | val io = IO(new Bundle{ 7 | val out = Output(UInt(log2Ceil(max).W)) 8 | val up_down = Input(Bool()) 9 | }) 10 | // Start code here 11 | 12 | 13 | // End your code here 14 | } 15 | 16 | println((new chisel3.stage.ChiselStage).emitVerilog(new up_down_counter(4))) 17 | -------------------------------------------------------------------------------- /Example_code/Lab11/rocket_bypass.scala: -------------------------------------------------------------------------------- 1 | // Bypass source ID 2 | val bypass_sources = IndexedSeq( 3 | (Bool(true), UInt(0), UInt(0)), // treat reading x0 as a bypass 4 | (ex_reg_valid && ex_ctrl.wxd, ex_waddr, mem_reg_wdata), 5 | (mem_reg_valid && mem_ctrl.wxd && !mem_ctrl.mem, mem_waddr, wb_reg_wdata), 6 | (mem_reg_valid && mem_ctrl.wxd, mem_waddr, dcache_bypass_data)) 7 | 8 | val id_bypass_src = id_raddr.map(raddr => bypass_sources.map(s => s._1 && s._2 === raddr)) -------------------------------------------------------------------------------- /Example_code/Lab5/type_param.scala: -------------------------------------------------------------------------------- 1 | class uStack[A] { 2 | private var elements: List[A] = Nil 3 | def push(x: A) { elements = x :: elements } 4 | def pop(): A = { 5 | val elementTop = elements.head 6 | elements = elements.tail 7 | elementTop 8 | } 9 | } 10 | 11 | val stackObj = new uStack[String] 12 | stackObj.push("Hello") 13 | stackObj.push("Trainee") 14 | println(stackObj.pop) // will print Trainee 15 | println(stackObj.pop) // will print Hello -------------------------------------------------------------------------------- /Example_code/Lab7/Pipe.scala: -------------------------------------------------------------------------------- 1 | 2 | import chisel3._ 3 | import chisel3.util._ 4 | import chisel3.iotesters.{ChiselFlatSpec,Driver,PeekPokeTester} 5 | 6 | class Pipe extends Module{ 7 | val io = IO(new Bundle { 8 | val in = Flipped(Valid(UInt(8.W))) //valid = Input, bits = Input 9 | val out = Valid(UInt(8.W)) //valid = Output, bits = Output 10 | }) 11 | io.out := Pipe(io.in,5) 12 | } 13 | println(chisel3.Driver.emitVerilog(new Pipe)) 14 | -------------------------------------------------------------------------------- /Example_code/Lab11/caseClass2.scala: -------------------------------------------------------------------------------- 1 | case class register(addr:Int, init: Int) 2 | 3 | var c = register(100, 11001100) 4 | var d = c.copy(addr = 104) 5 | 6 | // Display the register 7 | println("Reg Addr: " + c.addr + " Initial value: " + c.init) 8 | println("Reg Addr: " + d.addr + " Initial value: " + d.init) 9 | 10 | // the output on the terminal 11 | Reg Addr: 100 Initial value: 11001100 12 | Reg Addr: 104 Initial value: 11001100 13 | 14 | 15 | -------------------------------------------------------------------------------- /Example_code/Lab3/alu_IO.scala: -------------------------------------------------------------------------------- 1 | import ALUOP._ 2 | 3 | trait Config { 4 | // global config parameters 5 | val WLEN = 32 6 | val XLEN = 32 7 | val ALUOP_SIG_LEN = 4 // control signal's width 8 | } 9 | 10 | class AluIO extends Bundle with Config { 11 | val in_A = Input(UInt(WLEN.W)) 12 | val in_B = Input(UInt(WLEN.W)) 13 | val alu_Op = Input(UInt(ALUOP_SIG_LEN.W)) 14 | val out = Output(UInt(WLEN.W)) 15 | } 16 | -------------------------------------------------------------------------------- /Example_code/Lab6/pwm.scala: -------------------------------------------------------------------------------- 1 | // PWM example 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class PWM(val max: Int = 2, val duty_cycle: Int = 1) extends Module { 6 | val io = IO(new Bundle{ 7 | val out = Output(Bool()) 8 | }) 9 | val counter = RegInit(0.U(log2Ceil(max).W)) 10 | counter := Mux(counter === max.U, 0.U, counter+1.U) 11 | io.out := duty_cycle.U > counter 12 | } 13 | 14 | println((new chisel3.stage.ChiselStage).emitVerilog(new PWM(15))) 15 | -------------------------------------------------------------------------------- /Example_code/Lab11/caseClass.scala: -------------------------------------------------------------------------------- 1 | case class register(addr:Int, init: Int) 2 | 3 | var c = register(100, 11001100) 4 | 5 | // Display the register 6 | println("Reg Addr: " + c.addr + " Initial value: " + c.init) 7 | 8 | // the output on the terminal 9 | Reg Addr: 100 Initial value: 11001100 10 | 11 | // when tried to update the address 12 | c.addr = 15 13 | 14 | // the following error is encountered 15 | reassignment to val error 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Example_code/Lab11/rocket_control.scala: -------------------------------------------------------------------------------- 1 | def decode(inst: UInt, table: Iterable[(BitPat, List[BitPat])]) = { 2 | 3 | val decoder = DecodeLogic(inst, default, table) 4 | val sigs = Seq(legal, fp, rocc, branch, jal, jalr, rxs2, rxs1, scie, 5 | sel_alu2, sel_alu1, sel_imm, alu_dw, alu_fn, mem, mem_cmd, rfs1, 6 | rfs2, rfs3, wfd, mul, div, wxd, csr, fence_i, fence, amo, dp) 7 | 8 | sigs zip decoder map {case(s, d) => s := d} 9 | this 10 | } 11 | -------------------------------------------------------------------------------- /Example_code/Lab3/Valid_Interf.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | import chisel3.iotesters.{ChiselFlatSpec,Driver,PeekPokeTester} 4 | 5 | class Valid_Interf extends Module{ 6 | val io = IO(new Bundle { 7 | val in = Flipped(Valid(UInt(8.W))) //valid = Input, bits = Input 8 | val out = Valid(UInt(8.W)) //valid = Output, bits = Output 9 | }) 10 | io.out := RegNext(io.in) 11 | } 12 | println(chisel3.Driver.emitVerilog(new Valid_Interf)) 13 | -------------------------------------------------------------------------------- /Example_code/Lab7/Valid_Interf.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | import chisel3.iotesters.{ChiselFlatSpec,Driver,PeekPokeTester} 4 | 5 | class Valid_Interf extends Module{ 6 | val io = IO(new Bundle { 7 | val in = Flipped(Valid(UInt(8.W))) //valid = Input, bits = Input 8 | val out = Valid(UInt(8.W)) //valid = Output, bits = Output 9 | }) 10 | io.out := RegNext(io.in) 11 | } 12 | println(chisel3.Driver.emitVerilog(new Valid_Interf)) 13 | -------------------------------------------------------------------------------- /Example_code/Lab1/Assignment_skeleton.scala: -------------------------------------------------------------------------------- 1 | package Counter 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | import java.io.File 6 | 7 | class counter_up_down(n: Int) extends Module { 8 | val io = IO(new Bundle { 9 | val data_in = Input(UInt(n.W)) 10 | val reload = Input(Bool()) 11 | val out = Output(Bool()) 12 | }) 13 | 14 | val counter = RegInit(0.U(n.W)) 15 | val max_count = RegInit(6.U(n.W)) 16 | 17 | //Your code 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Example_code/Lab10/multiList.scala: -------------------------------------------------------------------------------- 1 | val uList1: List[(Int)] = List(3, 2) 2 | val uList2: List[(Int)] = List(20, 40, 100) 3 | 4 | // Processing multiple lists 5 | val resultProduct = (uList1, uList2).zipped.map(_ * _) 6 | val resultCount = (uList1, uList2).zipped.max 7 | 8 | println(s"The product of two lists: $resultProduct") 9 | println(s"The max element: $resultCount") 10 | 11 | // The output at the terminal 12 | The product of two lists: List(60, 80) 13 | The max element: (3,20) -------------------------------------------------------------------------------- /Example_code/Lab4/Tester.scala: -------------------------------------------------------------------------------- 1 | class Tester_Mux(c: Mux_for_tester) extends PeekPokeTester(c) { 2 | poke(c.io.in(0),0) 3 | poke(c.io.in(1),1) 4 | poke(c.io.sel,0) 5 | expect(c.io.out,0) 6 | // + operator concatenates both the strings 7 | println("The output is:" + peek(c.io.out)) 8 | 9 | poke(c.io.in(0),0) 10 | poke(c.io.in(1),1) 11 | poke(c.io.sel,1) 12 | expect(c.io.out,1) 13 | // Another way of printing data 14 | println(s"The output is: ${peek(c.io.out)}") 15 | } 16 | -------------------------------------------------------------------------------- /Example_code/Lab8/Assignment.scala: -------------------------------------------------------------------------------- 1 | package Lab8 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | 6 | class memory_assignment extends Module { 7 | val io = IO(new Bundle{ 8 | val memory_out = Vec(4, Output(UInt(32.W))) 9 | val requestor = Vec(4, Flipped(Decoupled(UInt(32.W)))) 10 | val Readaddr = Input(UInt(5.W)) 11 | val Writeaddr = Input(UInt(5.W)) 12 | }) 13 | // Start your code from here 14 | 15 | // End your code here 16 | } 17 | 18 | 19 | -------------------------------------------------------------------------------- /Example_code/Lab12/test_make.bat: -------------------------------------------------------------------------------- 1 | 2 | riscv64-unknown-elf-gcc -c -o main.o main.c -march=rv32i -mabi=ilp32 3 | 4 | riscv64-unknown-elf-gcc -o program.elf main.o -T linker.ld -nostdlib -march=rv32i -mabi=ilp32 5 | 6 | riscv64-unknown-elf-objcopy -O binary --only-section=.data* --only-section=.text* program.elf main.bin 7 | 8 | hexdump main.bin > main.hex 9 | 10 | python maketxt.py >> main.txt 11 | 12 | riscv64-unknown-elf-objdump -S -s program.elf > program.dump 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Example_code/Lab3/when.scala: -------------------------------------------------------------------------------- 1 | class EncoderIO extends Bundle { 2 | val in = Input(UInt(4.W)) 3 | val out = Output(UInt(2.W)) 4 | } 5 | 6 | class Encoder4to2 extends Module { 7 | val io = IO(new EncoderIO) 8 | 9 | when (io.in === "b0001".U) { 10 | io.out := "b00".U 11 | } .elsewhen(io.in === "b0010".U) { 12 | io.out := "b01".U 13 | } .elsewhen(io.in === "b0100".U) { 14 | io.out := "b10".U 15 | } .otherwise { 16 | io.out := "b11".U 17 | }} 18 | 19 | -------------------------------------------------------------------------------- /Example_code/Lab7/stateMachine.scala: -------------------------------------------------------------------------------- 1 | // The set of states 2 | val s0 :: s1 :: s2 :: s3 :: s4 :: Nil = Enum(5) 3 | 4 | // The state register 5 | val state = RegInit(s0) 6 | 7 | // Next state logic 8 | switch (state) { 9 | is (s0){ 10 | // state transition logic for s0 11 | // corresponds to outgoing arrows from s0 12 | } 13 | 14 | is (s1) { 15 | 16 | } 17 | 18 | ... 19 | 20 | is (s4) { 21 | // state transition logic for s4 22 | } 23 | } -------------------------------------------------------------------------------- /Example_code/Lab1/typecast1.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | 3 | class AdderWithOffset extends Module { 4 | val io = IO(new Bundle { 5 | val x = Input(SInt(16.W)) 6 | val y = Input(UInt(16.W)) 7 | val z = Output(UInt(16.W)) 8 | }) 9 | 10 | // Initialized as UInt and casted to SInt 11 | val y1 = (23.U).asSInt 12 | val in1 = io.x + y1 13 | io.z := in1.asUInt + io.y // Typecast SInt to UInt 14 | } 15 | 16 | println((new chisel3.stage.ChiselStage).emitVerilog(new AdderWithOffset)) 17 | -------------------------------------------------------------------------------- /Example_code/Lab15/miniConfig.scala: -------------------------------------------------------------------------------- 1 | import chisel3.Module 2 | import freechips.rocketchip.config.{Parameters, Config} 3 | import junctions._ 4 | 5 | class MiniConfig extends Config((site, here, up) => { 6 | // Core 7 | case XLEN => 32 8 | case Trace => true 9 | case BuildALU => (p: Parameters) => Module(new ALUArea()(p)) 10 | case BuildImmGen => (p: Parameters) => Module(new ImmGenWire()(p)) 11 | case BuildBrCond => (p: Parameters) => Module(new BrCondArea()(p)) 12 | 13 | ... -------------------------------------------------------------------------------- /Example_code/Lab2/Mux_5x1.scala: -------------------------------------------------------------------------------- 1 | package Lab2 2 | 3 | import chisel3._ 4 | 5 | class LM_IO_Interface extends Bundle { 6 | val s0 = Input(Bool()) 7 | val s1 = Input(Bool()) 8 | val s2 = Input(Bool()) 9 | val out = Output(UInt(32.W)) 10 | } 11 | 12 | class Mux_5to1 extends Module { 13 | val io = IO(new LM_IO_Interface) 14 | 15 | // Start coding here 16 | 17 | 18 | // End your code here 19 | } 20 | println((new chisel3.stage.ChiselStage).emitVerilog(new Mux_5to1)) 21 | -------------------------------------------------------------------------------- /Example_code/Lab4/dontTouch.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.stage.ChiselStage 3 | 4 | class DontTouch extends Module { 5 | val io = IO(new Bundle { 6 | val a = Input(UInt(32.W)) 7 | val b = Output(UInt(32.W)) 8 | }) 9 | 10 | io.b := io.a 11 | val reg1 = RegInit(18.U) 12 | val unused = io.a + reg1 // 'unused' will be eliminated if not 13 | dontTouch(unused) // preserved with dontTouch 14 | } 15 | 16 | println((new ChiselStage).emitVerilog(new DontTouch)) -------------------------------------------------------------------------------- /Example_code/Lab9/list_lookup.scala: -------------------------------------------------------------------------------- 1 | class Control extends Module { 2 | val io = IO(new ControlSignals) 3 | val ctrlSignals = ListLookup(io.inst, Control.default, Control.map) 4 | 5 | // Control signals for Fetch 6 | io.pc_sel := ctrlSignals(0) 7 | io.inst_kill := ctrlSignals(6).toBool 8 | 9 | // Control signals for Execute 10 | io.A_sel := ctrlSignals(1) 11 | io.B_sel := ctrlSignals(2) 12 | io.imm_sel := ctrlSignals(3) 13 | io.alu_op := ctrlSignals(4) 14 | 15 | ... -------------------------------------------------------------------------------- /Example_code/Lab5/Bundle_param_mux.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | 4 | class LM_IO_Interface[T <: Data](data_type:T) extends Bundle{ 5 | val in1 = Input(data_type.cloneType) 6 | val in2 = Input(data_type.cloneType) 7 | val out = Output(data_type.cloneType) 8 | val sel = Input(Bool()) 9 | } 10 | 11 | class Mux_2 extends Module{ 12 | val io = IO(new LM_IO_Interface(8.U)) 13 | 14 | io.out := Mux(io.sel,io.in1,io.in2) 15 | } 16 | println(chisel3.Driver.emitVerilog(new Mux_2)) 17 | -------------------------------------------------------------------------------- /Example_code/Lab2/Barrel_skeleton.scala: -------------------------------------------------------------------------------- 1 | package Lab2 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | 6 | class barrel_shift extends Module{ 7 | val io = IO(new Bundle{ 8 | val in = Vec(4, Input(Bool())) 9 | val sel = Vec(2, Input(Bool())) 10 | val shift_type = Input(Bool()) 11 | val out = Vec(4, Output(Bool())) 12 | }) 13 | 14 | // Start you code here 15 | 16 | 17 | // End your code here 18 | } 19 | println((new chisel3.stage.ChiselStage).emitVerilog(new barrel_shift)) 20 | -------------------------------------------------------------------------------- /Example_code/Lab3/aluOp.scala: -------------------------------------------------------------------------------- 1 | object ALUOP { 2 | // ALU Operations, may expand/modify in future 3 | val ALU_ADD = 0.U(4.W) 4 | val ALU_SUB = 1.U(4.W) 5 | val ALU_AND = 2.U(4.W) 6 | val ALU_OR = 3.U(4.W) 7 | val ALU_XOR = 4.U(4.W) 8 | val ALU_SLT = 5.U(4.W) 9 | val ALU_SLL = 6.U(4.W) 10 | val ALU_SLTU = 7.U(4.W) 11 | val ALU_SRL = 8.U(4.W) 12 | val ALU_SRA = 9.U(4.W) 13 | val ALU_COPY_A = 10.U(4.W) 14 | val ALU_COPY_B = 11.U(4.W) 15 | val ALU_XXX = 15.U(4.W) 16 | } -------------------------------------------------------------------------------- /Example_code/Lab10/match.scala: -------------------------------------------------------------------------------- 1 | def ALU_Scala(a: Int, b: Int, op: Int): Int = { 2 | op match { 3 | case 1 => a + b 4 | case 2 => a - b 5 | case 3 => a & b 6 | case 4 => a | b 7 | case 5 => a ^ b 8 | case _ => -999 // This should not happen 9 | } 10 | } 11 | 12 | var result = ALU_Scala(18,11,2) 13 | println(s"The result is: $result") 14 | 15 | result = ALU_Scala(12,17,9) 16 | println(s"The result is: $result") 17 | 18 | // The output at the terminal 19 | The result is: 7 20 | The result is: -999 -------------------------------------------------------------------------------- /Example_code/Lab5/bundle_param.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | 4 | class IO_Interface[T <: Data] (data_type:T) extends Bundle{ 5 | val in1 = Input(data_type.cloneType) 6 | val in2 = Input(data_type.cloneType) 7 | val out = Output(data_type.cloneType) 8 | val sel = Input(Bool()) 9 | } 10 | 11 | class Adder(size: UInt) extends Module{ 12 | val io = IO(new IO_Interface(size)) 13 | 14 | io.out := io.in1 + io.in2 15 | } 16 | println((new chisel3.stage.ChiselStage).emitVerilog(new Adder(15.U))) -------------------------------------------------------------------------------- /Example_code/Lab6/BBAdderInline.scala: -------------------------------------------------------------------------------- 1 | class BlackBoxAdder extends BlackBox with HasBlackBoxInline { 2 | val io = IO(new Bundle() { 3 | val in1 = Input(UInt(32.W)) 4 | val in2 = Input(UInt(32.W)) 5 | val out = Output(UInt(33.W)) 6 | }) 7 | setInline("BlackBoxAdder.v", 8 | s""" 9 | |module BlackBoxAdder( 10 | | input [32:0] in1, 11 | | input [32:0] in2, 12 | | output [33:0] out 13 | |); 14 | |always @* begin 15 | | out <= ((in1) + (in2)); 16 | |end 17 | |endmodule 18 | """.stripMargin) 19 | } 20 | -------------------------------------------------------------------------------- /Example_code/Lab6/shift_reg.scala: -------------------------------------------------------------------------------- 1 | // shift register example 2 | import chisel3._ 3 | 4 | class shift_reg(val init: Int = 1) extends Module { 5 | val io = IO(new Bundle{ 6 | val in = Input(Bool()) 7 | val out = Output(UInt(4.W)) 8 | }) 9 | // register initialization 10 | val state = RegInit(init.U(4.W)) 11 | 12 | // serial data in at LSB 13 | val nextState = (state << 1) | io.in 14 | state := nextState 15 | io.out := state 16 | } 17 | println((new chisel3.stage.ChiselStage).emitVerilog(new shift_reg)) -------------------------------------------------------------------------------- /Example_code/Lab5/Func_param_eMux.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | 4 | class eMux[T<:Data](gen:T) extends Module{ 5 | val io = IO(new Bundle{ 6 | val out = Output(gen) 7 | val in1 = Input(gen) 8 | val in2 = Input(gen) 9 | val sel = Input(Bool()) 10 | }) 11 | io.out := Mux2_to_1(io.in2, io.in1, io.sel) 12 | 13 | def Mux2_to_1[T <: Data](in_0:T, in_1:T, sel:Bool):T = { 14 | Mux(sel, in_1, in_0) } 15 | } 16 | println((new chisel3.stage.ChiselStage).emitVerilog(new eMux(SInt(2.W)))) -------------------------------------------------------------------------------- /Example_code/Lab10/placeHolder.scala: -------------------------------------------------------------------------------- 1 | // An example List 2 | val uList = List(11, -10, 5, 0, -5, 10) 3 | 4 | // Applying .filter to List 5 | val uList_filter1 = uList.filter(x => x > -1) 6 | println(s"Filtered list = $uList_filter1") 7 | 8 | // Applying .filter to List using _ 9 | val uList_filter2 = uList.filter(_ > -1) 10 | println(s"Filtered list using _ as place holder = $uList_filter2") 11 | 12 | // The output at the terminal 13 | Filtered list = List(11, 5, 0, 10) 14 | Filtered list using _ as place holder = List(11, 5, 0, 10) -------------------------------------------------------------------------------- /Example_code/Lab15/miniConfig_slides.scala: -------------------------------------------------------------------------------- 1 | import chisel3.Module 2 | import freechips.rocketchip.config.{Parameters, Config} 3 | 4 | class MiniConfig extends Config((site, here, up) => { 5 | case XLEN => 32 6 | case Trace => true 7 | case BuildALU => (p: Parameters) => Module(new ALUArea()(p)) 8 | ... 9 | } 10 | 11 | // Different parameters defined as case objects in core.scala 12 | case object XLEN extends Field[Int] 13 | case object Trace extends Field[Boolean] 14 | case object BuildALU extends Field[Parameters => ALU] 15 | -------------------------------------------------------------------------------- /Example_code/Lab3/Right_Or.scala: -------------------------------------------------------------------------------- 1 | \\Right Or 2 | class RightOR extends Module { 3 | val io = IO(new LM_IO_Interface) 4 | 5 | def rightOR(x: UInt): UInt = { 6 | val width = x.getWidth 7 | val stop = width 8 | def helper(s: Int, x: UInt): UInt = 9 | if (s >= stop) x else helper(s+s, x | (x >> s)) 10 | helper(1, x)(width-1, 0) 11 | } 12 | 13 | io.out := rightOR(io.in) 14 | } 15 | 16 | class LM_IO_Interface extends Bundle { 17 | val in = Input(UInt(8.W)) 18 | val out = Output(UInt()) 19 | } 20 | -------------------------------------------------------------------------------- /Example_code/Lab3/Left_Or.scala: -------------------------------------------------------------------------------- 1 | \\Left Or 2 | class LeftOR extends Module { 3 | val io = IO(new LM_IO_Interface) 4 | 5 | def leftOR(x: UInt): UInt = { 6 | val width = x.getWidth 7 | val stop = width 8 | def helper(s: Int, x: UInt): UInt = 9 | if (s >= stop) x else helper(s+s, x | (x << s)(width-1,0)) 10 | helper(1, x)(width-1, 0) 11 | } 12 | 13 | io.out := leftOR(io.in) 14 | } 15 | 16 | class LM_IO_Interface extends Bundle { 17 | val in = Input(UInt(8.W)) 18 | val out = Output(UInt()) 19 | } 20 | -------------------------------------------------------------------------------- /Example_code/Lab5/func_param.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | 4 | class Multiply_Acc(gen: UInt) extends Module { 5 | val io = IO(new Bundle { 6 | val out = Output(gen) 7 | val in1 = Input(gen) 8 | val in2 = Input(gen) 9 | val in3 = Input(gen) 10 | }) 11 | 12 | io.out := multiply_add(io.in1, io.in2, io.in3) 13 | 14 | def multiply_add[T <: UInt](in_1: T, in_2: T, in_3: T) = { 15 | in_1 * in_2 + in_3 16 | } 17 | } 18 | 19 | println(chisel3.Driver.emitVerilog(new Multiply_Acc(UInt(2.W)))) -------------------------------------------------------------------------------- /Example_code/Lab6/shift_register.scala: -------------------------------------------------------------------------------- 1 | // shift register example 2 | import chisel3._ 3 | 4 | class shift_register(val init: Int = 1) extends Module { 5 | val io = IO(new Bundle{ 6 | val in = Input(Bool()) 7 | val out = Output(UInt(4.W)) 8 | }) 9 | val state = RegInit(init.U(4.W)) // register initialization 10 | 11 | // serial data in at LSB 12 | val nextState = (state << 1) | io.in 13 | state := nextState 14 | io.out := state 15 | } 16 | println((new chisel3.stage.ChiselStage).emitVerilog(new shift_register)) 17 | -------------------------------------------------------------------------------- /Example_code/Lab10/reduce.scala: -------------------------------------------------------------------------------- 1 | // Illustration of reduce method for Lists 2 | val uList = List(1, 2, 3, 4, 5) 3 | 4 | val uSum_Explicit = uList.reduce((a, b) => a + b) 5 | println(s"Sum of elements using reduce function explicitly= $uSum_Explicit") 6 | 7 | val uSum: Double = uList.reduce(_ + _) 8 | println(s"Sum of elements using reduce function with wildcard = $uSum") 9 | 10 | // The output at the terminal is given below 11 | Sum of elements using reduce function explicitly = 15 12 | Sum of elements using reduce function with wildcard = 15.0 13 | -------------------------------------------------------------------------------- /Example_code/Lab2/mux2to1v.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | 3 | // Mux IO interface class 4 | class Mux_2to1_IO extends Bundle { 5 | val in_A = Input(UInt(32.W)) 6 | val in_B = Input(UInt(32.W)) 7 | val select = Input(Bool()) 8 | val out = Output(UInt()) 9 | } 10 | // 2 to 1 Mux implementation 11 | class Mux_2to1 extends Module { 12 | val io = IO(new Mux2to1_IO) 13 | 14 | // update the output 15 | io.out := Mux(io.select, io.in_A, io.in_B) 16 | } 17 | println((new chisel3.stage.ChiselStage).emitVerilog(new Mux_2to1())) 18 | -------------------------------------------------------------------------------- /Example_code/Lab2/mux2to1s.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | 3 | // Mux IO interface class 4 | class Mux_2to1_IO extends Bundle { 5 | val in_A = Input(Bool()) 6 | val in_B = Input(Bool()) 7 | val select = Input(Bool()) 8 | val out = Output(Bool()) 9 | } 10 | // 2 to 1 Mux implementation 11 | class Mux_2to1 extends Module { 12 | val io = IO(new Mux_2to1_IO) 13 | 14 | // update the output 15 | io.out := io.in_A & io.select | io.in_B & (~io.select) 16 | } 17 | println((new chisel3.stage.ChiselStage).emitVerilog(new Mux_2to1())) 18 | -------------------------------------------------------------------------------- /Example_code/Lab6/queue.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | 4 | class User_Queue extends Module { 5 | val io = IO(new Bundle { 6 | //valid is Input, ready is Output, bits is Input 7 | val in = Flipped(Decoupled(UInt(8.W))) 8 | //valid is Output, ready is Input , bits is Output 9 | val out = Decoupled(UInt(8.W)) 10 | }) 11 | // 16 element queue 12 | val queue = Module(new Queue(UInt(), 16)) 13 | queue.io.enq <> io.in 14 | io.out <> queue.io.deq 15 | } 16 | 17 | println(chisel3.Driver.emitVerilog(new User_Queue)) -------------------------------------------------------------------------------- /Example_code/Lab13/partialFunction.scala: -------------------------------------------------------------------------------- 1 | val squareRoot: PartialFunction[Double, Double] = { 2 | case d: Double if d > 0 => Math.sqrt(d) 3 | } 4 | val list: List[Double] = List(4, 16, 25, -9) 5 | val result = list.collect(squareRoot) 6 | // OR 7 | val result = list collect squareRoot 8 | 9 | // The output is shown below 10 | result: List[Double] = List(2.0, 4.0, 5.0) 11 | 12 | // Doing the same with the map method 13 | val list: List[Double] = List(4, 16, 25, -9) 14 | val result = list.map(Math.sqrt) 15 | result: List[Double] = List(2.0, 4.0, 5.0, NaN) -------------------------------------------------------------------------------- /Example_code/Lab2/mux4to1.scala: -------------------------------------------------------------------------------- 1 | // Mux4to1 example 2 | import chisel3._ 3 | 4 | class IO_Interface extends Bundle { 5 | val in = Input(UInt(4.W)) 6 | val s1 = Input(Bool()) 7 | val s2 = Input(Bool()) 8 | val out = Output(Bool()) // UInt(1.W)) 9 | } 10 | 11 | class Mux_4to1 extends Module { 12 | val io = IO(new IO_Interface) 13 | 14 | io.out := Mux(io.s2, Mux(io.s1, io.in(3), io.in(2)), 15 | Mux(io.s1, io.in(1), io.in(0))) 16 | } 17 | 18 | println((new chisel3.stage.ChiselStage).emitVerilog(new Mux_4to1())) 19 | -------------------------------------------------------------------------------- /Example_code/Lab4/MuxTree.scala: -------------------------------------------------------------------------------- 1 | package LM_Chisel 2 | import chisel3._ 3 | 4 | class MuxTreeIO extends Bundle { 5 | val in_1 = Input(UInt(32.W)) 6 | val in_2 = Input(UInt(32.W)) 7 | val in_3 = Input(UInt(32.W)) 8 | val sel_1 = Input(Bool()) 9 | val sel_2 = Input(Bool()) 10 | val out = Output(UInt()) 11 | } 12 | 13 | // 3 to 1 MuxTree implementation 14 | class MuxTree extends Module { 15 | val io = IO(new MuxTreeIO) 16 | 17 | // update the output 18 | io.out := Mux(io.sel_2, io.in_3, Mux(io.sel_1, io.in_2, io.in_1)) 19 | } -------------------------------------------------------------------------------- /Example_code/Lab9/lists.scala: -------------------------------------------------------------------------------- 1 | // List of Strings 2 | val modules: List[String] = List("ALU", "Branch", "Control") 3 | 4 | // List of Integers 5 | val nums: List[Int] = List(1, 2, 3, 3, 4) 6 | 7 | // Two dimensional list 8 | val matrix: List[List[Int]] = 9 | List( List(1, 0, 0), 10 | List(0, 1, 0), 11 | List(0, 0, 1) ) 12 | 13 | // Display the lists 14 | println(modules) // List(ALU, Branch, Control) 15 | println(nums) // List(1, 2, 3, 3, 4) 16 | println(matrix) // List(List(1, 0, 0), List(0, 1, 0), List(0, 0, 1)) 17 | 18 | 19 | -------------------------------------------------------------------------------- /Example_code/Lab3/Immediate_Extension_Skeleton.scala: -------------------------------------------------------------------------------- 1 | // Immediate (Assignment) 2 | package lab3 3 | import chisel3._ 4 | import chisel3.util._ 5 | 6 | class LM_IO_Interface_ImmdValGen extends Bundle { 7 | val instr = Input(UInt(32.W)) 8 | val immd_se = Output(UInt(32.W)) 9 | } 10 | 11 | class ImmdValGen extends Module { 12 | val io = IO(new LM_IO_Interface_ImmdValGen) 13 | 14 | // Start coding here 15 | 16 | // End your code here 17 | // Well, you can actually write classes too. So, technically you have no 18 | limit ;) 19 | } 20 | 21 | 22 | -------------------------------------------------------------------------------- /Example_code/Lab6/up_down_counter.scala: -------------------------------------------------------------------------------- 1 | // Up-down counter example 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class up_down_counter(val max: Int = 10) extends Module { 6 | val io = IO(new Bundle{ 7 | val out = Output(UInt(log2Ceil(max).W)) 8 | val up_down = Input(Bool()) 9 | }) 10 | val counter = RegInit(0.U(log2Ceil(max).W)) 11 | counter := Mux(io.up_down, 12 | Mux(counter===(max-1).U, 0.U, counter+1.U), counter-1.U) 13 | io.out := counter 14 | } 15 | 16 | println((new chisel3.stage.ChiselStage).emitVerilog(new up_down_counter(4))) 17 | -------------------------------------------------------------------------------- /Example_code/Lab10/foldAve.scala: -------------------------------------------------------------------------------- 1 | // source collection 2 | val uList = List(1, 5, 7, 8) 3 | 4 | // converting every element to a pair of the form (x,1) 5 | val uList_Modified = uList.map(x => (x, 1)) 6 | 7 | // adding elements at correspnding positions 8 | val result = uList_Modified.fold(0,0)((a, b) => (a._1 + b._1, a._2 + b._2)) 9 | val average = (result._1).toFloat / (result._2).toFloat 10 | 11 | println("(sum, no_of_elements) = " + result) 12 | println("Average = " + average) 13 | 14 | // The result at the terminal 15 | (sum, no_of_elements) = (21,4) 16 | Average = 5.25 -------------------------------------------------------------------------------- /Example_code/Lab10/reduceAve.scala: -------------------------------------------------------------------------------- 1 | // source collection 2 | val uList = List(1, 5, 7, 8) 3 | 4 | // converting every element to a pair of the form (x,1) 5 | val uList_Modified = uList.map(x => (x, 1)) 6 | 7 | // adding elements at correspnding positions 8 | val result = uList_Modified.reduce((a, b) => (a._1 + b._1, a._2 + b._2)) 9 | val average = (result._1).toFloat / (result._2).toFloat 10 | 11 | println("(sum, no_of_elements) = " + result) 12 | println("Average = " + average) 13 | 14 | // The result at the terminal 15 | (sum, no_of_elements) = (21,4) 16 | Average = 5.25 -------------------------------------------------------------------------------- /Example_code/Lab5/2_to_2_line_switch.scala: -------------------------------------------------------------------------------- 1 | 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class cross_bar_2_to_1[T<:Data](gen:T) extends Module{ 6 | val io = IO(new Bundle{ 7 | val in1 = Input(gen) 8 | val in2 = Input(gen) 9 | val out1 = Output(gen) 10 | val out2 = Output(gen) 11 | val sel = Input(Bool()) 12 | }) 13 | when(io.sel){ 14 | io.out1 := io.in2 15 | io.out2 := io.in1} 16 | .otherwise{ 17 | io.out1 := io.in1 18 | io.out2 := io.in2 19 | } 20 | } 21 | println(chisel3.Driver.emitVerilog(new cross_bar_2_to_1(UInt(8.W)))) 22 | 23 | -------------------------------------------------------------------------------- /Example_code/Lab2/mux_onehot.scala: -------------------------------------------------------------------------------- 1 | // Mux-Onehot example 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class mux_onehot_4to1 extends Module { 6 | val io = IO(new Bundle { 7 | val in0 = Input(UInt(32.W)) 8 | val in1 = Input(UInt(32.W)) 9 | val in2 = Input(UInt(32.W)) 10 | val in3 = Input(UInt(32.W)) 11 | val sel = Input(UInt(4.W)) 12 | val out = Output(UInt(32.W)) 13 | }) 14 | 15 | io.out := Mux1H(io.sel, Seq(io.in0, io.in1, io.in2, io.in3)) 16 | } 17 | 18 | println((new chisel3.stage.ChiselStage).emitVerilog(new mux_onehot_4to1())) 19 | -------------------------------------------------------------------------------- /Example_code/Lab5/Assignment2_skeleton .scala: -------------------------------------------------------------------------------- 1 | 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class cross_bar_2_to_1[T<:Data](gen:T) extends Module{ 6 | val io = IO(new Bundle{ 7 | val in1 = Input(gen) 8 | val in2 = Input(gen) 9 | val out1 = Output(gen) 10 | val out2 = Output(gen) 11 | val sel = Input(Bool()) 12 | }) 13 | when(io.sel){ 14 | io.out1 := io.in2 15 | io.out2 := io.in1} 16 | .otherwise{ 17 | io.out1 := io.in1 18 | io.out2 := io.in2 19 | } 20 | } 21 | println(chisel3.Driver.emitVerilog(new cross_bar_2_to_1(UInt(8.W)))) 22 | 23 | -------------------------------------------------------------------------------- /Example_code/Lab5/Assignment2_skeleton2.scala: -------------------------------------------------------------------------------- 1 | 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class cross_bar_2_to_1[T<:Data](gen:T) extends Module{ 6 | val io = IO(new Bundle{ 7 | val in1 = Input(gen) 8 | val in2 = Input(gen) 9 | val out1 = Output(gen) 10 | val out2 = Output(gen) 11 | val sel = Input(Bool()) 12 | }) 13 | when(io.sel){ 14 | io.out1 := io.in2 15 | io.out2 := io.in1} 16 | .otherwise{ 17 | io.out1 := io.in1 18 | io.out2 := io.in2 19 | } 20 | } 21 | println(chisel3.Driver.emitVerilog(new cross_bar_2_to_1(UInt(8.W)))) 22 | 23 | -------------------------------------------------------------------------------- /Example_code/Lab5/Module_param_Crossbar.scala: -------------------------------------------------------------------------------- 1 | 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class cross_bar_2_to_1[T<:Data](gen:T) extends Module{ 6 | val io = IO(new Bundle{ 7 | val in1 = Input(gen) 8 | val in2 = Input(gen) 9 | val out1 = Output(gen) 10 | val out2 = Output(gen) 11 | val sel = Input(Bool()) 12 | }) 13 | when(io.sel){ 14 | io.out1 := io.in2 15 | io.out2 := io.in1} 16 | .otherwise{ 17 | io.out1 := io.in1 18 | io.out2 := io.in2 19 | } 20 | } 21 | println(chisel3.Driver.emitVerilog(new cross_bar_2_to_1(UInt(8.W)))) 22 | 23 | -------------------------------------------------------------------------------- /Example_code/Lab8/arbiter.scala: -------------------------------------------------------------------------------- 1 | // Priority arbiter example 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class arbiter extends Module{ 6 | val io = IO(new Bundle { 7 | val in = Flipped(Vec(2, Decoupled(UInt(8.W)))) 8 | val out = Decoupled(UInt(8.W)) 9 | }) 10 | // Arbiter doesn't have a convenience constructor, so it's built like any Module 11 | val arbiter = Module(new Arbiter(UInt(8.W), 2)) // 2 to 1 Priority Arbiter 12 | arbiter.io.in <> io.in 13 | io.out <> arbiter.io.out 14 | } 15 | 16 | println((new chisel3.stage.ChiselStage).emitVerilog(new arbiter)) 17 | -------------------------------------------------------------------------------- /Example_code/Lab8/arbitor.scala: -------------------------------------------------------------------------------- 1 | // Priority arbiter example 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class arbiter extends Module{ 6 | val io = IO(new Bundle { 7 | val in = Flipped(Vec(2, Decoupled(UInt(8.W)))) 8 | val out = Decoupled(UInt(8.W)) 9 | }) 10 | // Arbiter doesn't have a convenience constructor, so it's built like any Module 11 | val arbiter = Module(new Arbiter(UInt(8.W), 2)) // 2 to 1 Priority Arbiter 12 | arbiter.io.in <> io.in 13 | io.out <> arbiter.io.out 14 | } 15 | 16 | println((new chisel3.stage.ChiselStage).emitVerilog(new arbiter)) 17 | -------------------------------------------------------------------------------- /Example_code/Lab6/one_shot_timer.scala: -------------------------------------------------------------------------------- 1 | // One shot generator 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class oneShotTimer extends Module { 6 | val io = IO(new Bundle{ 7 | val reloadValue = Input(UInt(8.W)) 8 | val reload = Input(Bool()) 9 | val out = Output(Bool()) 10 | }) 11 | val counter = RegInit(0.U(8.W)) 12 | counter := RegNext(Mux(RegNext(io.reload) & !io.reload, io.reloadValue, Mux(counter===0.U, 0.U, counter-1.U))) 13 | io.out := (counter===0.U) & RegNext(counter===1.U) 14 | } 15 | 16 | println((new chisel3.stage.ChiselStage).emitVerilog(new oneShotTimer())) 17 | -------------------------------------------------------------------------------- /Example_code/Lab11/map.scala: -------------------------------------------------------------------------------- 1 | // An example list 2 | val uList = List(1, 2, 3, 4, 5) 3 | 4 | // map method applied to List 5 | val uList_Twice = uList.map( x => x*2 ) 6 | println(s"List elements doubled = $uList_Twice") 7 | 8 | // Applying map to List using user defined method 9 | def f(x: Int) = if (x > 2) x*x else None 10 | val uList_Squared = uList.map(x => f(x)) 11 | println(s"List elements squared selectively = $uList_Squared") 12 | 13 | // The output at the terminal is given below 14 | List elements doubled = List(2, 4, 6, 8, 10) 15 | List elements squared selectively = List(None, None, 9, 16, 25) -------------------------------------------------------------------------------- /Example_code/Lab14/implictClass.scala: -------------------------------------------------------------------------------- 1 | class StringModifier(s: String) { 2 | def increment = s.map(c => ((c + 1).toChar).toUpper) 3 | } 4 | 5 | val result = (new StringModifier("hal")).increment 6 | println("hal is modified to: " + result) 7 | 8 | // The output at the terminal 9 | hal is modified to: IBM 10 | 11 | 12 | 13 | implicit class StringModifier(s: String) { 14 | def increment = s.map(c => ((c + 1).toChar).toUpper) 15 | } 16 | 17 | val result = ("hal").increment 18 | println("hal is modified to: " + result) 19 | 20 | // The output at the terminal 21 | HAL is modified to: IBM 22 | -------------------------------------------------------------------------------- /Example_code/Lab2/muxTree_slides.scala: -------------------------------------------------------------------------------- 1 | // Mux with input priority 2 | import chisel3._ 3 | 4 | class IO_Interface extends Bundle { 5 | val in = Input(UInt(4.W)) 6 | val s1 = Input(Bool()) 7 | val s2 = Input(Bool()) 8 | val s3 = Input(Bool()) 9 | val out = Output(Bool()) // UInt(1.W)) 10 | } 11 | 12 | class Mux_Tree extends Module { 13 | val io = IO(new IO_Interface) 14 | 15 | io.out := Mux(io.s3, io.in(3), Mux(io.s2, io.in(2), 16 | Mux(io.s1, io.in(1), io.in(0)))) 17 | } 18 | println((new chisel3.stage.ChiselStage).emitVerilog(new Mux_Tree())) -------------------------------------------------------------------------------- /Example_code/Lab8/RRarbiter.scala: -------------------------------------------------------------------------------- 1 | // Round robin arbiter example 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class RR_Arbiter extends Module{ 6 | val io = IO(new Bundle { 7 | val in = Flipped(Vec(2, Decoupled(UInt(8.W)))) 8 | val out = Decoupled(UInt(8.W)) 9 | }) 10 | // RRArbiter doesn't have a convenience constructor, so it's built like any Module 11 | val arbiter = Module(new Arbiter(UInt(8.W), 2)) // 2 to 1 round robin Arbiter 12 | arbiter.io.in <> io.in 13 | io.out <> arbiter.io.out 14 | } 15 | 16 | println((new chisel3.stage.ChiselStage).emitVerilog(new RR_Arbiter)) 17 | -------------------------------------------------------------------------------- /Example_code/Lab2/bitField.scala: -------------------------------------------------------------------------------- 1 | // Bitfield manipulations 2 | val xMSB = x(31) // when x is 32-bit 3 | val yLowByte = y(7, 0) // y is atleat 8-bit 4 | 5 | // concatenates bitfields with first operand on left 6 | val address = Cat(highByte, lowByte) 7 | 8 | // replicate a string multiple times 9 | val duplicate = Fill(2, "b1010".U) // "b10101010".U 10 | 11 | // Bitfield reductions 12 | val data = "b00111010".U 13 | val allOnes = data.andR // performs AND reduction 14 | val anyOne = data.orR // performs OR reduction 15 | val parityCheck = data.xorR // performs XOR reduction -------------------------------------------------------------------------------- /Example_code/Lab11/map_flatMap.scala: -------------------------------------------------------------------------------- 1 | // An example list 2 | val uList: List[Int] = List(1, 2, 3, 4, 5) 3 | 4 | def g(v:Int) = List(v-1, v, v+1) 5 | val uList_Extended = uList.map(x => g(x)) 6 | println(s"Extended list using map = $uList_Extended") 7 | 8 | val uList_Extended_flatmap = uList.flatMap(x => g(x)) 9 | println(s"Extended list using flatMap = $uList_Extended_flatmap") 10 | 11 | // The output at the terminal is 12 | Extended list using map = List(List(0, 1, 2), List(1, 2, 3), List(2, 3, 4), List(3, 4, 5), List(4, 5, 6)) 13 | 14 | Extended list using flatMap = List(0, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 6) -------------------------------------------------------------------------------- /Example_code/Lab5/module_param.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | 4 | class switch_2cross2 [T <: Data](parameter:T) extends Module{ 5 | val io = IO(new Bundle{ 6 | val in1 = Input(parameter) 7 | val in2 = Input(parameter) 8 | val out1 = Output(parameter) 9 | val out2 = Output(parameter) 10 | val sel = Input(Bool()) 11 | }) 12 | 13 | when(io.sel){ 14 | io.out1 := io.in2 15 | io.out2 := io.in1 16 | } 17 | .otherwise{ 18 | io.out1 := io.in1 19 | io.out2 := io.in2 20 | } 21 | } 22 | 23 | println(chisel3.Driver.emitVerilog(new switch_2cross2(UInt(8.W)))) -------------------------------------------------------------------------------- /Example_code/Lab10/function_higherOrder.scala: -------------------------------------------------------------------------------- 1 | // Define a higher order function 2 | def higherOrder(a: Int, b: Int, c: Int, d: Int, function: (Int, Int) => Int) = { 3 | val first_inst = function(a, b) 4 | val second_inst = function(c, d) 5 | function(first_inst, second_inst) 6 | } 7 | 8 | // call to higherOrder function 9 | val result1 = higherOrder(2, 5, 7, 9, (x, y) => x + y) 10 | val result2 = higherOrder(2, 5, 7, 9, _ + _) 11 | 12 | println(s"The result1 is = $result1") 13 | println(s"The result2 is same = $result2") 14 | 15 | // The output at the terminal 16 | The result1 is = 23 17 | The result2 is same = 23 18 | -------------------------------------------------------------------------------- /Example_code/Lab2/Mux_8x1.scala: -------------------------------------------------------------------------------- 1 | // Mux 8 to 1 (Assignment) 2 | import chisel3._ 3 | 4 | class LM_IO_Interface extends Bundle { 5 | val in = Input(UInt(8.W)) 6 | val s0 = Input(Bool()) 7 | val s1 = Input(Bool()) 8 | val s2 = Input(Bool()) 9 | val out = Output(Bool()) //UInt(1.W)) 10 | } 11 | 12 | class Mux_8to1 extends Module { 13 | val io = IO(new LM_IO_Interface) 14 | 15 | // Start coding here 16 | 17 | 18 | // End your code here 19 | // Well, you can actually write classes too. So, technically you have no limit ;) 20 | } 21 | println((new chisel3.stage.ChiselStage).emitVerilog(new Mux_8to1)) 22 | -------------------------------------------------------------------------------- /Example_code/Lab5/Counter_param.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.iotesters.{ChiselFlatSpec,Driver,PeekPokeTester} 3 | 4 | class Counter(size:Int, maxValue:UInt) extends Module{ 5 | val io = IO(new Bundle{ 6 | val result = Output(Bool()) 7 | }) 8 | 9 | def genCounter(n: Int, max :UInt) = { 10 | val count = RegInit(0.U(n.W)) 11 | 12 | when(count === max){ 13 | count := 0.U 14 | } 15 | .otherwise 16 | { 17 | count := count+1.U 18 | } 19 | count 20 | } 21 | 22 | // genCounter instantiation 23 | val counter1 = genCounter(size,maxValue) 24 | io.result := counter1(size-1) 25 | } 26 | println(chisel3.Driver.emitVerilog(new Counter(8,255.U))) 27 | -------------------------------------------------------------------------------- /Example_code/Lab1/counter.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | 3 | class Counter(size: Int, maxValue: UInt) extends Module { 4 | val io = IO(new Bundle { 5 | val result = Output(Bool()) 6 | }) 7 | 8 | // 'genCounter' with counter size 'n' 9 | def genCounter(n: Int, max: UInt) = { 10 | val count = RegInit(0.U(n.W)) 11 | 12 | when(count === max) { 13 | count := 0.U 14 | }.otherwise { count := count + 1.U } 15 | count 16 | } 17 | 18 | // genCounter instantiation 19 | val counter1 = genCounter(size, maxValue) 20 | io.result := counter1(size-1) 21 | } 22 | 23 | println((new chisel3.stage.ChiselStage).emitVerilog(new Counter(8, 255.U))) 24 | -------------------------------------------------------------------------------- /Example_code/Lab3/Decoder_switch_statement.scala: -------------------------------------------------------------------------------- 1 | // Decoder using switch statement 2 | import chisel3._ 3 | 4 | class LM_IO_Interface extends Bundle { 5 | val in = Input(UInt(2.W)) 6 | val out = Output(UInt(4.W)) 7 | } 8 | 9 | class Decoder_2to4 extends Module { 10 | val io = IO(new LM_IO_Interface) 11 | 12 | io.out := 0.U 13 | switch (io.in) { 14 | is ("b00".U) {io.out := "b0001".U} 15 | is ("b01".U) {io.out := "b0010".U} 16 | is ("b10".U) {io.out := "b0100".U} 17 | is ("b11".U) {io.out := "b1000".U} 18 | } 19 | } 20 | 21 | println((new chisel3.stage.ChiselStage).emitVerilog(new Decoder_2to4())) 22 | -------------------------------------------------------------------------------- /Example_code/Lab11/unapply.scala: -------------------------------------------------------------------------------- 1 | class uModule(val name: String, val bitWidth: Int) 2 | 3 | // companion object 4 | object uModule { 5 | def apply(name: String, bitWidth: Int): uModule = new uModule(name, bitWidth) 6 | 7 | def unapply(mod: uModule): Option[(String, Int)] = { 8 | if (mod.bitWidth == 0) None 9 | else Some((mod.name, mod.bitWidth)) 10 | } 11 | } 12 | 13 | // Using the apply method 14 | val objA = uModule("ALU", 32) 15 | // Extractor using unapply method 16 | val uModule(module_name, module_bitW) = objA 17 | println("Module name is: " + module_name) 18 | 19 | // output at the terminal is 20 | Module name is: ALU -------------------------------------------------------------------------------- /Example_code/Lab3/Decoder_using_when.scala: -------------------------------------------------------------------------------- 1 | //Example 2 to 4 decoder 2 | import chisel3._ 3 | class LM_IO_Interface extends Bundle { 4 | val in = Input(UInt(2.W)) 5 | val out = Output(UInt(4.W)) 6 | } 7 | class Decoder_2to4 extends Module { 8 | val io = IO(new LM_IO_Interface) 9 | 10 | when(io.in === "b00".U) { 11 | io.out := "b0001".U 12 | } .elsewhen(io.in === "b01".U) { 13 | io.out := "b0010".U 14 | } .elsewhen(io.in === "b10".U) { 15 | io.out := "b0100".U 16 | } .otherwise { 17 | io.out := "b1000".U 18 | } 19 | 20 | } 21 | 22 | println((new chisel3.stage.ChiselStage).emitVerilog(new Decoder_2to4())) 23 | -------------------------------------------------------------------------------- /Example_code/Lab3/Encoder_switch_statement.scala: -------------------------------------------------------------------------------- 1 | // Encoder using switch statement 2 | import chisel3._ 3 | 4 | class LM_IO_Interface extends Bundle { 5 | val in = Input(UInt(4.W)) 6 | val out = Output(UInt(2.W)) 7 | } 8 | 9 | class Encoder_4to2 extends Module { 10 | val io = IO(new LM_IO_Interface) 11 | 12 | io.out := "b00".U 13 | switch(io.in) { 14 | is("b0001".U) {io.out := "b00".U} 15 | is("b0010".U) {io.out := "b01".U} 16 | is("b0100".U) {io.out := "b10".U} 17 | is("b1000".U) {io.out := "b11".U} 18 | } 19 | } 20 | 21 | println((new chisel3.stage.ChiselStage).emitVerilog(new Encoder_4to1())) 22 | 23 | -------------------------------------------------------------------------------- /Example_code/Lab8/instMem.scala: -------------------------------------------------------------------------------- 1 | package LM_Chisel 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | import chisel3.util.experimental.loadMemoryFromFile 6 | import scala.io.Source 7 | 8 | class InstMemIO extends Bundle with Config { 9 | val addr = Input(UInt(WLEN.W)) 10 | val inst = Output(UInt(WLEN.W)) 11 | } 12 | 13 | class InstMem(initFile: String) extends Module with Config { 14 | val io = IO(new InstMemIO) 15 | 16 | // INST_MEM_LEN in Bytes or INST_MEM_LEN / 4 in words 17 | val imem = Mem(INST_MEM_LEN, UInt(WLEN.W)) 18 | 19 | loadMemoryFromFile(imem , initFile) 20 | 21 | io.inst := imem (io.addr / 4.U) 22 | } 23 | -------------------------------------------------------------------------------- /Example_code/Lab10/apply_old.scala: -------------------------------------------------------------------------------- 1 | // Illustration of the order of reduce method 2 | val uList = List(11, 22, 33, 44, 55) 3 | val uSet = Set(11, 22, 33, 44, 55) 4 | val uMap = Map(1 -> 'a', 2 -> 'b', 3 -> 'c', 4 -> 'd') 5 | 6 | val list_apply: Double = uList.apply(1) 7 | println(s"Apply method for the List = $list_apply") 8 | 9 | val set_apply = uSet.apply(22) 10 | println(s"Apply method for the Set = $set_apply") 11 | 12 | val map_apply = uMap.apply(1) 13 | println(s"Apply method for the Map = $map_apply") 14 | 15 | // The output at the terminal 16 | Apply method for the List = 22.0 17 | Apply method for the Set = true 18 | Apply method for the Map = a -------------------------------------------------------------------------------- /Example_code/Lab6/shift_reg_with_parallel_load_Skeleton.scala: -------------------------------------------------------------------------------- 1 | // Shift register with parallel load 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class shift_reg_with_parallel_load(val len : Int=1) extends Module { 6 | val io = IO(new Bundle{ 7 | val out = Vec(len, Output(Bool())) 8 | val load_in = Vec(len, Input(Bool())) 9 | val in = Input(Bool()) 10 | val load = Input(Bool()) 11 | }) 12 | // Start Coding here 13 | 14 | 15 | // End your code here 16 | // Well, you can actually write classes too. So, technically you have no limit ;) 17 | } 18 | 19 | println((new chisel3.stage.ChiselStage).emitVerilog(new shift_reg_with_parallel_load(n))) 20 | -------------------------------------------------------------------------------- /Example_code/Examples/counter.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.stage.ChiselStage 3 | 4 | class Counter(size: Int, maxValue: UInt) extends Module { 5 | val io = IO(new Bundle { 6 | val result = Output(Bool()) 7 | }) 8 | 9 | // 'genCounter' with counter size 'n' 10 | def genCounter(n: Int, max: UInt) = { 11 | val count = RegInit(0.U(n.W)) 12 | 13 | when(count === max) { 14 | count := 0.U 15 | }.otherwise { count := count + 1.U } 16 | count 17 | } 18 | 19 | // genCounter instantiation 20 | val counter1 = genCounter(size, maxValue) 21 | io.result := counter1(size-1) 22 | } 23 | 24 | println((new ChiselStage).emitVerilog(new Counter(8, 255.U))) -------------------------------------------------------------------------------- /Example_code/Lab6/shift_reg_with_parallel_load_skeleton(1)(1).scala: -------------------------------------------------------------------------------- 1 | // Shift register with parallel load 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class shift_reg_with_parallel_load(val len : Int=1) extends Module { 6 | val io = IO(new Bundle{ 7 | val out = Vec(len, Output(Bool())) 8 | val load_in = Vec(len, Input(Bool())) 9 | val in = Input(Bool()) 10 | val load = Input(Bool()) 11 | }) 12 | // Start Coding here 13 | 14 | 15 | // End your code here 16 | // Well, you can actually write classes too. So, technically you have no limit ;) 17 | } 18 | 19 | println((new chisel3.stage.ChiselStage).emitVerilog(new shift_reg_with_parallel_load(n))) 20 | -------------------------------------------------------------------------------- /Example_code/Lab6/shift_reg_with_parallel_load_skeleton(1).scala: -------------------------------------------------------------------------------- 1 | // Shift register with parallel load 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class shift_reg_with_parallel_load(val len : Int=1) extends Module { 6 | val io = IO(new Bundle{ 7 | val out = Vec(len, Output(Bool())) 8 | val load_in = Vec(len, Input(Bool())) 9 | val in = Input(Bool()) 10 | val load = Input(Bool()) 11 | }) 12 | // Start Coding here 13 | 14 | 15 | // End your code here 16 | // Well, you can actually write classes too. So, technically you have no limit ;) 17 | } 18 | 19 | println((new chisel3.stage.ChiselStage).emitVerilog(new shift_reg_with_parallel_load(n))) 20 | -------------------------------------------------------------------------------- /Example_code/Lab11/map_flatMap2.scala: -------------------------------------------------------------------------------- 1 | // An example list 2 | val uList: List[Int] = List(1, 2, 3, 4, 5) 3 | 4 | // Applying map and flatMap to List with builtin Options class 5 | def f(x: Int) = if (x > 2) Some(x) else None 6 | val uList_selective = uList.map(x => f(x)) 7 | println(s"Selective elements of List with .map = $uList_selective") 8 | 9 | val uList_selective_flatMap = uList.flatMap(x => f(x)) 10 | println(s"Selective elements of List with .flatMap = $uList_selective_flatMap") 11 | 12 | // Output at the terminal 13 | Selective elements of List using .map = List(None, None, Some(3), Some(4), Some(5)) 14 | Selective elements of List using .flatMap = List(3, 4, 5) -------------------------------------------------------------------------------- /Example_code/Lab6/shift_reg_with_parallel_load_skeleton(1)(1)(1).scala: -------------------------------------------------------------------------------- 1 | // Shift register with parallel load 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class shift_reg_with_parallel_load(val len : Int=1) extends Module { 6 | val io = IO(new Bundle{ 7 | val out = Vec(len, Output(Bool())) 8 | val load_in = Vec(len, Input(Bool())) 9 | val in = Input(Bool()) 10 | val load = Input(Bool()) 11 | }) 12 | // Start Coding here 13 | 14 | 15 | // End your code here 16 | // Well, you can actually write classes too. So, technically you have no limit ;) 17 | } 18 | 19 | println((new chisel3.stage.ChiselStage).emitVerilog(new shift_reg_with_parallel_load(n))) 20 | -------------------------------------------------------------------------------- /Example_code/Lab7/CounterUpDownTest.scala: -------------------------------------------------------------------------------- 1 | package LM_Chisel 2 | import chisel3._ 3 | import chisel3.iotesters.{Driver, PeekPokeTester} 4 | 5 | class TestCounterUpDown(c: CounterUpDown) extends PeekPokeTester(c) { 6 | var data_in = 6 7 | poke(c.io.data_in, data_in.U) 8 | step(40) 9 | data_in = 10 10 | poke(c.io.data_in, data_in.U) 11 | step(50) 12 | } 13 | 14 | // object for tester class 15 | object CounterUpDown_Main extends App { 16 | iotesters.Driver.execute(Array("--is-verbose", 17 | "--generate-vcd-output","on", "--backend-name", "firrtl"), 18 | () => new CounterUpDown(8)) {c => new TestCounterUpDown(c)} 19 | } 20 | -------------------------------------------------------------------------------- /Example_code/Lab10/foldOrder.scala: -------------------------------------------------------------------------------- 1 | // Illustration of the order of fold method 2 | val uList = List(1, 2, 3, 4, 5) 3 | 4 | val uSum_fold = uList.fold(0)(_ - _) 5 | println(s"Elements difference using fold method = $uSum_fold") 6 | 7 | val uSum_foldLeft = uList.foldLeft(0)(_ - _) 8 | println(s"Elements difference using foldLeft method = $uSum_foldLeft") 9 | 10 | val uSum_foldRight = uList.foldRight(0)(_ - _) 11 | println(s"Elements difference using foldRight method = $uSum_foldRight") 12 | 13 | // The output at the terminal 14 | Elements difference using fold method = -15 15 | Elements difference using foldLeft method = -15 16 | Elements difference using foldRight method = 3 -------------------------------------------------------------------------------- /Example_code/Lab10/zip.scala: -------------------------------------------------------------------------------- 1 | val uList1: List[(Char)] = List('a', 'b', 'c', 'd', 'e') 2 | val uList2: List[(Int)] = List(20, 40, 100) 3 | 4 | val uList_Zipped = uList1.zip(uList2) 5 | println(s"The zipped list is: $uList_Zipped") 6 | 7 | val uList_unZipped = uList_Zipped.unzip 8 | println(s"The unzipped list is: $uList_unZipped") 9 | 10 | val uList_indexZip = uList1.zipWithIndex 11 | println(s"The list zipped with its index: $uList_indexZip") 12 | 13 | // The output at the terminal 14 | The zipped list is: List((a,20), (b,40), (c,100)) 15 | The unzipped list is: (List(a, b, c),List(20, 40, 100)) 16 | The list zipped with its index: List((a,0), (b,1), (c,2), (d,3), (e,4)) -------------------------------------------------------------------------------- /Example_code/Lab14/scaling.scala: -------------------------------------------------------------------------------- 1 | class LinearMap { 2 | def multiplyOffset(x: Int) (implicit weight: Int, offset: Float) = 3 | (weight * x).toFloat + offset 4 | } 5 | 6 | // initial value assignment 7 | implicit val weightage = 3 8 | implicit val offset = 4.0F 9 | val x = 5 10 | 11 | val scale = new LinearMap 12 | println("The result with Implicit parameters omitted: " + scale.multiplyOffset(x)) 13 | println("The result with Implicit parameters passed explicitly: " + scale.multiplyOffset(x)(weightage, offset)) 14 | 15 | // output at the terminal is 16 | The result with Implicit parameters omitted: 19.0 17 | The result with Implicit parameters passed explicitly: 19.0 -------------------------------------------------------------------------------- /Example_code/Lab3/Encoder_whenelse_statement.scala: -------------------------------------------------------------------------------- 1 | // Encoder using when-else-statement 2 | import chisel3._ 3 | 4 | class LM_IO_Interface extends Bundle { 5 | val in = Input(UInt(4.W)) 6 | val out = Output(UInt(2.W)) 7 | } 8 | 9 | class Encoder_4to2 extends Module { 10 | val io = IO(new LM_IO_Interface) 11 | 12 | when (io.in === "b0001".U) { 13 | io.out := "b00".U 14 | } .elsewhen(io.in === "b0010".U) { 15 | io.out := "b01".U 16 | } .elsewhen(io.in === "b0100".U) { 17 | io.out := "b10".U 18 | } .otherwise { 19 | io.out := "b11".U 20 | } 21 | } 22 | 23 | println((new chisel3.stage.ChiselStage).emitVerilog(new Encoder_4to2())) 24 | -------------------------------------------------------------------------------- /Example_code/Lab6/shift_reg_with_parallel_load.scala: -------------------------------------------------------------------------------- 1 | // Shift register with parallel load 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class shift_reg_with_parallel_load(val len : Int=1) extends Module { 6 | val io = IO(new Bundle{ 7 | val out = Vec(len, Output(Bool())) 8 | val load_in = Vec(len, Input(Bool())) 9 | val in = Input(Bool()) 10 | val load = Input(Bool()) 11 | }) 12 | io.out(0) := RegNext(0.U, Mux(io.load, io.load_in(0), io.in)) 13 | for(i<- 1 until len){ 14 | io.out(i) := RegNext(0.U, Mux(io.load, io.load_in(0), io.out(i-1))) 15 | } 16 | } 17 | 18 | println((new chisel3.stage.ChiselStage).emitVerilog(new shift_reg_with_parallel_load(4))) 19 | -------------------------------------------------------------------------------- /Example_code/Lab1/datatypes.scala: -------------------------------------------------------------------------------- 1 | // signal definitions 2 | val s1 = WireInit(true.B) // Bool, initialized 3 | val s2 = Wire(Bool()) // Bool, uninitialized 4 | 5 | val x1 = WireInit(-45.S(8.W)) // SInt, initialized 8-bit 6 | val x2 = WireInit(-45.S) // SInt, initialized width inferred 7 | val x3 = Wire(SInt()) // SInt, uninitialized width inferred 8 | 9 | val y1 = WireInit(102.U(8.W)) // UInt, initialized 8-bit 10 | val y2 = WireInit(102.U) // UInt, initialized width inferred 11 | val y3 = Wire(UInt()) // UInt, uninitialized width inferred 12 | 13 | val z1 = Wire(Bits()) // Bits, uninitialized width inferred 14 | val z2 = Wire(Bits(16.W)) // Bits, uninitialized 16-bit -------------------------------------------------------------------------------- /Example_code/Lab11/pattern_match.scala: -------------------------------------------------------------------------------- 1 | case class uModule(name: String, bitWidth: Int) 2 | 3 | // pattern matching using unapply method of case class 4 | def matchObject(obj: uModule) = { 5 | val result = obj match { 6 | case uModule(name, 32) => println("Module name is: " + name) 7 | case uModule(name, 16) => println("Module name is: " + name) 8 | case _ => println(None) 9 | } 10 | } 11 | // instantiate different modules 12 | val objA = uModule("ALU", 32) 13 | val objI = uModule("Imm", 32) 14 | val objB = uModule("Branch", 16) 15 | val objM = uModule("Mul", 64) 16 | 17 | matchObject(objI) 18 | 19 | // output at the terminal 20 | Module name is: Imm -------------------------------------------------------------------------------- /Example_code/Lab10/reduceOrder.scala: -------------------------------------------------------------------------------- 1 | // Illustration of the order of reduce method 2 | val uList = List(1, 2, 3, 4, 5) 3 | 4 | val uSum: Double = uList.reduce(_ - _) 5 | println(s"Difference of elements using reduce function = $uSum") 6 | 7 | val uSum_Explicit = uList.reduceLeft(_ - _) 8 | println(s"Difference of elements using reduceLeft = $uSum_Explicit") 9 | 10 | val uSum_Explicit1 = uList.reduceRight(_ - _) 11 | println(s"Difference of elements using reduceRight = $uSum_Explicit1") 12 | 13 | // The output at the terminal 14 | Difference of elements using reduce function = -13.0 15 | Difference of elements using reduceLeft function = -13 16 | Difference of elements using reduceRight function = 3 -------------------------------------------------------------------------------- /Example_code/Lab7/edge_detectMoore.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | 4 | class Edge_FSM extends Module { 5 | val io = IO(new Bundle{ 6 | val sin = Input(Bool()) 7 | val edge = Output(Bool()) 8 | }) 9 | 10 | val zero :: one :: Nil = Enum(2) // The two states 11 | val state = RegInit(zero) // The state register 12 | io.edge := false.B // default value for output 13 | 14 | // Next state and output logic 15 | switch (state) { 16 | 17 | is(zero) { 18 | when(io.sin) { 19 | state := one 20 | } 21 | } 22 | 23 | is(one) { 24 | when(!io.sin) { 25 | state := zero 26 | io.edge := true.B 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Example_code/Lab8/masking.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | class MaskedReadWriteSmem extends Module { 3 | val width: Int = 8 4 | val io = IO(new Bundle { 5 | val enable = Input(Bool()) 6 | val write = Input(Bool()) 7 | val addr = Input(UInt(10.W)) 8 | val mask = Input(Vec(4, Bool())) 9 | val dataIn = Input(Vec(4, UInt(width.W))) 10 | val dataOut = Output(Vec(4, UInt(width.W))) 11 | }) 12 | 13 | // Create a 32-bit wide memory that is byte-masked 14 | val mem = SyncReadMem(1024, Vec(4, UInt(width.W))) 15 | // Write with mask 16 | mem.write(io.addr, io.dataIn, io.mask) 17 | io.dataOut := mem.read(io.addr, io.enable) 18 | } 19 | 20 | println(chisel3.Driver.emitVerilog(new MaskedReadWriteSmem)) 21 | -------------------------------------------------------------------------------- /Example_code/Lab3/alu_MuxLookUp.scala: -------------------------------------------------------------------------------- 1 | class Alu_Lookup extends Module with Config { 2 | val io = IO(new AluIO) 3 | 4 | val shamt = io.in_B(4,0).asUInt 5 | 6 | io.out := MuxLookup(io.alu_Op, io.in_B, Seq( 7 | ALU_ADD -> (io.in_A + io.in_B), 8 | ALU_SUB -> (io.in_A - io.in_B), 9 | ALU_SRA -> (io.in_A .asSInt >> shamt).asUInt, 10 | ALU_SRL -> (io.in_A >> shamt), 11 | ALU_SLL -> (io.in_A << shamt), 12 | ALU_SLT -> (io.in_A .asSInt < io.in_B.asSInt), 13 | ALU_SLTU -> (io.in_A < io.in_B), 14 | ALU_AND -> (io.in_A & io.in_B), 15 | ALU_OR -> (io.in_A | io.in_B), 16 | ALU_XOR -> (io.in_A ^ io.in_B), 17 | ALU_COPY_A -> io.in_A )) 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Example_code/Lab9/control_signals.scala: -------------------------------------------------------------------------------- 1 | class ControlSignals extends Bundle with Config { 2 | val inst = Input(UInt(XLEN.W)) 3 | val pc_sel = Output(UInt(2.W)) 4 | val inst_kill = Output(Bool()) 5 | val A_sel = Output(UInt(1.W)) 6 | val B_sel = Output(UInt(1.W)) 7 | val imm_sel = Output(UInt(3.W)) 8 | val alu_op = Output(UInt(5.W)) 9 | val br_type = Output(UInt(3.W)) 10 | val st_type = Output(UInt(2.W)) 11 | val ld_type = Output(UInt(3.W)) 12 | val wb_sel = Output(UInt(2.W)) 13 | val wb_en = Output(Bool()) 14 | val csr_cmd = Output(UInt(3.W)) 15 | val illegal = Output(Bool()) 16 | val en_rs1 = Output(Bool()) 17 | val en_rs2 = Output(Bool()) 18 | } -------------------------------------------------------------------------------- /Example_code/Lab10/function.scala: -------------------------------------------------------------------------------- 1 | // User type definition 2 | type R = Int 3 | 4 | // An example List 5 | val uList = List(1, 2, 3, 4, 5) 6 | 7 | // functional composition 8 | def compose(g: R => R, h: R => R) = 9 | (x: R) => g(h(x)) 10 | 11 | // implement y = mx+c ( with m=2 and c =1) 12 | def y1 = compose(x => x + 1, x => x * 2) 13 | def y2 = compose(_ + 1, _ * 2) 14 | 15 | val uList_map1 = uList.map(x => y1(x)) 16 | val uList_map2 = uList.map(y2(_)) 17 | 18 | println(s" Linearly mapped list 1 = $uList_map1 ") 19 | println(s" Linearly mapped list 2 = $uList_map2 ") 20 | 21 | // The output at the terminal 22 | Linearly mapped list 1 = List (3, 5, 7, 9, 11) 23 | Linearly mapped list 2 = List (3, 5, 7, 9, 11) 24 | -------------------------------------------------------------------------------- /Example_code/Lab4/aluTest_body2.scala: -------------------------------------------------------------------------------- 1 | // process the ALU result for -ve values 2 | val result1: BigInt = if (result < 0) 3 | (BigInt(0xFFFFFFFF)+result+1) & 0xFFFFFFFFL 4 | else result & 0xFFFFFFFFL 5 | 6 | poke(c.io.in_A, src_a.U) 7 | poke(c.io.in_B, src_b.U) 8 | poke(c.io.alu_Op, aluop) 9 | step(1) 10 | expect(c.io.out, result1.asUInt) 11 | } 12 | step(1) 13 | step(1) 14 | } 15 | 16 | // object for tester class 17 | object ALU_Main extends App { 18 | iotesters.Driver.execute(Array("--is-verbose", "--generate-vcd-output", 19 | "on", "--backend-name", "firrtl"), () => new ALU) { 20 | c => new TestALU(c) 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /Example_code/Lab5/counter.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.stage.ChiselStage 3 | 4 | class Counter(size: Int, maxValue: UInt) extends Module { 5 | val io = IO(new Bundle { 6 | val result = Output(Bool()) 7 | }) 8 | 9 | // 'genCounter' with counter size 'n' 10 | def genCounter(n: Int, max: UInt) = { 11 | val count = RegInit(0.U(n.W)) 12 | 13 | when(count === max) { 14 | count := 0.U 15 | }.otherwise { count := count + 1.U } 16 | count 17 | } 18 | 19 | // genCounter instantiation 20 | val counter1 = genCounter(size, maxValue) 21 | val counter2 = genCounter(size + size, maxValue) 22 | io.result := counter1(size-1) & counter2(0) 23 | } 24 | 25 | println((new ChiselStage).emitVerilog(new Counter(8, 255.U))) -------------------------------------------------------------------------------- /Example_code/Lab13/traitOutput.scala: -------------------------------------------------------------------------------- 1 | // Derived class extending base class and mixins with traits 2 | class DerivedClass extends BaseClass with Trait2 with Trait3{ 3 | override def print(){ println("Derived Class") 4 | super.print 5 | } 6 | } 7 | 8 | // The output at the terminal 9 | Derived Class 10 | Trait 3 11 | Trait 1 12 | Trait 2 13 | Base Class 14 | 15 | // Derived class extending base class and mixins with traits 16 | class DerivedClass extends BaseClass with Trait3 with Trait2{ 17 | override def print(){ 18 | println("Derived Class") 19 | super.print 20 | } 21 | } 22 | 23 | // The output at the terminal 24 | Derived Class 25 | Trait 2 26 | Trait 3 27 | Trait 1 28 | Base Class -------------------------------------------------------------------------------- /Example_code/Lab5/classAsParam.scala: -------------------------------------------------------------------------------- 1 | import chisel3.util._ 2 | 3 | class Parameters extends Bundle{ 4 | val addrWidth = UInt(32.W) 5 | val dataWidth = UInt(32.W) 6 | } 7 | 8 | 9 | class adder(params: Parameters) extends Module{ 10 | val io = IO(new Bundle{ 11 | val in1 = Input(params.addrWidth) 12 | val in2 = Input(UInt(32.W)) 13 | val out1 = Output(UInt(32.W)) 14 | val out2 = Output(UInt(32.W)) 15 | val sel = Input(Bool()) 16 | }) 17 | 18 | when(io.sel){ 19 | io.out1 := io.in2 20 | io.out2 := io.in1} 21 | .otherwise{ 22 | io.out1 := io.in1 23 | io.out2 := io.in2 24 | } 25 | } 26 | 27 | val params = (new Parameters) 28 | println(chisel3.Driver.emitVerilog(new adder(params))) -------------------------------------------------------------------------------- /Example_code/Lab6/counter.scala: -------------------------------------------------------------------------------- 1 | // Optimized counter example 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class counter(val max: Int, val min: Int = 0) extends Module { 6 | val io = IO(new Bundle{ 7 | val out = Output(UInt(log2Ceil(max).W)) 8 | }) 9 | val counter = RegInit(min.U(log2Ceil(max).W)) 10 | 11 | // If the max count is of power 2 and the min value = 0, 12 | // then we can skip the comparator and the Mux 13 | val count_buffer = if (isPow2(max) && (min == 0)) counter + 1.U 14 | else Mux(counter === max.U, min.U, counter + 1.U) 15 | counter := count_buffer 16 | io.out := counter 17 | } 18 | println((new chisel3.stage.ChiselStage).emitVerilog(new counter(32))) 19 | 20 | -------------------------------------------------------------------------------- /Example_code/Lab8/regFile.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | 3 | class RegFileIO extends Bundle with Config { 4 | val raddr1 = Input(UInt(5.W)) 5 | val raddr2 = Input(UInt(5.W)) 6 | val rdata1 = Output(UInt(XLEN.W)) 7 | val rdata2 = Output(UInt(XLEN.W)) 8 | val wen = Input(Bool()) 9 | val waddr = Input(UInt(5.W)) 10 | val wdata = Input(UInt(XLEN.W)) 11 | } 12 | 13 | class RegFile extends Module with Config { 14 | val io = IO(new RegFileIO) 15 | val regs = Mem(REGFILE_LEN, UInt(XLEN.W)) 16 | 17 | io.rdata1 := Mux((io.raddr1.orR), regs(io.raddr1), 0.U) 18 | io.rdata2 := Mux((io.raddr2.orR), regs(io.raddr2), 0.U) 19 | 20 | when(io.wen & io.waddr.orR) { 21 | regs(io.waddr) := io.wdata 22 | } 23 | } -------------------------------------------------------------------------------- /Example_code/Lab6/regFile.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | 3 | class RegFileIO extends Bundle with Config { 4 | val raddr1 = Input(UInt(5.W)) 5 | val raddr2 = Input(UInt(5.W)) 6 | val rdata1 = Output(UInt(XLEN.W)) 7 | val rdata2 = Output(UInt(XLEN.W)) 8 | val wen = Input(Bool()) 9 | val waddr = Input(UInt(5.W)) 10 | val wdata = Input(UInt(XLEN.W)) 11 | } 12 | 13 | class RegFile extends Module with Config { 14 | val io = IO(new RegFileIO) 15 | val regs = Reg(Vec(REGFILE_LEN, UInt(XLEN.W))) 16 | 17 | io.rdata1 := Mux((io.raddr1.orR), regs(io.raddr1), 0.U) 18 | io.rdata2 := Mux((io.raddr2.orR), regs(io.raddr2), 0.U) 19 | 20 | when(io.wen & io.waddr.orR) { 21 | regs(io.waddr) := io.wdata 22 | } 23 | } -------------------------------------------------------------------------------- /Example_code/Lab7/Queue_Double.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | import chisel3.iotesters.{ChiselFlatSpec,Driver,PeekPokeTester} 4 | 5 | class My_Queue extends Module{ 6 | val io = IO(new Bundle { 7 | val in = Flipped(Decoupled(UInt(8.W))) //valid = Input, ready = Output, bits = Input 8 | val out = Decoupled(UInt(8.W)) //valid = Output, ready = Input , bits = Output 9 | }) 10 | val queue = Queue(io.in, 5) // 5-element queue 11 | val w1 = Wire(Flipped(Decoupled(UInt(8.W)))) //valid = Input, ready = Output, bits = Input 12 | w1 <> queue 13 | val queue1 = Queue(w1, 5) // 5-element queue 14 | io.out <> queue1 15 | } 16 | -------------------------------------------------------------------------------- /Example_code/Lab3/Branch_Control_skeleton.scala: -------------------------------------------------------------------------------- 1 | // Branch control (Assignment) 2 | package lab3 3 | import chisel3._ 4 | import chisel3.util._ 5 | 6 | class LM_IO_Interface_BranchControl extends Bundle { 7 | val fnct3 = Input(UInt(3.W)) 8 | val branch = Input(Bool()) 9 | val arg_x = Input(UInt(32.W)) 10 | val arg_y = Input(UInt(32.W)) 11 | val br_taken = Output(Bool()) 12 | } 13 | 14 | class BranchControl extends Module { 15 | val io = IO(new LM_IO_Interface_BranchControl) 16 | // Start Coding here 17 | 18 | 19 | // End your code here 20 | // Well, you can actually write classes too. So, technically you have no limit ;) 21 | } 22 | 23 | println((new chisel3.stage.ChiselStage).emitVerilog(new Branch_Control)) 24 | 25 | -------------------------------------------------------------------------------- /Example_code/Lab1/object_typecast.scala: -------------------------------------------------------------------------------- 1 | class Parent { 2 | val countP = 10 3 | def display(): Unit = { 4 | println("Parent counter : " + countP); 5 | } 6 | } 7 | class Child extends Parent { 8 | val countC = 12 9 | def displayC(): Unit = { 10 | println("Child counter : " + countC); 11 | } 12 | } 13 | 14 | object Top { 15 | def main(args: Array[String]): Unit = 16 | { 17 | var pObject = new Parent() // parent object 18 | var cObject = new Child() // child object 19 | var castedObject = cObject.asInstanceOf[Parent] // object cast 20 | pObject.display() 21 | cObject.display() 22 | cObject.displayC() 23 | castedObject.display() 24 | } 25 | } -------------------------------------------------------------------------------- /Example_code/Lab4/MuxTreeTest1.scala: -------------------------------------------------------------------------------- 1 | package LM_Chisel 2 | import chisel3._ 3 | import chisel3.iotesters.{Driver, PeekPokeTester} 4 | 5 | class TestMuxT(c: MuxTree) extends PeekPokeTester(c) { 6 | val in1 = 0x11111111 7 | val in2 = 0x22222222 8 | val in3 = 0x33333333 9 | 10 | poke(c.io.in_1, in1.U) 11 | poke(c.io.in_2, in2.U) 12 | poke(c.io.in_3, in3.U) 13 | 14 | poke(c.io.sel_1, false.B) 15 | poke(c.io.sel_2, false.B) 16 | expect(c.io.out, in1.U) 17 | step(1) 18 | 19 | poke(c.io.sel_1, true.B) 20 | poke(c.io.sel_2, false.B) 21 | expect(c.io.out, in2.U) 22 | step(1) 23 | 24 | poke(c.io.sel_1, true.B) 25 | poke(c.io.sel_2, true.B) 26 | expect(c.io.out, in3.U) 27 | step(3) 28 | } -------------------------------------------------------------------------------- /Example_code/Lab9/lists2.scala: -------------------------------------------------------------------------------- 1 | // List of Strings 2 | val modules: List[String] = List("ALU", "Branch", "Control") 3 | val peripherals = List("Uart", "Timer") 4 | 5 | // List of Integers 6 | val nums: List[Int] = List(1, 2, 3, 3, 4) 7 | 8 | // split the list apart 9 | val List(b, c, d) = modules 10 | val a :: rest = modules 11 | 12 | // concatenate two lists (using ::: or List.:::() or List.concat() ) 13 | val combined_list = modules ::: peripherals 14 | println(rest) // List(Branch, Control) 15 | println(nums) // List(1, 2, 3, 3, 4) 16 | println(combined_list) // List(ALU, Branch, Control, Uart, Timer) 17 | 18 | // combine two lists of different types 19 | println(modules:::nums)// List(ALU, Branch, Control, 1, 2, 3, 3, 4) 20 | 21 | -------------------------------------------------------------------------------- /Example_code/Lab5/operatorComplete.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | 3 | // class definition with function as parameter 4 | class Operator[T <: Data](n: Int, generic: T)(op: (T, T) => T) extends Module { 5 | require(n > 0) // "reduce only works on non-empty Vecs" 6 | 7 | val io = IO(new Bundle { 8 | val in = Input(Vec(n, generic)) 9 | val out = Output(generic) 10 | }) 11 | 12 | io.out := io.in.reduce(op) 13 | } 14 | 15 | // Implement addition operation 16 | object UserOperator1 extends App { 17 | println((new chisel3.stage.ChiselStage).emitVerilog(new Operator(2, UInt(16.W))(_ + _))) 18 | } 19 | 20 | // Implement AND operation 21 | object UserOperator2 extends App { 22 | println((new chisel3.stage.ChiselStage).emitVerilog(new Operator(3, UInt(8.W))(_ & _))) 23 | } -------------------------------------------------------------------------------- /Example_code/Lab10/rocket_rf.scala: -------------------------------------------------------------------------------- 1 | class RegFile(n: Int, w: Int, zero: Boolean = false) { 2 | val rf = Mem(n, UInt(width = w)) 3 | private def access(addr: UInt) = rf(~addr(log2Up(n)-1,0)) 4 | private val reads = ArrayBuffer[(UInt,UInt)]() 5 | private var canRead = true 6 | 7 | def read(addr: UInt) = { 8 | require(canRead) 9 | reads += addr -> Wire(UInt()) 10 | reads.last._2 := Mux(Bool(zero) && addr === UInt(0), UInt(0), access(addr)) 11 | reads.last._2 12 | } 13 | def write(addr: UInt, data: UInt) = { 14 | canRead = false 15 | when (addr =/= UInt(0)) { 16 | access(addr) := data 17 | for ((raddr, rdata) <- reads) 18 | when (addr === raddr) { rdata := data } // check for forwarding 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Example_code/Lab12/make.bat: -------------------------------------------------------------------------------- 1 | 2 | riscv64-unknown-elf-gcc -c -o build/main.o src/main.c -march=rv32i -mabi=ilp32 3 | 4 | riscv64-unknown-elf-as -c -o build/startup.o src/startup.s -march=rv32i -mabi=ilp32 5 | 6 | riscv64-unknown-elf-as -c -o build/isr.o src/isr.s -march=rv32i -mabi=ilp32 7 | 8 | riscv64-unknown-elf-gcc -o build/program.elf build/startup.o build/isr.o build/main.o -T linker.ld -nostdlib -march=rv32i -mabi=ilp32 9 | 10 | riscv64-unknown-elf-objcopy -O binary --only-section=.data* --only-section=.text* build/program.elf build/main.bin 11 | 12 | hexdump build/main.bin > build/main.hex 13 | 14 | python maketxt.py build/main.bin > build/main.txt 15 | 16 | riscv64-unknown-elf-objdump -S -s build/program.elf > build/program.dump 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Example_code/Lab2/muxCase_slides.scala: -------------------------------------------------------------------------------- 1 | // 4 to 1 mux using MuxCase 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class MuxCase_Example extends Module { 6 | val io = IO(new Bundle{ 7 | val in0 = Input(Bool()) 8 | val in1 = Input(Bool()) 9 | val in2 = Input(Bool()) 10 | val in3 = Input(Bool()) 11 | val sel = Input(UInt(2.W)) 12 | val out = Output(Bool()) 13 | }) 14 | 15 | io.out := MuxCase(false.B, Array( 16 | (io.sel === 0.U) -> io.in0, 17 | (io.sel === 1.U) -> io.in1, 18 | (io.sel === 2.U) -> io.in2, 19 | (io.sel === 3.U) -> io.in3 20 | ) 21 | ) 22 | } 23 | 24 | println((new chisel3.stage.ChiselStage).emitVerilog(new MuxCase_Example ())) -------------------------------------------------------------------------------- /Example_code/Lab8/texput.log: -------------------------------------------------------------------------------- 1 | This is pdfTeX, Version 3.1415926-2.4-1.40.13 (MiKTeX 2.9) (preloaded format=pdflatex 2020.6.19) 9 JUL 2020 12:42 2 | entering extended mode 3 | **mem.tex 4 | 5 | ! Emergency stop. 6 | <*> mem.tex 7 | 8 | *** (job aborted, file error in nonstop mode) 9 | 10 | 11 | Here is how much of TeX's memory you used: 12 | 2 strings out of 493921 13 | 13 string characters out of 3144873 14 | 49031 words of memory out of 3000000 15 | 3400 multiletter control sequences out of 15000+200000 16 | 3640 words of font info for 14 fonts, out of 3000000 for 9000 17 | 841 hyphenation exceptions out of 8191 18 | 0i,0n,0p,1b,6s stack positions out of 5000i,500n,10000p,200000b,50000s 19 | ! ==> Fatal error occurred, no output PDF file produced! 20 | -------------------------------------------------------------------------------- /Example_code/Lab8/parameterized_mem.scala: -------------------------------------------------------------------------------- 1 | // parameterized memory 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class Parameterized_Mem(val size: Int = 32, val width: Int = 32) extends Module { 6 | val io = IO(new Bundle { 7 | val dataIn = Input(UInt(width.W)) 8 | val dataOut = Output(UInt(width.W)) 9 | val addr = Input(UInt(log2Ceil(size).W)) 10 | val rd_enable = Input(Bool()) 11 | val wr_enable = Input(Bool()) 12 | }) 13 | 14 | val Sync_memory = SyncReadMem(size, UInt(width.W)) 15 | // memory write operation 16 | when(io.wr_enable){ 17 | Sync_memory.write(io.addr, io.dataIn) 18 | } 19 | io.dataOut := Sync_memory.read(io.addr, io.rd_enable) 20 | } 21 | println((new chisel3.stage.ChiselStage).emitVerilog(new Parameterized_Mem)) 22 | -------------------------------------------------------------------------------- /Example_code/Lab16/Client_param.scala: -------------------------------------------------------------------------------- 1 | case class TLClientParameters( 2 | name: String, 3 | sourceId: IdRange = IdRange(0,1), 4 | nodePath: Seq[BaseNode] = Seq(), 5 | requestFifo: Boolean = false, 6 | visibility: Seq[AddressSet] = Seq(AddressSet(0, ~0)), // everything 7 | supportsProbe: TransferSizes = TransferSizes.none, 8 | supportsArithmetic: TransferSizes = TransferSizes.none, 9 | supportsLogical: TransferSizes = TransferSizes.none, 10 | supportsGet: TransferSizes = TransferSizes.none, 11 | supportsPutFull: TransferSizes = TransferSizes.none, 12 | supportsPutPartial: TransferSizes = TransferSizes.none, 13 | supportsHint: TransferSizes = TransferSizes.none){...} 14 | -------------------------------------------------------------------------------- /Example_code/Lab13/trait.scala: -------------------------------------------------------------------------------- 1 | class BaseClass{ 2 | def print{ println("Base Class") } 3 | } 4 | 5 | trait Trait1 extends BaseClass{ 6 | override def print(){ println("Trait 1") 7 | super.print 8 | } 9 | } 10 | 11 | trait Trait2 extends BaseClass{ 12 | override def print(){ println("Trait 2") 13 | super.print 14 | } 15 | } 16 | 17 | trait Trait3 extends Trait1{ 18 | override def print(){ println("Trait 3") 19 | super.print 20 | } 21 | } 22 | 23 | // Derived class extending base class and mixins with traits 24 | class DerivedClass extends BaseClass with Trait2 with Trait3{ 25 | override def print(){ println("Derived Class") 26 | super.print 27 | } 28 | } 29 | 30 | val printFun = new DerivedClass 31 | printFun.print -------------------------------------------------------------------------------- /Example_code/Lab8/dataMemMask.scala: -------------------------------------------------------------------------------- 1 | package LM_Chisel 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | 6 | class DataMemIO extends Bundle with Config { 7 | val addr = Input(UInt(WLEN.W)) 8 | val wdata = Input(UInt(WLEN.W)) 9 | val rd_en = Input(Bool()) 10 | val wr_en = Input(Bool()) 11 | val mask = Input(Vec(4, Bool())) 12 | val rdata = Output(UInt(WLEN.W)) 13 | } 14 | 15 | class DataMem extends Module with Config { 16 | val io = IO(new DataMemIO) 17 | 18 | // Data memory size and addressability width 19 | val dmem = SyncReadMem(DATA_MEM_LEN, UInt(BLEN.W)) 20 | // Write with mask 21 | when (io.wr_en.toBool()) { 22 | dmem.write(io.addr, io.wdata, io.mask) 23 | } 24 | io.rdata := dmem.read(io.addr, rd_en) 25 | } -------------------------------------------------------------------------------- /Example_code/Lab9/CSR_Seq.scala: -------------------------------------------------------------------------------- 1 | // CSR register file 2 | val csrFile = Seq( 3 | BitPat(CSR.CYCLE) -> cycle, 4 | BitPat(CSR.TIME) -> time, 5 | BitPat(CSR.INSTRET) -> instret, 6 | BitPat(CSR.CYCLEH) -> cycleh, 7 | BitPat(CSR.TIMEH) -> timeh, 8 | BitPat(CSR.INSTRETH) -> instreth, 9 | BitPat(CSR.MTVEC) -> mtvec, 10 | BitPat(CSR.MIE) -> mie.asUInt, 11 | BitPat(CSR.MSCRATCH) -> mscratch, 12 | BitPat(CSR.MEPC) -> mepc, 13 | BitPat(CSR.MCAUSE) -> mcause, 14 | BitPat(CSR.MTVAL) -> mtval, 15 | BitPat(CSR.MIP) -> mip.asUInt, 16 | BitPat(CSR.MSTATUS) -> mstatus.asUInt, 17 | BitPat(CSR.MISA) -> misa 18 | ) 19 | 20 | // reading CSR, 21 | io.out := Lookup(csr_addr, 0.U, csrFile).asUInt -------------------------------------------------------------------------------- /Example_code/Examples/rocket_core.scala: -------------------------------------------------------------------------------- 1 | // Exception checking in rocket core 2 | def checkExceptions(x: Seq[(Bool, UInt)]) = 3 | (x.map(_._1).reduce(_||_), PriorityMux(x)) 4 | 5 | 6 | // Hazard checking in rocket core 7 | def checkHazards(targets: Seq[(Bool, UInt)], cond: UInt => Bool) = 8 | targets.map(h => h._1 && cond(h._2)).reduce(_||_) 9 | 10 | // Bypass source ID 11 | val bypass_sources = IndexedSeq( 12 | (Bool(true), UInt(0), UInt(0)), // treat reading x0 as a bypass 13 | (ex_reg_valid && ex_ctrl.wxd, ex_waddr, mem_reg_wdata), 14 | (mem_reg_valid && mem_ctrl.wxd && !mem_ctrl.mem, mem_waddr, wb_reg_wdata), 15 | (mem_reg_valid && mem_ctrl.wxd, mem_waddr, dcache_bypass_data)) 16 | val id_bypass_src = id_raddr.map(raddr => bypass_sources.map(s => s._1 && s._2 === raddr)) 17 | -------------------------------------------------------------------------------- /Example_code/Lab7/Assignment2_skeleton.scala: -------------------------------------------------------------------------------- 1 | package Lab7 2 | import chisel3._ 3 | import chisel3.util._ 4 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester} 5 | import chisel3.experimental.ChiselEnum 6 | import chisel3.experimental.{withClock, withReset, withClockAndReset} 7 | import chisel3.experimental.BundleLiterals._ 8 | 9 | //optional, you can use compaion object 10 | object Manchester_Encoding{ //optional 11 | //your code 12 | } 13 | 14 | class Manchester_Encoding extends Module { 15 | import Manchester_Encoding.State 16 | import Manchester_Encoding.State._ 17 | val io = IO(new Bundle { 18 | val in = Input(UInt(1.W)) 19 | val start = Input(Bool()) 20 | val out = Output(UInt(8.W)) 21 | val flag = Output(UInt(1.W)) 22 | }) 23 | //your code here 24 | } 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example_code/Lab8/forwarding.scala: -------------------------------------------------------------------------------- 1 | // Memory forwarding example 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class Forwarding extends Module { 6 | val io = IO(new Bundle{ 7 | val out = Output(UInt(32.W)) 8 | val rdAddr = Input(UInt(10.W)) 9 | val wrAddr = Input(UInt(10.W)) 10 | val wrData = Input(UInt(32.W)) 11 | val wr_en = Input(Bool()) 12 | }) 13 | 14 | val memory = SyncReadMem(1024, UInt(32.W)) 15 | val wrDataReg = RegNext(io.wrData) 16 | val doForwardReg = RegNext(io.wrAddr === io.rdAddr && io.wr_en) 17 | val memData = memory.read(io.rdAddr) 18 | when(io.wr_en) 19 | {memory.write(io.wrAddr, io.wrData)} 20 | io.out := Mux(doForwardReg , wrDataReg , memData) 21 | } 22 | 23 | println((new chisel3.stage.ChiselStage).emitVerilog(new Forwarding())) 24 | -------------------------------------------------------------------------------- /Example_code/Lab15/xbar.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | 3 | class AHBXbar(nMasters: Int, nSlaves: Int) extends Module { 4 | val io = IO(new Bundle { 5 | val masters = Flipped(Vec(new AHBMasterIO, nMasters)) 6 | val slaves = Flipped(Vec(new AHBSlaveIO, nSlaves)) 7 | }) 8 | 9 | val buses = List.fill(nMasters) { Module(new AHBBus(nSlaves)) } 10 | val muxes = List.fill(nSlaves) { Module(new AHBSlaveMux(nMasters)) } 11 | 12 | // master and slave external IO connections 13 | (buses.map(b => b.io.master) zip io.masters) foreach { case (b, m) => b <> m } 14 | (muxes.map(m => m.io.out) zip io.slaves) foreach { case (x, s) => x <> s } 15 | 16 | // internal wiring of the Xbar 17 | for (m <- 0 until nMasters; s <- 0 until nSlaves) yield { 18 | buses(m).io.slaves(s) <> muxes(s).io.ins(m) 19 | } 20 | } -------------------------------------------------------------------------------- /Example_code/Lab9/Set_example.scala: -------------------------------------------------------------------------------- 1 | // An example set of type integer 2 | val set1 : Set[Int] = Set(2,4,5) 3 | 4 | // A second example set of integer type 5 | val set2 : Set[Int] = Set(1,3,3,5,5,7) 6 | 7 | // Union of sets with ++ as operator 8 | var set_union1 = set1 ++ set2 9 | 10 | // Union of sets with ++ as method 11 | var set_union2 = set1.++(set2) 12 | 13 | // Intersection of sets with & as method 14 | var set_intersect1 = set1.&(set2) 15 | 16 | println(set1) // Set(2, 4, 5) 17 | println(set2) // Set(1, 3, 5, 7) 18 | println(set2.head) // 1 19 | println(set2.tail) // Set(3, 5, 7) 20 | println(set1.isEmpty) // false 21 | println(set_union1) // Set(5, 1, 2, 7, 3, 4) 22 | println(set_union2) // Set(5, 1, 2, 7, 3, 4) 23 | println(set_intersect1) // Set(5) -------------------------------------------------------------------------------- /Example_code/Lab1/classExample.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | 3 | class AdderWithOffset extends Module { 4 | val io = IO(new Bundle { 5 | val x = Input(SInt(16.W)) 6 | val y = Input(UInt(16.W)) 7 | val z = Output(UInt(16.W)) 8 | }) 9 | 10 | // Initialized as UInt and casted to SInt 11 | val y1 = (23.U).asSInt 12 | val in1 = io.x + y1 13 | io.z := in1.asUInt + io.y // Typecast SInt to UInt 14 | } 15 | 16 | println((new chisel3.stage.ChiselStage).emitVerilog(new AdderWithOffset)) 17 | 18 | // The generated Verilog code 19 | module AdderWithOffset( 20 | input clock, 21 | input reset, 22 | input [15:0] io_x, 23 | input [15:0] io_y, 24 | output [15:0] io_z 25 | ); 26 | wire [15:0] _T_2; 27 | assign _T_2 = $signed(io_x) - 16'sh9; 28 | assign io_z = _T_2 + io_y; 29 | endmodule 30 | -------------------------------------------------------------------------------- /Example_code/Lab11/mapMap.scala: -------------------------------------------------------------------------------- 1 | // An example Map using (key, value) pairs 2 | val uMap = Map('a' -> 2, 'b' -> 4, 'c' -> 6) 3 | 4 | // Applying .mapValues to Map 5 | val uMap_mapValues = uMap.mapValues(v => v*2) 6 | println(s"Map values doubled using .mapValues = $uMap_mapValues") 7 | 8 | def h(k:Int, v:Int) = Some(k->v*2) 9 | 10 | // Applying .map to Map 11 | val uMap_map = uMap.map { case (k,v) => h(k,v) } 12 | println(s"Map values doubled using .map = $uMap_map") 13 | 14 | // Applying .flatMap to Map 15 | val uMap_flatMap = uMap.flatMap { case (k,v) => h(k,v) } 16 | println(s"Map values doubled using .flatMap = $uMap_flatMap") 17 | 18 | // The output at the terminal 19 | Map values doubled using .mapValues = Map(a -> 4, b -> 8, c -> 12) 20 | Map values doubled using .map = List(Some((97,4)), Some((98,8)), Some((99,12))) 21 | Map values doubled using .flatMap = Map(97 -> 4, 98 -> 8, 99 -> 12) -------------------------------------------------------------------------------- /Example_code/Lab5/classAsParam1.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | 4 | class Parameters(dWidth: Int, aWidth: Int) extends Bundle{ 5 | val addrWidth = UInt(aWidth.W) 6 | val dataWidth = UInt(dWidth.W) 7 | } 8 | 9 | class DataMem (params: Parameters) extends Module { 10 | val io = IO(new Bundle{ 11 | val data_in = Input(params.dataWidth) 12 | val data_out = Output(params.dataWidth) 13 | val addr = Input(params.addrWidth) 14 | val wr_en = Input(Bool()) 15 | }) 16 | 17 | // Make memory of 32 x 32 18 | val memory = Mem(32, params.dataWidth) 19 | 20 | io.data_out := 0.U 21 | 22 | when(io.wr_en) { 23 | memory.write(io.addr, io.data_in) 24 | } .otherwise { 25 | io.data_out := memory.read(io.addr) 26 | } 27 | } 28 | 29 | val params = (new Parameters(32, 5)) 30 | println((new chisel3.stage.ChiselStage).emitVerilog(new DataMem(params))) -------------------------------------------------------------------------------- /Example_code/Lab10/apply.scala: -------------------------------------------------------------------------------- 1 | // Illustration of built-in apply functions for different types of collections 2 | val uList = List (11 , 22 , 33 , 44 , 55) 3 | val uSet = Set (11 , 22 , 33 , 44 , 55) 4 | val uMap = Map (1 -> 'a', 2 -> 'b', 3 -> 'c', 4 -> 'd') 5 | 6 | println (s" Apply method for the List with .apply = ${uList.apply (1)}") 7 | // Similarly we can call the apply method without the use of .apply 8 | println (s" Apply method for the List without .apply = ${uList(1)}") 9 | 10 | println (s" Apply method for the Set with .apply = ${uSet.apply(22)}") 11 | // Similarly we can call the apply method without the use of .apply 12 | println (s" Apply method for the Set without .apply = ${uSet(22)}") 13 | 14 | println (s" Apply method for Map with .apply = ${uMap.apply(2)}") 15 | // Similarly we can call the apply method without the use of .apply 16 | println (s" Apply method for Map without .apply = ${uMap(2)}") 17 | -------------------------------------------------------------------------------- /Example_code/Lab2/mux_Tree.scala: -------------------------------------------------------------------------------- 1 | // An 8-to-1 Mux example 2 | import chisel3._ 3 | 4 | class LM_IO_Interface extends Bundle { 5 | val in = Input(UInt(8.W)) 6 | val s0 = Input(Bool()) 7 | val s1 = Input(Bool()) 8 | val s2 = Input(Bool()) 9 | val out = Output(Bool()) // UInt(1.W)) 10 | } 11 | 12 | class Mux_8to1 extends Module { 13 | val io = IO(new LM_IO_Interface) 14 | 15 | val Mux4_to_1_a = Mux(io.s1, Mux(io.s0, io.in(3), io.in(2)), 16 | Mux(io.s0, io.in(1), io.in(0))) 17 | val Mux4_to_1_b = Mux(io.s1, Mux(io.s0, io.in(7), io.in(6)), 18 | Mux(io.s0, io.in(5), io.in(4))) 19 | 20 | val Mux2_to_1 = Mux(io.s2, Mux4_to_1_b, Mux4_to_1_a) 21 | 22 | // Connecting output of 2_to_1 Mux with the output port. 23 | io.out := Mux2_to_1 24 | } 25 | println((new chisel3.stage.ChiselStage).emitVerilog(new Mux_8to1())) 26 | -------------------------------------------------------------------------------- /Example_code/Lab14/implictFunction.scala: -------------------------------------------------------------------------------- 1 | import scala.language.implicitConversions 2 | 3 | class Implicit_Function (i : Int) { 4 | // Explicit conversion to Seq (List) and then increment 5 | val i_explicit_seq_inc = Seq(i).map { n => n + 1 6 | } 7 | 8 | val i_inc = i + 2 9 | 10 | // Implicit conversion to Seq (List) and then increment 11 | val i_implicit_seq_inc = i.map(_ + 3) 12 | 13 | // Implicit function for conversion 14 | implicit def any_name(i: Int): Seq[Int] = Seq(i) 15 | } 16 | 17 | val convert = new Implicit_Function(5) 18 | println("Explicit conversion and increment: " + convert.i_explicit_seq_inc) 19 | println("Simple increment: " +convert.i_inc) 20 | println("Implicit conversion and increment: " +convert.i_implicit_seq_inc) 21 | 22 | // The output at the terminal 23 | Explicit conversion and increment: List(6) 24 | Simple increment: 7 25 | Implicit conversion and increment: List(8) -------------------------------------------------------------------------------- /Example_code/Lab4/options.scala: -------------------------------------------------------------------------------- 1 | Selected Tester Options 2 | ----------------------- 3 | 4 | -tbn, --backend-name 5 | backend to use with tester, default is treadle 6 | 7 | -tiv, --is-verbose set verbose flag on PeekPokeTesters, default is false 8 | 9 | -twffn, --wave-form-file-name 10 | wave form file name 11 | 12 | -tts, --test-seed 13 | provides a seed for random number generator 14 | 15 | -tgvo, --generate-vcd-output 16 | set this flag to "on" or "off", otherwise it defaults to on 17 | for verilator, off for scala backends 18 | 19 | -td , --target-dir 20 | defines a work directory for intermediate files, default is 21 | current directory -------------------------------------------------------------------------------- /Example_code/Lab2/mux_Lookup.scala: -------------------------------------------------------------------------------- 1 | // 8 to 1 mux using MuxLookup 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class MuxLookup extends Module { 6 | val io = IO(new Bundle{ 7 | val in0 = Input(Bool()) 8 | val in1 = Input(Bool()) 9 | val in2 = Input(Bool()) 10 | val in3 = Input(Bool()) 11 | val in4 = Input(Bool()) 12 | val in5 = Input(Bool()) 13 | val in6 = Input(Bool()) 14 | val in7 = Input(Bool()) 15 | val sel = Input(UInt(3.W)) 16 | val out = Output(Bool()) 17 | }) 18 | 19 | io.out := MuxLookup(io.sel , false.B, Array( 20 | (0.U) -> io.in0, 21 | (1.U) -> io.in1, 22 | (2.U) -> io.in2, 23 | (3.U) -> io.in3, 24 | (4.U) -> io.in4, 25 | (5.U) -> io.in5, 26 | (6.U) -> io.in6, 27 | (7.U) -> io.in7) 28 | ) 29 | } 30 | 31 | println((new chisel3.stage.ChiselStage).emitVerilog(new MuxLookup())) 32 | -------------------------------------------------------------------------------- /Example_code/Lab4/MuxTreeTest.scala: -------------------------------------------------------------------------------- 1 | package LM_Chisel 2 | import chisel3._ 3 | import chisel3.iotesters.{Driver, PeekPokeTester} 4 | 5 | class TestMuxT(c: MuxTree) extends PeekPokeTester(c) { 6 | val in1 = 0x11111111 7 | val in2 = 0x22222222 8 | val in3 = 0x33333333 9 | 10 | poke(c.io.in_1, in1.U) 11 | poke(c.io.in_2, in2.U) 12 | poke(c.io.in_3, in3.U) 13 | 14 | poke(c.io.sel_1, false.B) 15 | poke(c.io.sel_2, false.B) 16 | expect(c.io.out, in1.U) 17 | step(1) 18 | 19 | poke(c.io.sel_1, true.B) 20 | poke(c.io.sel_2, false.B) 21 | expect(c.io.out, in2.U) 22 | step(1) 23 | 24 | poke(c.io.sel_1, true.B) 25 | poke(c.io.sel_2, true.B) 26 | expect(c.io.out, in3.U) 27 | step(3) 28 | } 29 | 30 | // object for tester class 31 | object MuxT_Main extends App { 32 | iotesters.Driver.execute(Array("--is-verbose", "--generate-vcd-output", 33 | "on", "--backend-name", "firrtl"), () => new MuxTree) { 34 | c => new TestMuxT(c) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Example_code/Lab3/Branch_Control.scala: -------------------------------------------------------------------------------- 1 | class BranchControl extends Module { 2 | val io = IO(new LM_IO_Interface) 3 | 4 | io.br_taken := DontCare 5 | val cond_true = Wire(Bool()) 6 | cond_true := DontCare 7 | 8 | switch(io.fnct3) { 9 | is("b000".U) {cond_true := (io.arg_x === io.arg_y)} //beq 10 | is("b001".U) {cond_true := (io.arg_x =/= io.arg_y)} //bne 11 | is("b100".U) {cond_true := (io.arg_x.asSInt < io.arg_y.asSInt)} //blt 12 | is("b101".U) {cond_true := (io.arg_x.asSInt >= io.arg_y.asSInt)} //bge 13 | is("b110".U) {cond_true := (io.arg_x < io.arg_y)} //bltu 14 | is("b111".U) {cond_true := (io.arg_x >= io.arg_y)} //bgeu 15 | } 16 | io.br_taken := cond_true & io.branch 17 | } 18 | class LM_IO_Interface extends Bundle { 19 | val fnct3 = Input(UInt(3.W)) 20 | val branch = Input(Bool()) 21 | val arg_x = Input(UInt(32.W)) 22 | val arg_y = Input(UInt(32.W)) 23 | val br_taken = Output(Bool()) 24 | } 25 | -------------------------------------------------------------------------------- /Example_code/Lab9/control_ListLookUp.scala: -------------------------------------------------------------------------------- 1 | object Control { 2 | 3 | val default = 4 | // kill wb_en illegal? en_rs2 5 | // pc_sel A_sel B_sel imm_sel alu_op br_type | st_type ld_type wb_sel | csr_cmd | en_rs1 | 6 | // | | | | | | | | | | | | | | | 7 | List(PC_4, A_XXX, B_XXX, IMM_X, ALU_XXX , BR_XXX, N, ST_XXX, LD_XXX, WB_ALU, N, CSR.Z, Y, N, N) 8 | val map = Array( 9 | LUI -> List(PC_4 , A_PC, B_IMM, IMM_U, ALU_COPY_B, BR_XXX, N, ST_XXX, LD_XXX, WB_ALU, Y, CSR.Z, N, N, N), 10 | AUIPC -> List(PC_4 , A_PC, B_IMM, IMM_U, ALU_ADD , BR_XXX, N, ST_XXX, LD_XXX, WB_ALU, Y, CSR.Z, N, N, N), 11 | JAL -> List(PC_ALU, A_PC, B_IMM, IMM_J, ALU_ADD , BR_XXX, Y, ST_XXX, LD_XXX, WB_PC4, Y, CSR.Z, N, N, N), 12 | JALR -> List(PC_ALU, A_RS1,B_IMM, IMM_I, ALU_ADD , BR_XXX, Y, ST_XXX, LD_XXX, WB_PC4, Y, CSR.Z, N, Y, N), -------------------------------------------------------------------------------- /Example_code/Lab9/Map_example.scala: -------------------------------------------------------------------------------- 1 | // Map of timer registers 2 | val timer_regs_map = Map("cntReg" -> 10001014, "cmpReg" -> 10001018, "contReg" -> 10001010) 3 | 4 | // Map of uart registers 5 | val uart_regs_map = Map("txReg" -> 10001000, "rxReg" -> 10001004, "contReg" -> 10001008) 6 | 7 | println("Timer Regs: " + timer_regs_map) 8 | println("Uart Regs: " + uart_regs_map) 9 | 10 | // concatenating two maps using ++ operator 11 | val combined_regs = (uart_regs_map ++ timer_regs_map) 12 | 13 | combined_regs.keys.foreach{i => print( "Reg Name = " + i ) 14 | println(" Address = " + combined_regs(i))} 15 | 16 | // The output at the terminal 17 | Timer Regs: Map(cntReg -> 10001000, cmpReg -> 10001004, contReg -> 10001010) 18 | 19 | Uart Regs: Map(txReg -> 10001000, rxReg -> 10001004, contReg -> 10001008) 20 | 21 | Reg Name = contReg Address = 10001010 22 | Reg Name = rxReg Address = 10001004 23 | Reg Name = txReg Address = 10001000 24 | Reg Name = cmpReg Address = 10001018 25 | Reg Name = cntReg Address = 10001014 -------------------------------------------------------------------------------- /Example_code/Lab8/mem.scala: -------------------------------------------------------------------------------- 1 | // mem Example 2 | import chisel3._ 3 | 4 | class IO_Interface extends Bundle{ 5 | // Make an input from a Vector of 4 values 6 | val data_in = Input(Vec(4,(UInt(32.W)))) 7 | 8 | // Signal to control which vector is selected 9 | val data_selector = Input(UInt(2.W)) 10 | val data_out = Output(UInt(32.W)) 11 | val addr = Input(UInt(5.W)) 12 | 13 | // The signal is high for write 14 | val wr_en = Input(Bool()) 15 | } 16 | 17 | class Asynch_Mem extends Module { 18 | val io = IO(new IO_Interface) 19 | 20 | io.data_out := 0.U 21 | 22 | // Make a memory of 32x32 23 | val memory = Mem(32, UInt(32.W)) 24 | 25 | when(io.wr_en){ // Write for wr_en = 1 26 | // Write at memory location addr, with selected data from data_in 27 | memory.write(io.addr, io.data_in(io.data_selector)) 28 | } 29 | // Asyncronous read from addr location 30 | io.data_out := memory.read(io.addr) 31 | } 32 | 33 | println((new chisel3.stage.ChiselStage).emitVerilog(new Asynch_Mem())) 34 | -------------------------------------------------------------------------------- /Example_code/Lab2/mux_Case.scala: -------------------------------------------------------------------------------- 1 | // 8 to 1 mux using MuxCase 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class MuxCase_ex extends Module { 6 | val io = IO(new Bundle{ 7 | val in0 = Input(Bool()) 8 | val in1 = Input(Bool()) 9 | val in2 = Input(Bool()) 10 | val in3 = Input(Bool()) 11 | val in4 = Input(Bool()) 12 | val in5 = Input(Bool()) 13 | val in6 = Input(Bool()) 14 | val in7 = Input(Bool()) 15 | val sel = Input(UInt(3.W)) 16 | val out = Output(Bool()) 17 | }) 18 | 19 | io.out := MuxCase(false.B, Array( 20 | (io.sel===0.U) -> io.in0, 21 | (io.sel===1.U) -> io.in1, 22 | (io.sel===2.U) -> io.in2, 23 | (io.sel===3.U) -> io.in3, 24 | (io.sel===4.U) -> io.in4, 25 | (io.sel===5.U) -> io.in5, 26 | (io.sel===6.U) -> io.in6, 27 | (io.sel===7.U) -> io.in7) 28 | ) 29 | } 30 | 31 | println((new chisel3.stage.ChiselStage).emitVerilog(new MuxCase_ex())) 32 | -------------------------------------------------------------------------------- /Example_code/Lab2/Bundle_Vec.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | 3 | class LM_IO_Interface extends Bundle{ 4 | // Make an input from a Vector of 4 values 5 | val data_in = Input(Vec(4,(UInt(32.W)))) 6 | 7 | // Signal to control which vector is selected 8 | val data_selector = Input(UInt(2.W)) 9 | 10 | val data_out = Output(UInt(32.W)) 11 | val addr = Input(UInt(5.W)) 12 | 13 | // The signal is high for write 14 | val wr_en = Input(Bool()) 15 | } 16 | 17 | class Mem_bundle_intf extends Module { 18 | val io = IO(new LM_IO_Interface) 19 | 20 | io.data_out := 0.U 21 | 22 | // Make a memory of 32X32 23 | val memory = Mem(32, UInt(32.W)) 24 | 25 | when(io.wr_en){ // Write for wr_en = 1 26 | // Write at memory location addr, with selected data from data_in (Vector) 27 | memory.write(io.addr, io.data_in(io.data_selector)) 28 | } .otherwise{ 29 | // Asyncronous read from addr location 30 | io.data_out := memory.read(io.addr) 31 | } 32 | } 33 | 34 | println((new chisel3.stage.ChiselStage).emitVerilog(new Mem_bundle_intf())) 35 | -------------------------------------------------------------------------------- /Example_code/Lab2/Bundle_Vec_slides.scala: -------------------------------------------------------------------------------- 1 | //Example using Asynchronous memory 2 | import chisel3._ 3 | import chisel3.util._ 4 | 5 | class IO_Interface extends Bundle{ 6 | // input using a Vector of 4 values 7 | val data_in = Input(Vec(4,(UInt(32.W)))) 8 | 9 | val data_selector = Input(UInt(2.W)) // vector slection lines 10 | val data_out = Output(UInt(32.W)) // output data 11 | val addr = Input(UInt(5.W)) // address lines 12 | val wr_en = Input(Bool()) // high for write 13 | } 14 | 15 | class Mem_bundle_intf extends Module { 16 | val io = IO(new IO_Interface) 17 | val memory = Mem(32, UInt(32.W)) // Make memory of 32x32 18 | 19 | io.data_out := 0.U 20 | 21 | when(io.wr_en) { 22 | // Write at addr, with selected data from data_in vector 23 | memory.write(io.addr, io.data_in(io.data_selector)) 24 | } .otherwise { 25 | // Asyncronous read from addr location 26 | io.data_out := memory.read(io.addr) 27 | } 28 | } 29 | 30 | println((new chisel3.stage.ChiselStage).emitVerilog(new Mem_bundle_intf())) -------------------------------------------------------------------------------- /Example_code/Lab16/Manager_param.scala: -------------------------------------------------------------------------------- 1 | case class TLManagerParameters( 2 | address: Seq[AddressSet], 3 | resources: Seq[Resource] = Seq(), 4 | regionType: RegionType.T = RegionType.GET_EFFECTS, 5 | executable: Boolean = false, 6 | nodePath: Seq[BaseNode] = Seq(), 7 | supportsAcquireT: TransferSizes = TransferSizes.none, 8 | supportsAcquireB: TransferSizes = TransferSizes.none, 9 | supportsArithmetic:TransferSizes = TransferSizes.none, 10 | supportsLogical: TransferSizes = TransferSizes.none, 11 | supportsGet: TransferSizes = TransferSizes.none, 12 | supportsPutFull: TransferSizes = TransferSizes.none, 13 | supportsPutPartial:TransferSizes = TransferSizes.none, 14 | supportsHint: TransferSizes = TransferSizes.none, 15 | mayDenyGet: Boolean = false, // applies to: AccessAckData, GrantData 16 | mayDenyPut: Boolean = false, // applies to: AccessAck, Grant, HintAck 17 | alwaysGrantsT: Boolean = false, // typically only true for CacheCork'd read-write devices 18 | fifoId: Option[Int] = None, 19 | device: Option[Device] = None){...} 20 | -------------------------------------------------------------------------------- /Example_code/Lab3/alu_mux.scala: -------------------------------------------------------------------------------- 1 | class ALU extends Module with Config { 2 | val io = IO(new AluIO) 3 | 4 | val sum = io.in_A + Mux(io.alu_Op(0), -io.in_B, io.in_B) 5 | val cmp = Mux(io.in_A (XLEN-1) === io.in_B(XLEN-1), sum(XLEN-1), 6 | Mux(io.alu_Op(1), io.in_B(XLEN-1), io.in_A(XLEN-1))) 7 | val shamt = io.in_B(4,0).asUInt 8 | val shin = Mux(io.alu_Op(3), io.in_A, Reverse(io.in_A)) 9 | val shiftr = (Cat(io.alu_Op(0) && shin(XLEN-1), shin).asSInt >> shamt) (XLEN-1, 0) 10 | 11 | val shiftl = Reverse(shiftr) 12 | 13 | val out = 14 | Mux(io.alu_Op === ALU_ADD.U || io.alu_Op === ALU_SUB.U, sum, 15 | Mux(io.alu_Op === ALU_SLT.U || io.alu_Op === ALU_SLTU.U, cmp, 16 | Mux(io.alu_Op === ALU_SRA.U || io.alu_Op === ALU_SRL.U, shiftr, 17 | Mux(io.alu_Op === ALU_SLL.U, shiftl, 18 | Mux(io.alu_Op === ALU_AND.U, (io.in_A & io.in_B), 19 | Mux(io.alu_Op === ALU_OR.U, (io.in_A | io.in_B), 20 | Mux(io.alu_Op === ALU_XOR.U, (io.in_A ^ io.in_B), 21 | Mux(io.alu_Op === ALU_COPY_A.U, io.in_A, 22 | Mux(io.alu_Op === ALU_COPY_A.U, io.in_B, 0.U))))))))) 23 | 24 | io.out := out 25 | } -------------------------------------------------------------------------------- /Example_code/Lab2/Flipped_Bulk_slides.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | 3 | class IO_Interface extends Bundle { 4 | val data_M_to_S = Output(UInt(32.W)) 5 | val data_S_to_M = Input(UInt(32.W)) 6 | val addr = Output(UInt(5.W)) 7 | val rd_wr = Output(Bool()) 8 | } 9 | 10 | class Master extends Module { 11 | val io = IO(new IO_Interface) 12 | 13 | io.data_M_to_S := io.data_S_to_M 14 | io.addr := 2.U 15 | io.rd_wr := true.B 16 | } 17 | 18 | class Slave extends Module { 19 | val io = IO(Flipped(new IO_Interface)) // use of Flipped 20 | 21 | io.data_S_to_M := io.data_M_to_S 22 | } 23 | 24 | class Top_Level extends Module { 25 | val io = IO(new Bundle { 26 | val master_io = new IO_Interface 27 | val slave_io = Flipped(new IO_Interface) // use of Flipped 28 | }) 29 | 30 | val master_node = Module(new Master()) 31 | val slave_node = Module(new Slave()) 32 | 33 | master_node.io <> slave_node.io // bulk connections 34 | io.master_io <> master_node.io 35 | io.slave_io <> slave_node.io 36 | } 37 | 38 | println((new chisel3.stage.ChiselStage).emitVerilog(new Top_Level)) 39 | -------------------------------------------------------------------------------- /Example_code/Lab4/aluTest_body1.scala: -------------------------------------------------------------------------------- 1 | class TestALU(c: ALU) extends PeekPokeTester(c) { 2 | // ALU operations 3 | val array_op = Array(ALU_ADD , ALU_SUB, ALU_AND, ALU_OR, ALU_XOR, ALU_SLT, ALU_SLL, ALU_SLTU, ALU_SRL, ALU_SRA, ALU_COPY_A, ALU_COPY_B, ALU_XXX) 4 | 5 | for (i <- 0 until 100) { 6 | 7 | val src_a = Random.nextLong()& 0xFFFFFFFFL 8 | val src_b = Random.nextLong()& 0xFFFFFFFFL 9 | val opr = Random.nextInt(12) 10 | val aluop = array_op(opr) 11 | 12 | // ALU functional implementation using Scala match 13 | val result = aluop match { 14 | case ALU_ADD => src_a + src_b 15 | case ALU_SUB => src_a - src_b 16 | case ALU_AND => src_a & src_b 17 | case ALU_OR => src_a | src_b 18 | case ALU_XOR => src_a ^ src_b 19 | case ALU_SLT => (src_a.toInt < src_b.toInt).toInt 20 | case ALU_SLL => src_a << (src_b & 0x1F) 21 | case ALU_SLTU => (src_a < src_b).toInt 22 | case ALU_SRL => src_a >> (src_b & 0x1F) 23 | case ALU_SRA => src_a.toInt >> (src_b & 0x1F) 24 | case ALU_COPY_A => src_a 25 | case ALU_COPY_B => src_b 26 | case _ => 0 27 | } 28 | 29 | -------------------------------------------------------------------------------- /Example_code/Lab7/FSM_Seq_D.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester} 4 | import chisel3.experimental.ChiselEnum 5 | 6 | //Sequence to detect is 110 7 | class Detect_Seq extends Module { 8 | val io = IO(new Bundle { 9 | val in = Input(Bool()) 10 | val out = Output(Bool()) 11 | }) 12 | 13 | val s0 :: s1 :: s2 :: Nil = Enum(3) //Enumeration type 14 | val state = RegInit(s0) //state = s0 15 | 16 | io.out := (state === s2) & (!io.in) //Mealy type state machine 17 | 18 | switch (state) { 19 | is (s0) { 20 | when (io.in) { //move to next state when input is 1 21 | state := s1 22 | } 23 | } 24 | is (s1) { 25 | when (io.in) { //move to next state when input is 1 26 | state := s2 27 | } .otherwise { 28 | state := s0 29 | } 30 | } 31 | is (s2) { 32 | when (!io.in) { 33 | //move to default state when input is zero 34 | // otherwise stay here because input sequence is 111 35 | state := s0 36 | } 37 | } 38 | } 39 | } 40 | println(chisel3.Driver.emitVerilog(new Detect_Seq)) 41 | -------------------------------------------------------------------------------- /Example_code/Lab5/cloneType.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.stage.ChiselStage 3 | 4 | class Adder_Inputs(x: Int, y: Int) extends Bundle { 5 | val in1 = UInt(x.W) 6 | val in2 = UInt(y.W) 7 | 8 | // creating a custom cloneType method 9 | override def cloneType = (new Adder_Inputs(x, y)).asInstanceOf[this.type] 10 | } 11 | 12 | class Adder(inBundle: Adder_Inputs, outSize: Int) extends Module { 13 | val io = IO(new Bundle { 14 | val out = Output(UInt(outSize.W)) 15 | 16 | // chiselTypeOf returns the chisel type of the object 17 | val in_bundle = Input(chiselTypeOf(inBundle)) 18 | }) 19 | io.out := io.in_bundle.in1 + io.in_bundle.in2 20 | } 21 | 22 | class Top(in1Size: Int, in2Size: Int, outSize: Int) extends Module { 23 | val io = IO(new Bundle { 24 | val out = Output(UInt(outSize.W)) 25 | val in = Input(UInt(in1Size.W)) 26 | }) 27 | 28 | // input bundle instance 29 | val inBundle = Wire(new Adder_Inputs(in1Size, in2Size)) 30 | inBundle := DontCare 31 | 32 | // module instance 33 | val m = Module(new Adder(inBundle, outSize)) 34 | m.io.in_bundle.in1 := io.in 35 | m.io.in_bundle.in2 := io.in 36 | io.out := m.io.out 37 | } 38 | 39 | println((new ChiselStage).emitVerilog(new Top(18, 30, 32))) -------------------------------------------------------------------------------- /Example_code/Lab5/parameter_module.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.experimental.{BaseModule} 3 | 4 | // Provides a more specific interface since generic Module 5 | // provides no compile-time information on generic module's IOs. 6 | trait MyAdder { 7 | def in1: UInt 8 | def in2: UInt 9 | def out: UInt 10 | } 11 | 12 | class Mod1 extends RawModule with MyAdder { 13 | val in1 = IO(Input(UInt(8.W))) 14 | val in2 = IO(Input(UInt(8.W))) 15 | val out = IO(Output(UInt(8.W))) 16 | out := in1 + in2 17 | } 18 | 19 | class Mod2 extends RawModule with MyAdder { 20 | val in1 = IO(Input(UInt(8.W))) 21 | val in2 = IO(Input(UInt(8.W))) 22 | val out = IO(Output(UInt(8.W))) 23 | out := in1 - in2 24 | } 25 | 26 | class X[T <: BaseModule with MyAdder](genT: => T) extends Module { 27 | val io = IO(new Bundle { 28 | val in1 = Input(UInt(8.W)) 29 | val in2 = Input(UInt(8.W)) 30 | val out = Output(UInt(8.W)) 31 | }) 32 | val subMod = Module(genT) 33 | io.out := subMod.out 34 | subMod.in1 := io.in1 35 | subMod.in2 := io.in2 36 | } 37 | 38 | println((new chisel3.stage.ChiselStage).emitVerilog(new X(new Mod1))) 39 | println((new chisel3.stage.ChiselStage).emitVerilog(new X(new Mod2))) -------------------------------------------------------------------------------- /Example_code/Lab2/Flipped_Bulk.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | 4 | class Interface extends Bundle { 5 | val in_data = Input(UInt(6.W)) 6 | val valid = Output(Bool()) 7 | val out_data = Output(UInt(6.W)) 8 | } 9 | 10 | class MS_interface extends Bundle { 11 | val s2m = Input(UInt(6.W)) 12 | val m2s = Output(UInt(6.W)) 13 | } 14 | 15 | class Top_module extends Module { 16 | val io = IO(new Interface) 17 | 18 | val master = Module(new Master) 19 | val slave = Module(new Slave) 20 | //connecting top with master => same direction, same name connects 21 | io <> master.io.top_int 22 | //connecting master with slave => opposite direction, same name connects 23 | master.io.MS <> slave.io 24 | } 25 | 26 | class Master extends Module { 27 | val io = IO(new Bundle { 28 | val top_int = new Interface 29 | val MS = new MS_interface 30 | }) 31 | 32 | io.MS.m2s := io.top_int.in_data 33 | io.top_int.valid := true.B 34 | io.top_int.out_data := io.MS.s2m 35 | } 36 | 37 | class Slave extends Module { 38 | val io = IO(Flipped(new MS_interface)) 39 | 40 | io.s2m := io.m2s + 16.U 41 | } 42 | 43 | println(chisel3.Driver.emitVerilog(new Top_module)) 44 | -------------------------------------------------------------------------------- /Example_code/Lab13/parameterize.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | import chisel3.experimental.{BaseModule} 4 | 5 | // Define IO interface as a Trait 6 | trait ModuleIO { 7 | def in1: UInt 8 | def in2: UInt 9 | def out: UInt 10 | } 11 | 12 | class Add extends RawModule with ModuleIO { 13 | val in1 = IO(Input(UInt(8.W))) 14 | val in2 = IO(Input(UInt(8.W))) 15 | val out = IO(Output(UInt(8.W))) 16 | out := in1 + in2 17 | } 18 | 19 | class Sub extends RawModule with ModuleIO { 20 | val in1 = IO(Input(UInt(8.W))) 21 | val in2 = IO(Input(UInt(8.W))) 22 | val out = IO(Output(UInt(8.W))) 23 | out := in1 - in2 24 | } 25 | 26 | class Top [T <: BaseModule with ModuleIO] (genT: => T) extends Module { 27 | val io = IO(new Bundle { 28 | val in1 = Input(UInt(8.W)) 29 | val in2 = Input(UInt(8.W)) 30 | val out = Output(UInt(8.W)) 31 | }) 32 | val sub_Module = Module(genT) 33 | io.out := sub_Module.out 34 | sub_Module.in1 := io.in1 35 | sub_Module.in2 := io.in2 36 | } 37 | 38 | // Generate verilog for two modules, one for addition, second for subtraction 39 | println((new chisel3.stage.ChiselStage).emitVerilog(new Top(new Add))) 40 | println((new chisel3.stage.ChiselStage).emitVerilog(new Top(new Sub))) -------------------------------------------------------------------------------- /Example_code/Lab3/alu.scala: -------------------------------------------------------------------------------- 1 | //ALU example 2 | import chisel3._ 3 | 4 | class LM_IO_Interface extends Bundle { 5 | val alu_oper = Input(UInt(4.W)) 6 | val arg_x = Input(UInt(32.W)) 7 | val arg_y = Input(UInt(32.W)) 8 | val alu_out = Output(UInt(32.W)) 9 | } 10 | 11 | class myALU extends Module { 12 | val io = IO(new LM_IO_Interface) 13 | 14 | io.alu_out := 0.U 15 | 16 | switch(io.alu_oper) { 17 | is("b0000".U) { //AND 18 | io.alu_out := io.arg_x & io.arg_y 19 | } 20 | is("b0001".U) { //OR 21 | io.alu_out := io.arg_x | io.arg_y 22 | } 23 | is("b0010".U) { //ADD 24 | io.alu_out := io.arg_x + io.arg_y 25 | } 26 | is("b0110".U) { //SUB 27 | io.alu_out := io.arg_x - io.arg_y 28 | } 29 | is("b0011".U) { //XOR 30 | io.alu_out := io.arg_x ^ io.arg_y 31 | } 32 | is("b0100".U) { //SLL 33 | io.alu_out := io.arg_x << io.arg_y(4, 0) 34 | } 35 | is("b0101".U) { //SRL 36 | io.alu_out := io.arg_x >> io.arg_y(4, 0) 37 | } 38 | is("b0111".U) { //SRA 39 | io.alu_out := (io.arg_x.asSInt >> io.arg_y(4, 0)).asUInt 40 | } 41 | is("b1000".U) { //SLT 42 | io.alu_out := io.arg_x.asSInt < io.arg_y.asSInt 43 | } 44 | is("b1001".U) { //SLTU 45 | io.alu_out := io.arg_x < io.arg_y 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Example_code/Lab2/Flipped_Bulk1.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester} 4 | 5 | class Interface extends Bundle { 6 | val in_data = Input(UInt(6.W)) 7 | val valid = Output(Bool()) 8 | val out_data = Output(UInt(6.W)) 9 | } 10 | 11 | class MS_interface extends Bundle { 12 | val s2m = Input(UInt(6.W)) 13 | val m2s = Output(UInt(6.W)) 14 | } 15 | 16 | class Top_module extends Module { 17 | val io = IO(new Interface) 18 | 19 | val master = Module(new Master) 20 | val slave = Module(new Slave) 21 | 22 | io <> master.io.top_int //connecting top with master => same direction and same name connects 23 | master.io.MS <> slave.io //connecting master with slave => opposite direction and same name connects 24 | } 25 | 26 | class Master extends Module { 27 | val io = IO(new Bundle { 28 | val top_int = new Interface 29 | val MS = new MS_interface 30 | 31 | }) 32 | 33 | io.MS.m2s := io.top_int.in_data 34 | io.top_int.valid := true.B 35 | io.top_int.out_data := io.MS.s2m + io.MS.m2s 36 | } 37 | 38 | class Slave extends Module { 39 | val io = IO(Flipped(new MS_interface)) 40 | 41 | io.s2m := io.m2s + 16.U 42 | } 43 | 44 | println(chisel3.Driver.emitVerilog(new Top_module)) 45 | -------------------------------------------------------------------------------- /Example_code/Lab7/CounterUpDown.scala: -------------------------------------------------------------------------------- 1 | // up-down counter implementation 2 | 3 | package LM_Chisel 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | 8 | class CounterUpDown(n: Int) extends Module { 9 | val io = IO(new Bundle { 10 | val data_in = Input(UInt(n.W)) 11 | val out = Output(Bool())}) 12 | 13 | val counter = RegInit(0.U(n.W)) 14 | val max_count = RegInit(6.U(n.W)) 15 | 16 | val init :: up :: down :: Nil = Enum(3) // Enumeration type 17 | val state = RegInit(init) // state = init 18 | val up_flag = (counter === max_count) 19 | val down_flag = (counter === 0.U) 20 | 21 | switch (state) { 22 | is (init) { 23 | state := up // on reset 24 | } 25 | 26 | is (up) { 27 | when (up_flag) { 28 | state := down 29 | // start count down immediately on up_flag 30 | counter := counter - 1.U 31 | }.otherwise { 32 | counter := counter + 1.U 33 | } 34 | } 35 | 36 | is (down) { 37 | when (down_flag) { 38 | state := up 39 | counter := counter + 1.U 40 | max_count := io.data_in // load the counter 41 | }.otherwise { 42 | counter := counter - 1.U 43 | } 44 | } 45 | } 46 | io.out := up_flag | down_flag 47 | } 48 | object CounterUpDown_generate extends App { 49 | chisel3.Driver.execute(args, () => new CounterUpDown(8)) 50 | } 51 | 52 | -------------------------------------------------------------------------------- /Example_code/Lab8/dataMem.scala: -------------------------------------------------------------------------------- 1 | package LM_Chisel 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | import Control._ 6 | 7 | class DataMemIO extends Bundle with Config { 8 | val addr = Input(UInt(WLEN.W)) 9 | val wdata = Input(UInt(WLEN.W)) 10 | val rd_en = Input(Bool()) 11 | val wr_en = Input(Bool()) 12 | val st_type = Input(UInt(STTYPE_LEN.W)) 13 | val rdata = Output(UInt(WLEN.W)) 14 | } 15 | 16 | class DataMem extends Module with Config { 17 | val io = IO(new DataMemIO) 18 | 19 | // Data memory size and addressability width 20 | val dmem = SyncReadMem(DATA_MEM_LEN, UInt(BLEN.W)) 21 | val addr = io.addr 22 | val read_data = Wire(UInt(XLEN.W)) 23 | read_data := 0.U 24 | 25 | when (io.wr_en) { 26 | when (io.st_type === 1.U) { 27 | dmem (addr) := io.wdata(7,0) 28 | dmem (addr + 1.U) := io.wdata(15,8) 29 | dmem (addr + 2.U) := io.wdata(23,16) 30 | dmem (addr + 3.U) := io.wdata(31,24) 31 | }.elsewhen (io.st_type === 2.U) { 32 | dmem (addr) := io.wdata(7,0) 33 | dmem (addr + 1.U) := io.wdata(15,8) 34 | }.elsewhen (io.st_type === 3.U) { 35 | dmem (addr) := io.wdata(7,0) 36 | } 37 | } 38 | 39 | // read data from 4 memory banks 40 | read_data := Cat(dmem(addr + 3.U), dmem(addr + 2.U), dmem(addr + 1.U), dmem(addr)) 41 | 42 | io.rdata := Mux(io.rd_en, read_data, 0.U) 43 | } -------------------------------------------------------------------------------- /Example_code/Lab3/advance_alu.scala: -------------------------------------------------------------------------------- 1 | import ALUOP._ 2 | 3 | class ALUIO extends Bundle with Config { 4 | val in_A = Input(UInt(WLEN.W)) 5 | val in_B = Input(UInt(WLEN.W)) 6 | val alu_Op = Input(UInt(ALUOP_SIG_LEN.W)) 7 | val out = Output(UInt(WLEN.W)) 8 | val sum = Output(UInt(WLEN.W)) 9 | } 10 | 11 | class ALU extends Module with Config { 12 | val io = IO(new ALUIO) 13 | 14 | val sum = io.in_A + Mux(io.alu_Op(0), -io.in_B, io.in_B) 15 | val cmp = Mux(io.in_A (XLEN-1) === io.in_B(XLEN-1), sum(XLEN-1), 16 | Mux(io.alu_Op(1), io.in_B(XLEN-1), io.in_A(XLEN-1))) 17 | val shamt = io.in_B(4,0).asUInt 18 | val shin = Mux(io.alu_Op(3), io.in_A, Reverse(io.in_A)) 19 | val shiftr = (Cat(io.alu_Op(0) && shin(XLEN-1), shin).asSInt >> shamt)(XLEN-1, 0) 20 | val shiftl = Reverse(shiftr) 21 | 22 | val out = 23 | Mux(io.alu_Op === ALU_ADD.U || io.alu_Op === ALU_SUB.U, sum, 24 | Mux(io.alu_Op === ALU_SLT.U || io.alu_Op === ALU_SLTU.U, cmp, 25 | Mux(io.alu_Op === ALU_SRA.U || io.alu_Op === ALU_SRL.U, shiftr, 26 | Mux(io.alu_Op === ALU_SLL.U, shiftl, 27 | Mux(io.alu_Op === ALU_AND.U, (io.in_A & io.in_B), 28 | Mux(io.alu_Op === ALU_OR.U, (io.in_A | io.in_B), 29 | Mux(io.alu_Op === ALU_XOR.U, (io.in_A ^ io.in_B), 30 | Mux(io.alu_Op === ALU_COPY_A.U, io.in_A, 31 | Mux(io.alu_Op === ALU_COPY_A.U, io.in_B, 0.U))))))))) 32 | 33 | io.out := out 34 | io.sum := sum 35 | } 36 | -------------------------------------------------------------------------------- /Example_code/Lab7/FSM_Manchester_Tester.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester} 4 | import chisel3.experimental.ChiselEnum 5 | import chisel3.experimental.{withClock, withReset, withClockAndReset} 6 | import chisel3.experimental.BundleLiterals._ 7 | 8 | class Tester(c: Manchester_Encoding) extends PeekPokeTester(c) { 9 | poke(c.io.start,false.B) 10 | step(1) 11 | poke(c.io.start,true.B) 12 | step(1) 13 | 14 | poke(c.io.in,1.U) //1 15 | step(1) 16 | poke(c.io.in,0.U) 17 | step(1) 18 | 19 | 20 | poke(c.io.in,1.U) //1 21 | step(1) 22 | poke(c.io.in,0.U) 23 | step(1) 24 | 25 | 26 | poke(c.io.in,0.U) //0 27 | step(1) 28 | poke(c.io.in,1.U) 29 | step(1) 30 | 31 | 32 | poke(c.io.in,0.U) //0 33 | step(1) 34 | poke(c.io.in,1.U) 35 | step(1) 36 | 37 | poke(c.io.in,1.U) //1 38 | step(1) 39 | poke(c.io.in,0.U) 40 | step(1) 41 | 42 | 43 | poke(c.io.in,1.U) //1 44 | step(1) 45 | poke(c.io.in,0.U) 46 | step(1) 47 | 48 | 49 | poke(c.io.in,0.U) //0 50 | step(1) 51 | poke(c.io.in,1.U) 52 | step(1) 53 | 54 | 55 | poke(c.io.in,1.U) //1 56 | step(1) 57 | poke(c.io.in,0.U) 58 | //step(1) 59 | 60 | expect(c.io.out,205.U) 61 | expect(c.io.flag,1.U) 62 | 63 | } 64 | assert(Driver(() => new Manchester_Encoding) {c => new Tester(c)}) 65 | println("SUCCESS!!") 66 | -------------------------------------------------------------------------------- /Example_code/Lab16/Node.scala: -------------------------------------------------------------------------------- 1 | trait InwardNodeImp[DI, UI, EI, BI <: Data]{...} 2 | 3 | // DO = Downwards flowing Parameters generated by the outer side of the node 4 | // UO = Upwards flowing Parameters received on the outer side of the node 5 | // EO = Edge Parameters describing a connection on the outer side of the node 6 | // BO = Bundle type used when connecting to the outer side of the node 7 | trait OutwardNodeImp[DO, UO, EO, BO <: Data]{...} 8 | 9 | abstract class NodeImp[D, U, EO, EI, B <: Data] 10 | extends Object with InwardNodeImp[D, U, EI, B] with OutwardNodeImp[D, U, EO, B] 11 | 12 | sealed abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( 13 | val inner: InwardNodeImp [DI, UI, EI, BI], 14 | val outer: OutwardNodeImp[DO, UO, EO, BO])( 15 | implicit valName: ValName) 16 | extends BaseNode with NodeHandle[DI, UI, EI, BI, DO, UO, EO, BO] with InwardNode[DI, UI, BI] with OutwardNode[DO, UO, BO]{...} 17 | 18 | class NexusNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])( 19 | dFn: Seq[D] => D, 20 | uFn: Seq[U] => U, 21 | inputRequiresOutput: Boolean = true, 22 | outputRequiresInput: Boolean = true)( 23 | implicit valName: ValName) 24 | extends MixedNexusNode[D, U, EI, B, D, U, EO, B](imp, imp)(dFn, uFn, inputRequiresOutput, outputRequiresInput) 25 | 26 | // There are no Mixed SourceNodes/SinkNodes 27 | class SourceNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(po: Seq[D])(implicit valName: ValName) 28 | extends MixedNode(imp, imp){...} 29 | 30 | class SinkNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(pi: Seq[U])(implicit valName: ValName) 31 | extends MixedNode(imp, imp){...} 32 | -------------------------------------------------------------------------------- /Example_code/Lab5/ALU_Param.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | import chisel3.iotesters.{Driver,PeekPokeTester} 4 | 5 | class ALU(width_parameter:Int) extends Module { 6 | val io = IO(new IO_Interface(width_parameter)) 7 | 8 | io.alu_out := 0.U 9 | val index = log2Ceil(width_parameter) 10 | 11 | switch(io.alu_oper) { //AND 12 | is("b0000".U) { 13 | io.alu_out := io.arg_x & io.arg_y 14 | } //OR 15 | is("b0001".U) { 16 | io.alu_out := io.arg_x | io.arg_y 17 | } //ADD 18 | is("b0010".U) { 19 | io.alu_out := io.arg_x + io.arg_y 20 | } //SUB 21 | is("b0110".U) { 22 | io.alu_out := io.arg_x - io.arg_y 23 | } //XOR 24 | is("b0011".U) { 25 | io.alu_out := io.arg_x ^ io.arg_y 26 | } //SLL 27 | is("b0100".U) { 28 | io.alu_out := io.arg_x << io.arg_y(index-1, 0) 29 | } //SRL 30 | is("b0101".U) { 31 | io.alu_out := io.arg_x >> io.arg_y(index-1, 0) 32 | } //SRA 33 | is("b0111".U) { 34 | io.alu_out := (io.arg_x.asSInt >> io.arg_y(index-1, 0)).asUInt 35 | } //SLT 36 | is("b1000".U) { 37 | io.alu_out := io.arg_x.asSInt < io.arg_y.asSInt 38 | } //SLTU 39 | is("b1001".U) { 40 | io.alu_out := io.arg_x < io.arg_y 41 | } 42 | } 43 | } 44 | 45 | class IO_Interface(width:Int) extends Bundle { 46 | val alu_oper = Input(UInt(width.W)) 47 | val arg_x = Input(UInt(width.W)) 48 | val arg_y = Input(UInt(width.W)) 49 | val alu_out = Output(UInt(width.W)) 50 | } 51 | 52 | println((new chisel3.stage.ChiselStage).emitVerilog(new ALU(32))) 53 | println((new chisel3.stage.ChiselStage).emitVerilog(new ALU(64))) -------------------------------------------------------------------------------- /Example_code/Lab3/Immediate_using_switch.scala: -------------------------------------------------------------------------------- 1 | \\immediate using switch 2 | class ImmdValGen extends Module { 3 | val io = IO(new LM_IO_Interface) 4 | 5 | io.immd_se := 0.U 6 | 7 | val opcode = io.instr(6,0) 8 | switch(opcode) { 9 | is("b0010011".U) { //I-type arithematic 10 | val immd = io.instr(31,20) 11 | io.immd_se := Cat(Fill(20,immd(11)),immd) 12 | } 13 | is("b0000011".U) { //I-type Load 14 | val immd = io.instr(31,20) 15 | io.immd_se := Cat(Fill(20,immd(11)),immd) 16 | } 17 | is("b1100111".U) { //I-type JALR 18 | val immd = io.instr(31,20) 19 | io.immd_se := Cat(Fill(20,immd(11)),immd) 20 | } 21 | is("b0100011".U) { //S-type 22 | val immd = Cat(io.instr(31,25),io.instr(11,7)) 23 | io.immd_se := Cat(Fill(20,immd(11)),immd) 24 | } 25 | is("b1100011".U) { //B-type 26 | val immd = Cat(io.instr(31),io.instr(7),io.instr(30,25),io.instr(11,8)) 27 | io.immd_se := Cat(Fill(19,immd(11)),immd, 0.U) 28 | } 29 | is("b1101111".U) { //J-type 30 | val immd = Cat(io.instr(31),io.instr(19,12),io.instr(20),io.instr(30,25),io.instr(24,21)) 31 | io.immd_se := Cat(Fill(11,immd(19)),immd, 0.U) 32 | } 33 | is("b0110111".U) { //U-type lui 34 | val immd = Cat(io.instr(31,12)) 35 | io.immd_se := Cat(immd, Fill(12,0.U)) 36 | } 37 | is("b0010111".U) { //U-type auipc 38 | val immd = Cat(io.instr(31,12)) 39 | io.immd_se := Cat(immd, Fill(12,0.U)) 40 | } 41 | } 42 | } 43 | 44 | class LM_IO_Interface extends Bundle { 45 | val instr = Input(UInt(32.W)) 46 | val immd_se = Output(UInt(32.W)) 47 | } 48 | -------------------------------------------------------------------------------- /Example_code/Lab7/FSM_FR.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | import chisel3.iotesters.{ChiselFlatSpec,Driver,PeekPokeTester} 4 | 5 | class SimpleFsm extends Module { 6 | val io = IO(new Bundle { 7 | val forward1 = Input (Bool()) 8 | val forward2 = Input (Bool()) 9 | val reverse1 = Input (Bool()) 10 | val reverse2 = Input (Bool()) 11 | val out = Output (UInt()) 12 | }) 13 | 14 | io. out := 0.U 15 | 16 | // The six states 17 | val s0 :: s1 :: s2 :: s3 :: s4 :: s5 :: Nil = Enum (6) 18 | 19 | // The state register 20 | val stateReg = RegInit (s0) 21 | 22 | // Next state logic 23 | switch ( stateReg ) { 24 | is (s0) { 25 | when(io.forward1) {stateReg := s1} 26 | .elsewhen(io.forward2) {stateReg := s5} 27 | .otherwise {stateReg := s0} 28 | } 29 | 30 | is ( s1 ) { 31 | when(io.forward1) {stateReg := s2} 32 | .elsewhen(io.reverse1) {stateReg := s0} 33 | .otherwise {stateReg := s1} 34 | } 35 | 36 | is ( s2 ) { 37 | when(io.forward1) {stateReg := s3} 38 | .elsewhen(io.reverse1) {stateReg := s1} 39 | .otherwise {stateReg := s2} 40 | } 41 | 42 | is ( s3 ) { 43 | stateReg := s0 44 | } 45 | 46 | is ( s4 ) { 47 | when(io.forward2) {stateReg := s3} 48 | .elsewhen(io.reverse2) {stateReg := s5} 49 | .otherwise {stateReg := s4} 50 | } 51 | 52 | is ( s5 ) { 53 | when(io.forward2) {stateReg := s4} 54 | .elsewhen(io.reverse2) {stateReg := s0} 55 | .otherwise {stateReg := s5} 56 | } 57 | } 58 | // Output logic 59 | io. out := Mux(stateReg===s2, 3.U, Mux(stateReg===s4, 7.U, 0.U)) 60 | } 61 | 62 | println(chisel3.Driver.emitVerilog(new SimpleFsm)) 63 | -------------------------------------------------------------------------------- /Example_code/Lab9/control_table.scala: -------------------------------------------------------------------------------- 1 | object Control { 2 | 3 | 4 | val default = 5 | // kill wb_en illegal? en_rs2 6 | // pc_sel A_sel B_sel imm_sel alu_op br_type | st_type ld_type wb_sel | csr_cmd | en_rs1 | 7 | // | | | | | | | | | | | | | | | 8 | List(PC_4, A_XXX, B_XXX, IMM_X, ALU_XXX , BR_XXX, N, ST_XXX, LD_XXX, WB_ALU, N, CSR.Z, Y, N, N) 9 | val map = Array( 10 | LUI -> List(PC_4 , A_PC, B_IMM, IMM_U, ALU_COPY_B, BR_XXX, N, ST_XXX, LD_XXX, WB_ALU, Y, CSR.Z, N, N, N), 11 | AUIPC -> List(PC_4 , A_PC, B_IMM, IMM_U, ALU_ADD , BR_XXX, N, ST_XXX, LD_XXX, WB_ALU, Y, CSR.Z, N, N, N), 12 | JAL -> List(PC_ALU, A_PC, B_IMM, IMM_J, ALU_ADD , BR_XXX, Y, ST_XXX, LD_XXX, WB_PC4, Y, CSR.Z, N, N, N), 13 | JALR -> List(PC_ALU, A_RS1, B_IMM, IMM_I, ALU_ADD , BR_XXX, Y, ST_XXX, LD_XXX, WB_PC4, Y, CSR.Z, N, Y, N), 14 | 15 | BEQ -> List(PC_4 , A_PC, B_IMM, IMM_B, ALU_ADD , BR_EQ , N, ST_XXX, LD_XXX, WB_ALU, N, CSR.Z, N, Y, Y), 16 | BNE -> List(PC_4 , A_PC, B_IMM, IMM_B, ALU_ADD , BR_NE , N, ST_XXX, LD_XXX, WB_ALU, N, CSR.Z, N, Y, Y), 17 | BLT -> List(PC_4 , A_PC, B_IMM, IMM_B, ALU_ADD , BR_LT , N, ST_XXX, LD_XXX, WB_ALU, N, CSR.Z, N, Y, Y), 18 | BGE -> List(PC_4 , A_PC, B_IMM, IMM_B, ALU_ADD , BR_GE , N, ST_XXX, LD_XXX, WB_ALU, N, CSR.Z, N, Y, Y), 19 | BLTU -> List(PC_4 , A_PC, B_IMM, IMM_B, ALU_ADD , BR_LTU, N, ST_XXX, LD_XXX, WB_ALU, N, CSR.Z, N, Y, Y), 20 | BGEU -> List(PC_4 , A_PC, B_IMM, IMM_B, ALU_ADD , BR_GEU, N, ST_XXX, LD_XXX, WB_ALU, N, CSR.Z, N, Y, Y), -------------------------------------------------------------------------------- /Example_code/Lab4/aluTest_body.scala: -------------------------------------------------------------------------------- 1 | package LM_Chisel 2 | 3 | import chisel3._ 4 | import chisel3.util 5 | import chisel3.iotesters.{Driver, PeekPokeTester} 6 | import scala.util.Random 7 | import ALUOP._ 8 | 9 | class TestALU(c: ALU) extends PeekPokeTester(c) { 10 | // ALU operations 11 | val array_op = Array(ALU_ADD , ALU_SUB, ALU_AND, ALU_OR, ALU_XOR,ALU_SLT, ALU_SLL, ALU_SLTU, ALU_SRL, ALU_SRA, ALU_COPY_A, ALU_COPY_B, ALU_XXX) 12 | 13 | for (i <- 0 until 100) { 14 | val src_a = Random.nextLong()& 0xFFFFFFFFL 15 | val src_b = Random.nextLong()& 0xFFFFFFFFL 16 | val opr = Random.nextInt(12) 17 | val aluop = array_op(opr) 18 | 19 | // ALU functional implementation using Scala match 20 | val result = aluop match { 21 | case ALU_ADD => src_a + src_b 22 | case ALU_SUB => src_a - src_b 23 | case ALU_AND => src_a & src_b 24 | case ALU_OR => src_a | src_b 25 | case ALU_XOR => src_a ^ src_b 26 | case ALU_SLT => (src_a.toInt < src_b.toInt).toInt 27 | case ALU_SLL => src_a << (src_b & 0x1F) 28 | case ALU_SLTU => (src_a < src_b).toInt 29 | case ALU_SRL => src_a >> (src_b & 0x1F) 30 | case ALU_SRA => src_a.toInt >> (src_b & 0x1F) 31 | case ALU_COPY_A => src_a 32 | case ALU_COPY_B => src_b 33 | case _ => 0 34 | } 35 | 36 | val result1: BigInt = if (result < 0) 37 | (BigInt(0xFFFFFFFFL)+result+1) & 0xFFFFFFFFL 38 | else result & 0xFFFFFFFFL 39 | 40 | poke(c.io.in_A, src_a.U) 41 | poke(c.io.in_B, src_b.U) 42 | poke(c.io.alu_Op, aluop) 43 | step(1) 44 | expect(c.io.out, result1.asUInt) 45 | } 46 | step(2) 47 | } 48 | 49 | // object for tester class 50 | object ALU_Main extends App { 51 | iotesters.Driver.execute(Array("--is-verbose", "--generate-vcd-output", "on", "--backend-name", "firrtl"), () => new ALU) {c => new TestALU(c)} 52 | } -------------------------------------------------------------------------------- /Example_code/Lab7/FSM_Manchester.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester} 4 | import chisel3.experimental.ChiselEnum 5 | import chisel3.experimental.{withClock, withReset, withClockAndReset} 6 | import chisel3.experimental.BundleLiterals._ 7 | 8 | object Manchester_Encoding{ 9 | object State extends ChiselEnum { 10 | val sNone, sRead, sWait, sDecode = Value 11 | } 12 | } 13 | 14 | class Manchester_Encoding extends Module { 15 | import Manchester_Encoding.State 16 | import Manchester_Encoding.State._ 17 | val io = IO(new Bundle { 18 | val in = Input(UInt(1.W)) 19 | val start = Input(Bool()) 20 | //val alternateReset = Input(Bool()) 21 | //val alternateClock = Input(Clock()) 22 | val out = Output(UInt(8.W)) 23 | val flag = Output(UInt(1.W)) 24 | }) 25 | val state = RegInit(sNone) 26 | val data_in = RegInit(UInt(8.W), 0.U) 27 | val data_next = (data_in << 1) | io.in 28 | val count = RegInit(0.U(4.U)) 29 | 30 | when(state === sWait){ 31 | io.flag:= 1.U } 32 | .otherwise{ 33 | io.flag:= 0.U } 34 | 35 | 36 | io.out := data_in 37 | 38 | switch (state) { 39 | is (sNone) { 40 | when (io.start) { 41 | state:=sRead 42 | }.otherwise{ 43 | state:=sNone 44 | } 45 | } 46 | is (sRead) { 47 | when (count<8.U) { 48 | data_in := data_next 49 | count := count + 1.U 50 | state:=sWait 51 | }.otherwise { 52 | count:=0.U 53 | state:=sDecode 54 | } 55 | } 56 | is (sWait) { 57 | state:=sRead 58 | } 59 | is (sDecode) 60 | { 61 | 62 | state:=sDecode 63 | } 64 | } 65 | 66 | } 67 | //println(getVerilog(new Manchester_Encoding)) 68 | 69 | 70 | -------------------------------------------------------------------------------- /Example_code/Lab4/aluTest.scala: -------------------------------------------------------------------------------- 1 | package LM_Chisel 2 | 3 | import chisel3._ 4 | import chisel3.iotesters.{Driver, PeekPokeTester} 5 | import chisel3.util 6 | import scala.util.Random 7 | 8 | import ALUOP._ 9 | 10 | class TestALU(c: ALU) extends PeekPokeTester(c) { 11 | // ALU operations 12 | val array_op = Array(ALU_ADD , ALU_SUB, ALU_AND, ALU_OR, ALU_XOR, ALU_SLT, ALU_SLL, ALU_SLTU, ALU_SRL, ALU_SRA, ALU_COPY_A, ALU_COPY_B, ALU_XXX) 13 | 14 | for (i <- 0 until 102) { 15 | 16 | val src_a = Random.nextLong()& 0xFFFFFFFFL 17 | val src_b = Random.nextLong()& 0xFFFFFFFFL 18 | val opr = Random.nextInt(12) 19 | val aluop = array_op(opr) 20 | 21 | // ALU functional implementation using Scala match 22 | val result = aluop match { 23 | case ALU_ADD => src_a + src_b 24 | case ALU_SUB => src_a - src_b 25 | case ALU_AND => src_a & src_b 26 | case ALU_OR => src_a | src_b 27 | case ALU_XOR => src_a ^ src_b 28 | case ALU_SLT => (src_a.toInt < src_b.toInt).toInt 29 | case ALU_SLL => src_a << (src_b & 0x1F) 30 | case ALU_SLTU => (src_a < src_b).toInt 31 | case ALU_SRL => src_a >> (src_b & 0x1F) 32 | case ALU_SRA => src_a.toInt >> (src_b & 0x1F) 33 | case ALU_COPY_A => src_a 34 | case ALU_COPY_B => src_b 35 | case _ => 0 36 | } 37 | 38 | val result1: BigInt = if (result < 0) 39 | (BigInt(0xFFFFFFFF)+result+1) & 0xFFFFFFFFL 40 | else result & 0xFFFFFFFFL 41 | 42 | poke(c.io.in_A, src_a.U) 43 | poke(c.io.in_B, src_b.U) 44 | poke(c.io.alu_Op, aluop) 45 | step(1) 46 | expect(c.io.out, result1.asUInt) 47 | } 48 | step(1) 49 | step(1) 50 | } 51 | 52 | // object for tester class 53 | object ALU_Main extends App { 54 | iotesters.Driver.execute(Array("--is-verbose", "--generate-vcd-output", 55 | "on", "--backend-name", "firrtl"), () => new ALU) { 56 | c => new TestALU(c) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Example_code/Lab7/UARTTx_chisel3.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3 . stage . ChiselStage 3 | import chisel3.util._ 4 | 5 | case class UART_Params( 6 | dataBits: Int = 8, 7 | stopBits: Int = 2, 8 | divisorBits: Int = 5, 9 | oversample: Int = 2, 10 | nSamples: Int = 3, 11 | nTxEntries: Int = 4, 12 | nRxEntries: Int = 4) { 13 | def oversampleFactor = 1 << oversample 14 | require(divisorBits > oversample) 15 | require(oversampleFactor > nSamples) 16 | } 17 | 18 | class UART_Tx(c: UART_Params) extends Module { 19 | val io = IO(new Bundle { 20 | val en = Input(Bool()) 21 | val in = Flipped(Decoupled(UInt((c.dataBits).W))) 22 | val out = Output(Bool()) 23 | val div = Input(UInt((c.divisorBits).W)) 24 | val nstop = Input(UInt((c.stopBits).W)) 25 | }) 26 | // pulses generated at baud rate using prescaler 27 | val prescaler = RegInit(0.U((c.divisorBits).W)) 28 | val pulse = (prescaler === 0.U) 29 | private val n = c.dataBits + 1 30 | 31 | val counter = RegInit(0.U((log2Floor(n + c.stopBits)+1).W)) 32 | val shifter = Reg(UInt(n.W)) 33 | val out = RegInit(true.B) 34 | io.out := out 35 | 36 | val busy = (counter =/= 0.U) 37 | val state1 = io.en && !busy 38 | val state2 = busy 39 | io.in.ready := state1 40 | 41 | when(state1) { 42 | shifter := Cat(io.in.bits, false.B) 43 | counter := Mux1H( 44 | (0 until c.stopBits).map(i => (io.nstop === i.U) -> (n+i+2).U) 45 | ) 46 | } 47 | 48 | when(state2) { 49 | prescaler := Mux(pulse, (io.div - 1.U), prescaler - 1.U) 50 | 51 | when(pulse) { 52 | counter := counter - (1.U) 53 | shifter := Cat(true.B, shifter >> 1) 54 | out := shifter(0) 55 | } 56 | } 57 | } 58 | 59 | // Instantiation of the UART_Tx module for Verilog generator 60 | object UART_Tx_generate extends App { 61 | val param = UART_Params() 62 | chisel3.Driver.execute(args, () => new UART_Tx(param)) 63 | } 64 | 65 | 66 | -------------------------------------------------------------------------------- /Example_code/Lab12/startup.s: -------------------------------------------------------------------------------- 1 | .equ CSR_MSTATUS, 0x300 2 | .equ MSTATUS_MIE, 0x00000008 3 | .equ CSR_MTVEC, 0x305 4 | 5 | # Main interrupt vector table entries 6 | .global vtable 7 | .type vtable, %object 8 | .section .text.vector_table,"a",%progbits 9 | 10 | # this entry is to align reset_handler at address 0x04 11 | .word 0x00000013 12 | j reset_handler 13 | .align 2 14 | vtable: 15 | j default_interrupt_handler 16 | .word 0 17 | .word 0 18 | j msip_handler 19 | .word 0 20 | .word 0 21 | .word 0 22 | j mtip_handler 23 | .word 0 24 | .word 0 25 | .word 0 26 | .word 0 27 | .word 0 28 | .word 0 29 | .word 0 30 | .word 0 31 | j user_handler 32 | .word 0 33 | .word 0 34 | 35 | # Weak aliases to point each exception handler to the 36 | # 'default_interrupt_handler', unless the application defines 37 | # a function with the same name to override the reference. 38 | 39 | .weak msip_handler 40 | .set msip_handler, default_interrupt_handler 41 | .weak mtip_handler 42 | .set mtip_handler, default_interrupt_handler 43 | .weak user_handler 44 | .set user_handler, default_interrupt_handler 45 | 46 | # Assembly 'reset handler' function to initialize core CPU registers. 47 | .section .text.default_interrupt_handler,"ax",%progbits 48 | 49 | .global reset_handler 50 | .type reset_handler,@function 51 | 52 | reset_handler: 53 | # Set mstatus bit MIE = 1 (enable M mode interrupts) 54 | li t0, 8 55 | csrrs zero, CSR_MSTATUS, t0 56 | 57 | # Load the initial stack pointer value. 58 | la sp, _sp 59 | 60 | # Set the vector table's base address. 61 | la a0, vtable 62 | addi a0, a0, 1 63 | csrw CSR_MTVEC, a0 64 | 65 | # Call user 'main(0,0)' (.data/.bss sections initialized there) 66 | li a0, 0 67 | li a1, 0 68 | call main 69 | 70 | # A 'default' handler, in case an interrupt triggers without its handler defined 71 | default_interrupt_handler: 72 | j default_interrupt_handler -------------------------------------------------------------------------------- /Example_code/Lab5/rocket_alu.scala: -------------------------------------------------------------------------------- 1 | class ALU(implicit p: Parameters) extends CoreModule()(p) { 2 | val io = new Bundle { 3 | val dw = Bits(INPUT, SZ_DW) 4 | val fn = Bits(INPUT, SZ_ALU_FN) 5 | val in2 = UInt(INPUT, xLen) // xLen is an implicit parameter 6 | val in1 = UInt(INPUT, xLen) 7 | val out = UInt(OUTPUT, xLen) 8 | val adder_out = UInt(OUTPUT, xLen) 9 | val cmp_out = Bool(OUTPUT) 10 | } 11 | 12 | // ADD, SUB 13 | val in2_inv = Mux(isSub(io.fn), ~io.in2, io.in2) 14 | val in1_xor_in2 = io.in1 ^ in2_inv 15 | io.adder_out := io.in1 + in2_inv + isSub(io.fn) 16 | 17 | // SLT, SLTU 18 | val slt = 19 | Mux(io.in1(xLen-1) === io.in2(xLen-1), io.adder_out(xLen-1), 20 | Mux(cmpUnsigned(io.fn), io.in2(xLen-1), io.in1(xLen-1))) 21 | io.cmp_out := cmpInverted(io.fn) ^ Mux(cmpEq(io.fn), in1_xor_in2 === UInt(0), slt) 22 | 23 | // SLL, SRL, SRA 24 | val (shamt, shin_r) = 25 | if (xLen == 32) (io.in2(4,0), io.in1) 26 | else { 27 | require(xLen == 64) 28 | val shin_hi_32 = Fill(32, isSub(io.fn) && io.in1(31)) 29 | val shin_hi = Mux(io.dw === DW_64, io.in1(63,32), shin_hi_32) 30 | val shamt = Cat(io.in2(5) & (io.dw === DW_64), io.in2(4,0)) 31 | (shamt, Cat(shin_hi, io.in1(31,0))) 32 | } 33 | val shin = Mux(io.fn === FN_SR || io.fn === FN_SRA, shin_r, Reverse(shin_r)) 34 | val shout_r = (Cat(isSub(io.fn) & shin(xLen-1), shin).asSInt >> shamt)(xLen-1,0) 35 | val shout_l = Reverse(shout_r) 36 | val shout = Mux(io.fn === FN_SR || io.fn === FN_SRA, shout_r, UInt(0)) | 37 | Mux(io.fn === FN_SL, shout_l, UInt(0)) 38 | 39 | // AND, OR, XOR 40 | val logic = Mux(io.fn === FN_XOR || io.fn === FN_OR, in1_xor_in2, UInt(0)) | 41 | Mux(io.fn === FN_OR || io.fn === FN_AND, io.in1 & io.in2, UInt(0)) 42 | val shift_logic = (isCmp(io.fn) && slt) | logic | shout 43 | val out = Mux(io.fn === FN_ADD || io.fn === FN_SUB, io.adder_out, shift_logic) 44 | 45 | io.out := out 46 | if (xLen > 32) { 47 | require(xLen == 64) 48 | when (io.dw === DW_32) { io.out := Cat(Fill(32, out(31)), out(31,0)) } 49 | } 50 | } -------------------------------------------------------------------------------- /Example_code/Lab3/Mux_Based_Alu.scala: -------------------------------------------------------------------------------- 1 | //mux based ALU example 2 | import ALUOP._ 3 | 4 | trait Config { 5 | // global config parameters 6 | val WLEN = 32 7 | val XLEN = 32 8 | 9 | // control signal's width 10 | val ALU_SRC_SIG_LEN = 1 11 | val ALUOP_SIG_LEN = 4 12 | 13 | 14 | } 15 | object ALUOP { 16 | // ALU Operations, may expand/modify in future 17 | val ALU_ADD = 0 // 18 | val ALU_SUB = 1 // 19 | val ALU_AND = 2 // 20 | val ALU_OR = 3 // 21 | val ALU_XOR = 4 // 22 | val ALU_SLT = 5 // 23 | val ALU_SLL = 6 // 24 | val ALU_SLTU = 7 // 25 | val ALU_SRL = 8 // 26 | val ALU_SRA = 9 // 27 | val ALU_COPY_A = 10 // 28 | val ALU_COPY_B = 11 // 29 | val ALU_XXX = 15 // 30 | } 31 | 32 | class ALUio extends Bundle with Config { 33 | val in_A = Input(UInt(WLEN.W)) 34 | val in_B = Input(UInt(WLEN.W)) 35 | val alu_Op = Input(UInt(ALUOP_SIG_LEN.W)) 36 | val out = Output(UInt(WLEN.W)) 37 | val sum = Output(UInt(WLEN.W)) 38 | } 39 | 40 | class ALU extends Module with Config { 41 | val io = IO(new ALUio) 42 | 43 | val sum = io.in_A + Mux(io.alu_Op(0), -io.in_B, io.in_B) 44 | val cmp = Mux(io.in_A (XLEN-1) === io.in_B(XLEN-1), sum(XLEN-1), 45 | Mux(io.alu_Op(1), io.in_B(XLEN-1), io.in_A(XLEN-1))) 46 | val shamt = io.in_B(4,0).asUInt 47 | val shin = Mux(io.alu_Op(3), io.in_A, Reverse(io.in_A)) 48 | val shiftr = (Cat(io.alu_Op(0) && shin(XLEN-1), shin).asSInt >> shamt)(XLEN-1, 0) 49 | val shiftl = Reverse(shiftr) 50 | 51 | val out = 52 | Mux(io.alu_Op === ALU_ADD.U || io.alu_Op === ALU_SUB.U, sum, 53 | Mux(io.alu_Op === ALU_SLT.U || io.alu_Op === ALU_SLTU.U, cmp, 54 | Mux(io.alu_Op === ALU_SRA.U || io.alu_Op === ALU_SRL.U, shiftr, 55 | Mux(io.alu_Op === ALU_SLL.U, shiftl, 56 | Mux(io.alu_Op === ALU_AND.U, (io.in_A & io.in_B), 57 | Mux(io.alu_Op === ALU_OR.U, (io.in_A | io.in_B), 58 | Mux(io.alu_Op === ALU_XOR.U, (io.in_A ^ io.in_B), 59 | Mux(io.alu_Op === ALU_COPY_A.U, io.in_A, 60 | Mux(io.alu_Op === ALU_COPY_A.U, io.in_B, 0.U))))))))) 61 | 62 | io.out := out 63 | io.sum := sum 64 | } 65 | -------------------------------------------------------------------------------- /Example_code/Lab5/ALU_Tester_64.scala: -------------------------------------------------------------------------------- 1 | import chisel3.UInt 2 | import chisel3._ 3 | import chisel3.iotesters 4 | import chisel3.iotesters.{Driver, PeekPokeTester} 5 | import chisel3.util 6 | import org.scalatest.{FlatSpec, Matchers} 7 | import scala.util.Random 8 | 9 | //import ALUOP._ 10 | //import Extension._ 11 | class TestALU(c: myALU) extends PeekPokeTester(c) { 12 | 13 | // ALU operations 14 | val array_op = Array(ALU_ADD , ALU_SUB, ALU_AND, ALU_OR, ALU_XOR, ALU_SLT, ALU_SLL, ALU_SLTU, ALU_SRL, ALU_SRA, ALU_COPY_A, ALU_COPY_B, ALU_XXX) 15 | 16 | 17 | for (i <- 0 until 50) { 18 | val src_a = Random.nextLong()& 9223372036854775807L 19 | val src_b = Random.nextLong()& 9223372036854775807L 20 | val opr = Random.nextInt(12) 21 | val aluop = array_op(opr) 22 | 23 | // ALU functional implementation using Scala match 24 | val result = aluop match { 25 | case ALU_ADD => src_a + src_b 26 | case ALU_SUB => src_a - src_b 27 | case ALU_AND => src_a & src_b 28 | case ALU_OR => src_a | src_b 29 | case ALU_XOR => src_a ^ src_b 30 | case ALU_SLT => (src_a < src_b).toLong 31 | case ALU_SLL => src_a << (src_b & 0x1F) 32 | case ALU_SLTU => (src_a < src_b).toLong 33 | case ALU_SRL => src_a >> (src_b & 0x1F) 34 | case ALU_SRA => src_a >> (src_b & 0x1F) 35 | case ALU_COPY_A => src_a 36 | case ALU_COPY_B => src_b 37 | case _ => 0 38 | } 39 | 40 | val inter : BigInt = BigInt(9223372036854775807L) +BigInt(9223372036854775807L) +BigInt(1) 41 | val result1: BigInt = if (result < 0) (inter+result+1)& 42 | 0xFFFFFFFFFFFFFFFFL 43 | else result & 0xFFFFFFFFFFFFFFFFL 44 | println(s"This is the result ${result.toLong.toHexString} and this is result1 ${result1.toLong.toHexString}") 45 | poke(c.io.in_A, src_a.U) 46 | poke(c.io.in_B, src_b.U) 47 | poke(c.io.alu_Op, aluop) 48 | step(1) 49 | expect(c.io.out, result1.asUInt) 50 | } 51 | step(1) 52 | step(1) 53 | } 54 | 55 | // object for tester class 56 | 57 | 58 | iotesters.Driver.execute(Array("--is-verbose", "--generate-vcd-output", 59 | "on", "--backend-name", "firrtl"), () => new myALU) { 60 | c => new TestALU(c)} 61 | -------------------------------------------------------------------------------- /Example_code/Lab4/ALU.scala: -------------------------------------------------------------------------------- 1 | 2 | package LM_Chisel 3 | 4 | import chisel3._ 5 | import chisel3.util._ 6 | import ALUOP._ 7 | 8 | trait Config { 9 | // global config parameters 10 | val WLEN = 32 11 | val XLEN = 32 12 | 13 | // control signal's width 14 | val ALU_SRC_SIG_LEN = 1 15 | val ALUOP_SIG_LEN = 4 16 | } 17 | 18 | object ALUOP { 19 | // ALU Operations, may expand/modify in future 20 | val ALU_ADD = 0.U(4.W) 21 | val ALU_SUB = 1.U(4.W) 22 | val ALU_AND = 2.U(4.W) 23 | val ALU_OR = 3.U(4.W) 24 | val ALU_XOR = 4.U(4.W) 25 | val ALU_SLT = 5.U(4.W) 26 | val ALU_SLL = 6.U(4.W) 27 | val ALU_SLTU = 7.U(4.W) 28 | val ALU_SRL = 8.U(4.W) 29 | val ALU_SRA = 9.U(4.W) 30 | val ALU_COPY_A = 10.U(4.W) 31 | val ALU_COPY_B = 11.U(4.W) 32 | val ALU_XXX = 15.U(4.W) 33 | } 34 | 35 | class ALUio extends Bundle with Config { 36 | val in_A = Input(UInt(WLEN.W)) 37 | val in_B = Input(UInt(WLEN.W)) 38 | val alu_Op = Input(UInt(ALUOP_SIG_LEN.W)) 39 | val out = Output(UInt(WLEN.W)) 40 | val sum = Output(UInt(WLEN.W)) 41 | } 42 | 43 | class ALU extends Module with Config { 44 | val io = IO(new ALUio) 45 | 46 | val sum = io.in_A + Mux(io.alu_Op(0), -io.in_B, io.in_B) 47 | val cmp = Mux(io.in_A (XLEN-1) === io.in_B(XLEN-1), sum(XLEN-1), 48 | Mux(io.alu_Op(1), io.in_B(XLEN-1), io.in_A(XLEN-1))) 49 | val shamt = io.in_B(4,0).asUInt 50 | val shin = Mux(io.alu_Op(3), io.in_A, Reverse(io.in_A)) 51 | val shiftr = (Cat(io.alu_Op(0) && shin(XLEN-1), shin).asSInt >> shamt)(XLEN-1, 0) 52 | val shiftl = Reverse(shiftr) 53 | 54 | val out = 55 | Mux(io.alu_Op === ALU_ADD || io.alu_Op === ALU_SUB, sum, 56 | Mux(io.alu_Op === ALU_SLT || io.alu_Op === ALU_SLTU, cmp, 57 | Mux(io.alu_Op === ALU_SRA || io.alu_Op === ALU_SRL, shiftr, 58 | Mux(io.alu_Op === ALU_SLL, shiftl, 59 | Mux(io.alu_Op === ALU_AND, (io.in_A & io.in_B), 60 | Mux(io.alu_Op === ALU_OR, (io.in_A | io.in_B), 61 | Mux(io.alu_Op === ALU_XOR, (io.in_A ^ io.in_B), 62 | Mux(io.alu_Op === ALU_COPY_A, io.in_A, io.in_B)))))))) 63 | 64 | io.out := out 65 | io.sum := sum 66 | } 67 | 68 | object ALU_generate extends App { 69 | chisel3.Driver.execute(args, () => new ALU) 70 | } 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Chisel-Training 2 | 3 | ### Overview 4 | This course is aimed for both practitioners as well as academics involved in Digital Design. Chisel (Constructing Hardware in a Scala Embedded Language) is an open-source hardware construction language (HCL) used to generate digital circuits at the register-transfer level. The object-oriented as well as functional programming aspects of Scala are inherited in Chisel for digital hardware generation. Digital circuits described in Chisel are translated to equivalent Verilog for synthesis as well as simulation. 5 | 6 | After completing this course, the reader will be able to program for modular hardware generation that can be parameterized. Specifically, the reader will be able to synthesize combinational and sequential circuits, implement state machine, develop data-paths and controllers for different processor architectures, though the focus of this course will be on RISC V architecture. 7 | Below is the list of topics that are covered. 8 | 9 | - Introduction to Chisel (chisel3) and Scala 10 | - Combinational circuits, Control flow, Testing in Chisel 11 | - Parameterization 12 | - Sequential circuits, Finite state machines, Memories 13 | 14 | - Collections in Scala, Scala I, Scala II 15 | - Project 16 | - Scala III, Scala IV 17 | - Diplomacy & TileLink in RocketChip 18 | 19 | The topics 1 to 4 cover different Chisel constructs that are used for hardware construction. The topics 5 and 7 selectively introduce Scala components that enable parameterized hardware generation. The proposed project is aimed to employ both Chisel as well as Scala to develop parameterized hardware modules allowing reusability. The examples and use cases are drawn from rocketchip core generators. 20 | 21 | 22 | [Chisel Programming Manual](Lab_Manual/Chisel_Lab_manual.pdf) 23 | 24 | ### Chisel Programming Slides 25 | 26 | [Introduction](Lecture_slides/Introduction.pdf) 27 | 28 | [Combinational circuits](Lecture_slides/combinational.pdf) 29 | 30 | [Control flow](Lecture_slides/control_combinational.pdf) 31 | 32 | [Testing in Chisel](Lecture_slides/Chisel_testers.pdf) 33 | 34 | [Parameterization](Lecture_slides/parameterization.pdf) 35 | 36 | [Sequential circuits](Lecture_slides/sequential.pdf) 37 | 38 | [Finite state machines](Lecture_slides/fsm.pdf) 39 | 40 | [Memories](Lecture_slides/memory.pdf) 41 | 42 | [Collections in Scala](Lecture_slides/Scala_collections.pdf) 43 | 44 | [Scala I](Lecture_slides/scala1.pdf) 45 | 46 | [Scala II](Lecture_slides/Scala2.pdf) 47 | 48 | [Project](Lecture_slides/Project.pdf) 49 | 50 | [Scala III](Lecture_slides/scala3.pdf) 51 | 52 | [Scala IV](Lecture_slides/scala4.pdf) 53 | 54 | [Diplomacy & TileLink](Lecture_slides/tilelink_diplomacy.pdf) 55 | 56 | -------------------------------------------------------------------------------- /Example_code/Lab16/lm_tilelink3.scala: -------------------------------------------------------------------------------- 1 | package LM_diplomacy_TL 2 | 3 | import Chisel.Decoupled 4 | import chisel3._ 5 | import freechips.rocketchip.config.Parameters 6 | import freechips.rocketchip.diplomacy._ 7 | import freechips.rocketchip.tilelink._ 8 | import testchipip.TLHelper 9 | 10 | class MemReq extends Bundle { 11 | val data = UInt(64.W) 12 | val addr = UInt(64.W) 13 | val wen = Bool() 14 | val mask = UInt(8.W) 15 | } 16 | class MemResp extends Bundle { 17 | val data = UInt(64.W) 18 | //val addr = Input(UInt(64.W)) 19 | } 20 | 21 | class MyClient(implicit p: Parameters) extends LazyModule { 22 | val node = TLHelper.makeClientNode("my-client1", IdRange(0, 1)) 23 | 24 | lazy val module = new LazyModuleImp(this) { 25 | val io = IO(new Bundle{ 26 | val req = Flipped(Decoupled(new MemReq)) 27 | val resp = Decoupled(new MemResp) 28 | }) 29 | val (tl_out, edge) = node.out.head 30 | val deq_ready = RegNext(~io.req.fire()) 31 | io.req.ready := deq_ready 32 | when(io.req.fire()){ 33 | tl_out.a.valid := tl_out.a.ready 34 | 35 | when(io.req.bits.wen) { 36 | tl_out.a.bits := edge.Put(0.U,io.req.bits.addr,2.U,io.req.bits.data,io.req.bits.mask)._2 37 | } .otherwise { 38 | tl_out.a.bits := edge.Get(0.U, io.req.bits.addr, 2.U)._2 39 | } 40 | } .otherwise { 41 | tl_out.a.valid := false.B 42 | } 43 | 44 | 45 | val tl_d_ready = RegNext(~tl_out.d.fire()) 46 | tl_out.d.ready := tl_d_ready 47 | io.resp.bits.data := tl_out.d.bits.data 48 | when(tl_out.d.fire()) { 49 | io.resp.valid := (tl_out.d.bits.opcode === 1.U & io.resp.ready) 50 | }.otherwise { 51 | io.resp.valid := false.B 52 | } 53 | 54 | tl_out.c.valid := false.B 55 | tl_out.e.valid := false.B 56 | tl_out.b.ready := true.B 57 | } 58 | } 59 | 60 | 61 | class MyManager(beatBytes: Int)(implicit p: Parameters) extends LazyModule { 62 | val device = new SimpleDevice("my-device", Seq("tutorial,my-device0")) 63 | //val beatBytes = 8 64 | val node = TLHelper.makeManagerNode(beatBytes, TLManagerParameters( 65 | address = Seq(AddressSet(0x0000, 0xfff)), 66 | resources = device.reg, 67 | regionType = RegionType.UNCACHED, 68 | executable = true, 69 | supportsArithmetic = TransferSizes(1, beatBytes), 70 | supportsLogical = TransferSizes(1, beatBytes), 71 | supportsGet = TransferSizes(1, beatBytes), 72 | supportsPutFull = TransferSizes(1, beatBytes), 73 | supportsPutPartial = TransferSizes(1, beatBytes), 74 | supportsHint = TransferSizes(1, beatBytes), 75 | fifoId = Some(0))) 76 | 77 | lazy val module = new LazyModuleImp(this) { 78 | val (tl, edge) = node.in.head 79 | val mem = Mem(2048,UInt(32.W)) 80 | 81 | val a_ready = RegNext(~tl.a.fire()) 82 | tl.a.ready := a_ready 83 | 84 | when(tl.a.fire() && tl.a.bits.opcode =/= 4.U){ 85 | mem(tl.a.bits.address) := tl.a.bits.data 86 | } 87 | 88 | when(tl.a.fire() && tl.a.bits.opcode =/= 4.U){ 89 | mem(tl.a.bits.address) := tl.a.bits.data 90 | tl.d.valid := true.B 91 | tl.d.bits := edge.AccessAck(tl.a.bits) 92 | }.elsewhen(tl.a.fire() && tl.a.bits.opcode === 4.U){ 93 | tl.d.valid := tl.d.ready 94 | tl.d.bits := edge.AccessAck(tl.a.bits, mem(tl.a.bits.address)) 95 | }. otherwise{ 96 | tl.d.valid := false.B 97 | } 98 | } 99 | } 100 | 101 | 102 | class MyClientManager(implicit p: Parameters) extends LazyModule { 103 | val client = LazyModule(new MyClient) 104 | val manager = LazyModule(new MyManager(4)) 105 | 106 | manager.node :=* client.node 107 | 108 | lazy val module = new LazyModuleImp(this) { 109 | val io = IO(new Bundle { 110 | val req = Flipped(Decoupled(new MemReq)) 111 | val resp = Decoupled(new MemResp) 112 | }) 113 | io <> client.module.io 114 | } 115 | } 116 | 117 | object lm_tilelink3 extends App{ 118 | val verilog = chisel3.Driver.emitVerilog( 119 | LazyModule(new MyClientManagerComplex3()(Parameters.empty)).module 120 | ) 121 | println(s"```verilog\n$verilog```") 122 | chisel3.Driver.execute(Array("--target-dir", "generated-src", "--split-modules"), () => 123 | LazyModule(new MyClientManagerComplex3()(Parameters.empty)).module 124 | ) 125 | } 126 | --------------------------------------------------------------------------------