首页 > > 详细

代写EECS31L Introduction to Digital Logic Design Lab Winter 2025 Lab 4代写R语言

项目预算:   开发周期:  发布时间:   要求地区:

Introduction to Digital Logic Design Lab

EECS31L

Winter 2025

Lab 4 (100 Points)

Through this course, we want to design a RISC-V Single Cycle Processor.   Here in this Lab, we will work on the Datapath part of the processor.  In Part 1, we again review the RISC-V datapath.  In part 2 we talk about how to design the data memory and in part 3 we talk about designing the datapath and finally in part 4 we test the datapath.

1    Datapath

Figure 1:  RISC-V Datapath.

Figure  1 shows the datapath of a RISC-V single cycle processor.  The instruction execution starts by using the program counter to supply the instruction address to the instruction memory.  After the in- structionis fetched, the register operands used by an instruction are specified by fields of that instruction. Once the register operands have been fetched, they can be operated on to compute a memory address (for a load or store), to compute an arithmetic result (for an integer arithmetic-logical instruction), or an equality check (for a branch).  If the instruction is an arithmetic-logical instruction, the result from the ALU must be written to a register. If the operation is a load or store, the ALU result is used as an address to either store a value from the registers or load a value from memory into the registers.  The result from the ALU or memory is written back into the register file.  The blue lines interconnecting the functional units represent buses, which consist of multiple signals.   The arrows are used to guide the reader in knowing how the information flows.  Since signal lines may cross, we explicitly show when crossing lines are connected by the presence of a dot where the lines cross.

Some of the inputs (RegWrite, ALUSrc, ALUCC, MemRead, MemWrite, MemtoReg) are control signals which are derived by a module named  “Control” .  The control unit will be designed in Lab 5.  Here in this lab, assume you have all the control signals as inputs.

Table 1 shows the list of Instructions that our Datapath supports.

Table 1 : Instruction Set.

Note:  along with the provided  instructions  in Table  1, your datapath needs to support "lw" and  "sw" instructions  too.   Table  2  and  3  show  format  of these  two  data-transfer instructions.

Table 2 : Instruction Set (lw).

Table 3 : Instruction Set (sw).

For this part, you need to save these two instructions into the ”Instruction Memory” that you designed in lab 3.  Add the following two instructions into the instruction memory (as you did in lab 3):

memory[18] = 32’h02b02823; // sw r11, 48(r0) alu result = 32’h00000030

memory[19] = 32’h03002603; // lw r12, 48(r0) alu result = 32’h00000030 , r12 = 32’h00000005

2    Lower Level Modules

As it is shown in Figure 1, there is a top module  (Datapath) and nine lower-level modules  (FlipFlop, Adder, Instr mem, RegFile, Imm Gen, Mux (two instantiations), ALU, data mem).  Eight sub-modules are designed in the previous labs and in this lab, we start by designing the last sub-module which is data mem.

Note:  32-bit ALU design source is provided for you in section 2.2.  You are welcome to use your own design source from Lab 2, if your design source got the full point.

2.1    Data Memory

Same as the Instruction Memory (refer to the previous lab), the Data Memory in our processor is byte addressable. We can store 128 data each with 32 bits (128 x 32).  To address 128 x 4 = 512 bytes, 9 bits are required for address line.  These 9-bits come from the 9 LSBs of the output of the ALU (ALU Result). To read a data, we need an address (addr[8:2] which uses bit 2 to bit 8 from 9-bit addr) and the read enable signal (MemRead). To write a data, we need an address (addr[8:2] which uses bit 2 to bit 8 from 9-bit addr), the write enable signal (MemWrite), and a data to write (write data).

Note:  Use the provided module definition to design your Data Memory.  Otherwise, your submission will not be considered for grading.

Code 1:  Data Memory

1 ‘timescale 1ns / 1ps 2 // Module definition 3 module DataMem ( MemRead , MemWrite , addr , write_data , read_data ); 4 // Define I/O ports 5 6 7 // Describe data_mem behavior. 8 9 10 endmodule // data_mem

2.2    Mux

The MUX on the output of the Data Memory will decide whether the writing data (to the register file) should come from the ALU or come from the Data Memory (refer to Figure 1).  You can use 2-to-1 Mux design from Lab 1. The only diference is that for this datapath, you need to consider size of input data and output data for each 2-to-1 Mux. For example, for the last 2-to-1 Mux in datapath (refer to Figure 1), size of data input is 32 bits. Follow the same rule for the Mux which is before ALU in the datapath.

2.3    32-bit ALU

Code 2:  32-bit ALU

1 module alu_32 ( 2 input [31:0] A_in ,B_in , // ALU 32 bit inputs 3 input [3:0] ALU_Sel , // ALU 4 bits selection 4 output [31:0] ALU_Out , // ALU 32 bits output 5 output reg Carry_Out , 6 output Zero , // 1 bit Zero Flag 7 output reg verflow = 1’b0 // 1 bit Overflow flag 8 ); 9 reg [31:0] ALU_Result ; 10 reg [32:0] temp ; 11 reg [32:0] twos_com ; // to hold 2’sc of second source of ALU 12

13 assign ALU_Out = ALU_Result ; // ALU Out 14 assign Zero = ( ALU_Result == 0); // Zero Flag 15 16 always @ (*) 17 begin 18 verflow = 1’b0; 19 Carry_Out = 1’b0; 20 case ( ALU_Sel ) 21 4’ b0000 : // bit - wise and 22 ALU_Result = A_in & B_in ; 23 24 4’ b0001 : // bit - wise or 25 ALU_Result = A_in | B_in ; 26 27 4’ b0010 : // Signed Addition with Overflow and Carry_out checking 28 begin 29 ALU_Result = $signed ( A_in ) + $signed ( B_in ); 30 temp = {1’b0 , A_in } + {1’b0 , B_in }; 31 Carry_Out = temp [32]; 32 if (( A_in [31] & B_in [31] & ∼ALU_Out [31]) | 33 (∼A_in [31] & ∼B_in [31] & ALU_Out [31])) 34 verflow = 1’b1; 35 else 36 verflow = 1’b0; 37 end 38 39 4’ b0110 : // Signed Subtraction with Overflow checking 40 begin 41 ALU_Result = $signed ( A_in ) - $signed ( B_in ) ; 42 twos_com = ∼( B_in ) + 1’b1; 43 if (( A_in [31] & twos_com [31] & ∼ALU_Out [31]) | 44 (∼A_in [31] & ∼twos_com [31] & ALU_Out [31])) 45 verflow = 1’b1; 46 else 47 verflow = 1’b0; 48 end 49 50 4’ b0111 : // Signed less than comparison 51 ALU_Result = ($signed ( A_in ) < $signed ( B_in ))?32 ’ d1:32’ d0; 52 53 4’ b1100 : // bit - wise nor 54 ALU_Result = ∼( A_in | B_in ); 55 56 4’ b1111 : // Equal comparison 57 ALU_Result = ( A_in == B_in )?32 ’ d1:32’ d0 ; 58 59 default : ALU_Result = A_in + B_in ; 60 endcase 61 end 62 63 endmodule

2.4    Adder

You can directly use the addition operator in Verilog ‘+ ’ to calculate the next pc (PCPlus4 in Figure 1).  Don’t use a separate adder module to calculate PCPlus4.

3    Higher Level Module

Now that we have designed all of the submodules, we can use them as a component and design the Datapath.   Here again, you see the Datapath.   Blue lines are wires used to connect the submodules. Define these blue lines as “wire” and connect the components to complete the Datapath.

Use the following code for the module definition of your Datapath.

For Datapath code, we used lowercase letters for input/output naming. You need to use the exact code samples provided for you to design the Datapath and tb Datapath.  Otherwise, your submission will not be considered for grading.

Careful!  * The port names in the diagram are slightly diferent than the port names in the module definition. When writing your code, please use the port names provided in the module definition.  (The diagram is just provided for visual purposes.).

*Pay attention to the orientation of MUX in the figure (which signals are passed to D0 & D1)

*PC increments by 4 bytes to get the next instruction because RISC-V uses byte-addressable memory.

Code 3:  Datapath

1 module data_path #( 2 parameter PC_W = 8, // Program Counter 3 parameter INS_W = 32, // Instruction Width 4 parameter RF_ADDRESS = 5, // Register File Address 5 parameter DATA_W = 32, // Data WriteData 6 parameter DM_ADDRESS = 9, // Data Memory Address 7 parameter ALU_CC_W = 4 // ALU Control Code Width 8 )( 9 input clk , // CLK in Datapath figure 10 input reset , // Reset in Datapath figure 11 input reg_write , // RegWrite in Datapath figure 12 input mem2reg , // MemtoReg in Datapath figure 13 input alu_src , // ALUSrc in Datapath figure 14 input mem_write , // MemWrite in Datapath Figure 15 input mem_read , // MemRead in Datapath Figure 16 input [ ALU_CC_W -1:0] alu_cc , // ALUCC in Datapath Figure 17 output [6:0] opcode , // opcode in Datapath Figure 18 output [6:0] funct7 , // Funct7 in Datapath Figure 19 output [2:0] funct3 , // Funct3 in Datapath Figure 20 output [ DATA_W -1:0] alu_result // Datapath_Result in Datapath Figure 21 ); 22 23 // Write your code here 24 25 26 endmodule // Datapath

Important Note:  we want you to have separate source files for each of the datapath sub- modules.

4    Test the Datapath

Use the code bellow to test your Datapath design.

Code 4: tb Datapath

1 module dp_tb_top (); 2 3 /** Clock & reset **/ 4 reg clk , rst; 5 always begin 6 #10; 7 clk = ∼clk ; 8 end 9 10 initial begin 11 clk = 0; 12 @( posedge clk ); 13 rst = 1; 14 @( posedge clk ); 15 rst = 0; 16 end 17 18 /** DUT Instantiation **/ 19 wire reg_write ; 20 wire mem2reg ; 21 wire alu_src ; 22 wire mem_write ; 23 wire mem_read ; 24 wire [3:0] alu_cc ; 25 wire [6:0] opcode ; 26 wire [6:0] funct7 ; 27 wire [2:0] funct3 ; 28 wire [31:0] alu_result ; 29 30 data_path dp_inst ( 31 . clk ( clk ), 32 . reset ( rst ), 33 . reg_write ( reg_write ), 34 . mem2reg ( mem2reg ), 35 . alu_src ( alu_src ), 36 . mem_write ( mem_write ), 37 . mem_read ( mem_read ), 38 . alu_cc ( alu_cc ), 39 . opcode ( opcode ), 40 . funct7 ( funct7 ), 41 . funct3 ( funct3 ), 42 . alu_result ( alu_result ) 43 );

44

45 /** Stimulus **/

46 wire [6:0] R_TYPE , LW , SW , RTypeI ; 47 48 assign R_TYPE = 7’ b0110011 ; 49 assign LW = 7’ b0000011 ; 50 assign SW = 7’ b0100011 ; 51 assign RTypeI = 7’ b0010011 ; 52 53 54 assign alu_src = ( pcode == LW || pcode == SW || pcode == RTypeI ); 55 assign mem2reg = ( pcode == LW ); 56 assign reg_write = ( pcode == R_TYPE || pcode == LW || pcode == RTypeI ); 57 assign mem_read = ( pcode == LW ); 58 assign mem_write = ( pcode == SW ); 59 60 assign alu_cc = (( pcode == R_TYPE || pcode == RTypeI ) 61 && ( funct7 == 7’ b0000000 ) && ( funct3 == 3’ b000 )) ? 4’ b0010 : 62 (( pcode == R_TYPE || pcode == RTypeI ) 63 && ( funct7 == 7’ b0100000 )) ? 4’ b0110 : 64 (( pcode == R_TYPE || pcode == RTypeI ) 65 && ( funct7 == 7’ b0000000 ) && ( funct3 == 3’ b100 )) ? 4’ b1100 : 66 (( pcode == R_TYPE || pcode == RTypeI ) 67 && ( funct7 == 7’ b0000000 ) && ( funct3 == 3’ b110 )) ? 4’ b0001 : 68 (( pcode == R_TYPE || pcode == RTypeI ) 69 && ( funct7 == 7’ b0000000 ) && ( funct3 == 3’ b111 )) ? 4’ b0000 : 70 (( pcode == R_TYPE || pcode == RTypeI ) 71 && ( funct7 == 7’ b0000000 ) && ( funct3 == 3’ b010 )) ? 4’ b0111 : 72 (( pcode == R_TYPE || pcode == RTypeI ) 73 && ( funct3 == 3’ b100 )) ? 4’ b1100 : 74 (( pcode == R_TYPE || pcode == RTypeI ) 75 && ( funct3 == 3’ b110 )) ? 4’ b0001 : 76 (( pcode == R_TYPE || pcode == RTypeI ) 77 && ( funct3 == 3’ b010 )) ? 4’ b0111 : 78 (( pcode == LW || pcode == SW) 79 && ( funct3 == 3’ b010 ))? 4’ b0010 : 0; 80 81 initial begin 82 #420; 83 $finish ; 84 end 85 86 endmodule

Check the outputs (opcode, funct3, funct7, alu result) to see if they are correct.  Put a screenshot of the wave in your report.  Here you see the screenshot of the wave for the datapath:

Note1:  After running the  simulation, you can add modules/signals from the scope tab to add more signals.   After adding the signal to the wave window you re-run the simulation to show the updated values.

Note2: For Windows users, the use of the slicing operator on the ‘instruction’ wire to pass values to the register file input ports ‘rg rd addr1’ , ‘rg rd addr2’ and ‘rg wrt addr’ - as shown below - might result in a faulty output waveform.

Code 5:  Problematic Register File Instance

1 RegFile rf (...; 2 . rg_wrt_addr ( instruction [11:7] ), 3 . rg_rd_addr1 ( instruction [19: 15] ), 4 . rg_rd_addr2 ( instruction [24: 20] ), 5 ... 6 );

Although this issue will not afect the correctness of the module’s functionality, it can be avoided by creating wires and assigning them to the sliced values and finally connecting these new wires to the ports of the register file as follows:

Code 6:  Solution

1 wire [ RF_ADDRESS -1:0] rd_rg_wrt_wire ; 2 wire [ RF_ADDRESS -1:0] rd_rg_addr_wire1 ; 3 wire [ RF_ADDRESS -1:0] rd_rg_addr_wire1 ; 4 5 assign rd_rg_wrt_wire = instruction [11: 7]; 6 assign rd_rg_addr_wire1 = instruction [19: 15]; 7 assign rd_rg_addr_wire2 = instruction [20: 24]; 8 9 RegFile rf (...; 10 . rg_wrt_addr ( rd_rg_wrt_wire ), 11 . rg_rd_addr1 ( rd_rg_addr_wire1 ), 12 . rg_rd_addr2 ( rd_rg_addr_wire2 ), 13 ... 14 );

5    Assignment Deliverable

Your submission should include the following:

•  Block designs  and testbenches.   (FlipFlop.v,  InstMem.v,  RegFile.v,  ImmGen.v,  Mux.v,  ALU.v, DataMem.v, Datapath.v. tb Datapath.v).  Use the files we provided for you with this lab.

•  For the Mux design, consider size of data inputs and change your previous designs to match with the processor datapath (see Figure 1).

•  A report in pdf format.  Follow the rules in the “sample report” .

Note1: Compress all files (10 files :  9 .v files + report.pdf) into zip and upload to the CANVAS before deadline.  Make sure that you submit one  .zip file, otherwise your submission will not be considered for grading.

Note2:  Use the code samples that are given in the lab description.  The module part of your code should exactly look like the code sample otherwise your submission will not be considered for grading.


软件开发、广告设计客服
  • QQ:99515681
  • 邮箱:99515681@qq.com
  • 工作时间:8:00-23:00
  • 微信:codinghelp
热点标签

联系我们 - QQ: 9951568
© 2021 www.rj363.com
软件定制开发网!