.. SERV documentation master file, created by sphinx-quickstart on Mon Feb 24 00:01:33 2020. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. SERV user manual ================ .. toctree:: :maxdepth: 2 :caption: Contents: Modules ------- SERV is a bit-serial CPU which means that the internal datapath is one bit wide. :ref:`dataflow` show the internal dataflow. For each instruction, data is read from the register file or the immediate fields of the instruction word and the result of the operation is stored back into the register file. Reading and writing memory is handled through the memory interface module. .. _dataflow: .. figure:: serv_dataflow.png SERV internal dataflow serv_rf_top ^^^^^^^^^^^ .. image:: serv_rf_top.png serv_rf_top is a top-level convenience wrapper that includes SERV and the default RF implementation and just exposes the timer IRQ and instruction/data wishbone buses. serv_top ^^^^^^^^ serv_top is the top-level of the SERV core without an RF serv_alu ^^^^^^^^ .. image:: serv_alu.png serv_alu handles alu operations. The first input operand (A) comes from i_rs1 and the second operand (B) comes from i_rs2 or i_imm depending on the type of operation. The data passes through the add/sub or bool logic unit and finally ends up in o_rd to be written to the destination register. The output o_cmp is used for conditional branches to decide whether or not to take the branch. The add/sub unit can do additions A+B or subtractions A-B by converting it to A+BĚ…+1. Subtraction mode (i_sub = 1) is also used for the comparisions in the slt* and conditional branch instructions. The +1 used in subtraction mode is done by preloading the carry input with 1. Less-than comparisons are handled by converting the expression Ab","b~>c"] } The bus requests begin by SERV raising o_ibus_cyc until the memory responds with an i_ibus_ack and presents the instruction on i_ibus_rdt. Upon seeing the ack, SERV will ower cyc to indicate the end of the bus cycle. When the ack appears, two things happen in SERV. The relevant portions of the instruction such as opcode, funct3 and immediate value are saved in serv_decode and serv_immdec. The saved bits of the instruction is then decoded to create the internal control signals that corresponds to the current instruction. The other thing to happen is that request to start accessing the register file is sent by strobing rf_rreq which prepares the register file for both read and write access. .. wavedrom:: { signal: [ { name: "clk" , wave: "0P.|....."}, { name: "rreq" , wave: "010|.....", node: ".a..."}, { name: "rreg0" , wave: "x.2|.....", node: "....", data: "r0"}, { name: "rreg1" , wave: "x.2|.....", node: "....", data: "r1"}, { name: "ready" , wave: "0..|10...", node: "....b."}, { name: "rdata0" , wave: "-..|12345", data: "0 1 2 3 4"}, { name: "rdata1" , wave: "-..|12345", data: "0 1 2 3 4"}, ], edge : [ "a~>b"] } The interface between the core and the register file is described in a protocol where the core strobes rreq and present the registers to read on the following cycle. The register file will prepare to stream out data bit from the two requested registers. The cycle before it sends out the first bit (LSB) it will strobe rf_ready. Writes work in a similar way in that the registers to write has to be presented the cycle after rf_wreq is strobed and that the register file will start accepting data the cycle after it has strobed rf_ready. Note that the delay between rf_wreq and rf_ready does not have to be the same as from rf_rreq to rf_ready. Also note that register data will only be written to a register if the corresponding write enable signal is asserted. In the diagram below, only register r0 will be written to. .. wavedrom:: { signal: [ { name: "clk" , wave: "0P....."}, { name: "wreq" , wave: "010....", node: ".a..."}, { name: "ready" , wave: "010....", node: ".b."}, { name: "wreg0" , wave: "x.2....", node: "....", data: "r0"}, { name: "wreg1" , wave: "x.2....", node: "....", data: "r1"}, { name: "wen0" , wave: "0.1...."}, { name: "wen1" , wave: "0......"}, { name: "wdata0" , wave: "-123456", node: "..c.", data: "0 1 2 3 4"}, { name: "wdata1" , wave: "-123456", node: "..d.", data: "0 1 2 3 4"}, ], edge : [ "a~>b", "b~>c", "b~>d"] }