diff --git a/caravan b/caravan index 2067408..14ed666 160000 --- a/caravan +++ b/caravan @@ -1 +1 @@ -Subproject commit 2067408c4081e4bdfc728f120353b2558d9273e6 +Subproject commit 14ed666e53540a119914f464dfcad0032b736003 diff --git a/src/main/resources/sram/sram.v b/src/main/resources/sram/sram.v new file mode 100644 index 0000000..279697a --- /dev/null +++ b/src/main/resources/sram/sram.v @@ -0,0 +1,144 @@ +// SPDX-FileCopyrightText: 2020 fabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +//`default_nettype none +// OpenRAM SRAM model +// Words: 256 +// Word size: 32 +// Write size: 8 + +module sram #( + parameter NUM_WMASKS = 4, + parameter DATA_WIDTH = 32, + parameter ADDR_WIDTH = 10, + parameter RAM_DEPTH = 1 << ADDR_WIDTH, + // FIXME: This delay is arbitrary. + parameter DELAY = 3, + parameter IZERO = 0 , // binary / Initial RAM with zeros (has priority over INITFILE) + parameter IFILE = "" +) +( +/*`ifdef USE_POWER_PINS + vdd, + gnd, +`endif */ +// Port 0: RW + clk0,csb0,web0,wmask0,addr0,din0,dout0, +// Port 1: R + clk1,csb1,addr1,dout1 + ); + + +/*`ifdef USE_POWER_PINS + inout vdd; + inout gnd; +`endif + */ + input clk0; // clock + input csb0; // active low chip select + input web0; // active low write control + input [NUM_WMASKS-1:0] wmask0; // write mask + input [ADDR_WIDTH-1:0] addr0; + input [DATA_WIDTH-1:0] din0; + output [DATA_WIDTH-1:0] dout0; + input clk1; // clock + input csb1; // active low chip select + input [ADDR_WIDTH-1:0] addr1; + output [DATA_WIDTH-1:0] dout1; + + reg csb0_reg; + reg web0_reg; + reg [NUM_WMASKS-1:0] wmask0_reg; + reg [ADDR_WIDTH-1:0] addr0_reg; + reg [DATA_WIDTH-1:0] din0_reg; + reg [DATA_WIDTH-1:0] dout0; + + // All inputs are registers + always @(posedge clk0) + begin + csb0_reg = csb0; + web0_reg = web0; + wmask0_reg = wmask0; + addr0_reg = addr0; + din0_reg = din0; + //dout0 = 32'bx0; +/*`ifdef DBG + if ( !csb0_reg && web0_reg ) + $display($time," Reading %m addr0=%b dout0=%b",addr0_reg,mem[addr0_reg]); + if ( !csb0_reg && !web0_reg ) + $display($time," Writing %m addr0=%b din0=%b wmask0=%b",addr0_reg,din0_reg,wmask0_reg); +`endif +*/ end + + reg csb1_reg; + reg [ADDR_WIDTH-1:0] addr1_reg; + reg [DATA_WIDTH-1:0] dout1; + + // All inputs are registers + always @(posedge clk1) + begin + csb1_reg = csb1; + addr1_reg = addr1; +//`ifdef DBG +// if (!csb0 && !web0 && !csb1 && (addr0 == addr1)) +// $display($time," WARNING: Writing and reading addr0=%b and addr1=%b simultaneously!",addr0,addr1); +// dout1 = 32'bx; +// if ( !csb1_reg ) +// $display($time," Reading %m addr1=%b dout1=%b",addr1_reg,mem[addr1_reg]); +//`endif + end +integer i; +reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1]; +initial + if (IZERO) + for (i=0; i io.req + io.rsp <> hostAdapter.io.rspOut + hostAdapter.io.wbMasterTransmitter <> deviceAdapter.io.wbMasterReceiver + hostAdapter.io.wbSlaveReceiver <> deviceAdapter.io.wbSlaveTransmitter + + spi.io.req <> deviceAdapter.io.reqOut + spi.io.rsp <> deviceAdapter.io.rspIn + + + io.cs_n := spi.io.cs_n + io.sclk := spi.io.sclk + io.mosi := spi.io.mosi + + spi.io.miso := io.miso +} + +object SpiFlashDriverWB extends App { + implicit val config = WishboneConfig(32,32) + // implicit val spiConfig = Config() + (new ChiselStage).emitVerilog(new SpiFlashHarness()) +} + + + + +class SpiFlashHarnessTL(implicit val config: TilelinkConfig) extends Module { + val io = IO(new Bundle { + + // bus interconnect interfaces + val req = Flipped(Decoupled(new TLRequest())) + val rsp = Decoupled(new TLResponse()) + + // master spi interfaces + val cs_n = Output(Bool()) + val sclk = Output(Bool()) + val mosi = Output(Bool()) + val miso = Input(Bool()) + + }) + val hostAdapter = Module(new TilelinkHost()) + val deviceAdapter = Module(new TilelinkDevice()) + val spi = Module(new SpiFlash(new TLRequest(), new TLResponse())) + + hostAdapter.io.reqIn <> io.req + io.rsp <> hostAdapter.io.rspOut + hostAdapter.io.tlMasterTransmitter <> deviceAdapter.io.tlMasterReceiver + hostAdapter.io.tlSlaveReceiver <> deviceAdapter.io.tlSlaveTransmitter + + spi.io.req <> deviceAdapter.io.reqOut + spi.io.rsp <> deviceAdapter.io.rspIn + + + io.cs_n := spi.io.cs_n + io.sclk := spi.io.sclk + io.mosi := spi.io.mosi + + spi.io.miso := io.miso +} + +object SpiFlashDriverTL extends App { + implicit val config = TilelinkConfig() + // implicit val spiConfig = Config() + (new ChiselStage).emitVerilog(new SpiFlashHarnessTL()) +} diff --git a/src/main/scala/jigsaw/SpiHarness.scala b/src/main/scala/jigsaw/SpiHarness.scala index 938f025..a9355dd 100644 --- a/src/main/scala/jigsaw/SpiHarness.scala +++ b/src/main/scala/jigsaw/SpiHarness.scala @@ -4,9 +4,9 @@ import caravan.bus.wishbone.{WBRequest, WBResponse, WishboneConfig, WishboneDevi import chisel3._ import chisel3.stage.ChiselStage import chisel3.util.Decoupled -import jigsaw.peripherals.spiflash.{Config,Spi} +import jigsaw.peripherals.spi.{Config,Spi} -class SpiHarness(implicit val config: WishboneConfig, spiConfig:Config) extends Module { +class SpiHarness(implicit val config: WishboneConfig) extends Module { val io = IO(new Bundle { // bus interconnect interfaces @@ -42,14 +42,14 @@ class SpiHarness(implicit val config: WishboneConfig, spiConfig:Config) extends object SpiDriverWB extends App { implicit val config = WishboneConfig(32,32) - implicit val spiConfig = Config() + // implicit val spiConfig = Config() (new ChiselStage).emitVerilog(new SpiHarness()) } -class SpiHarnessTL(implicit val config: TilelinkConfig, spiConfig:Config) extends Module { +class SpiHarnessTL(implicit val config: TilelinkConfig) extends Module { val io = IO(new Bundle { // bus interconnect interfaces @@ -85,6 +85,6 @@ class SpiHarnessTL(implicit val config: TilelinkConfig, spiConfig:Config) extend object SpiDriverTL extends App { implicit val config = TilelinkConfig() - implicit val spiConfig = Config() + // implicit val spiConfig = Config() (new ChiselStage).emitVerilog(new SpiHarnessTL()) } diff --git a/src/main/scala/jigsaw/SramHarness.scala b/src/main/scala/jigsaw/SramHarness.scala new file mode 100644 index 0000000..d0fbc02 --- /dev/null +++ b/src/main/scala/jigsaw/SramHarness.scala @@ -0,0 +1,65 @@ +package jigsaw +import caravan.bus.tilelink.{TLRequest, TLResponse, TilelinkConfig, TilelinkDevice, TilelinkHost} +import caravan.bus.wishbone.{WBRequest, WBResponse, WishboneConfig, WishboneDevice, WishboneHost} +import chisel3._ +import chisel3.stage.ChiselStage +import chisel3.util.Decoupled +// import jigsaw.peripherals.spiflash.{Config,Spi} +import jigsaw.rams.sram._ + +class SramHarness(programFile:Option[String], val AW:Int = 10)(implicit val config: WishboneConfig) extends Module { + val io = IO(new Bundle { + + // bus interconnect interfaces + val req = Flipped(Decoupled(new WBRequest())) + val rsp = Decoupled(new WBResponse()) + }) + val hostAdapter = Module(new WishboneHost()) + val deviceAdapter = Module(new WishboneDevice()) + val sram = Module(new SRAM1kb(new WBRequest(), new WBResponse())(programFile, AW)) + + hostAdapter.io.reqIn <> io.req + io.rsp <> hostAdapter.io.rspOut + hostAdapter.io.wbMasterTransmitter <> deviceAdapter.io.wbMasterReceiver + hostAdapter.io.wbSlaveReceiver <> deviceAdapter.io.wbSlaveTransmitter + + sram.io.req <> deviceAdapter.io.reqOut + sram.io.rsp <> deviceAdapter.io.rspIn +} + +object SramDriverWB extends App { + implicit val config = WishboneConfig(32,32) +// implicit val spiConfig = Config() + (new ChiselStage).emitVerilog(new SramHarness(None)) +} + + + + +class SramHarnessTL(programFile:Option[String], val AW:Int = 10)(implicit val config: TilelinkConfig ) extends Module { + val io = IO(new Bundle { + + // bus interconnect interfaces + val req = Flipped(Decoupled(new TLRequest())) + val rsp = Decoupled(new TLResponse()) + + }) + val hostAdapter = Module(new TilelinkHost()) + val deviceAdapter = Module(new TilelinkDevice()) + val sram = Module(new SRAM1kb(new TLRequest(), new TLResponse())(programFile, AW)) + + hostAdapter.io.reqIn <> io.req + io.rsp <> hostAdapter.io.rspOut + hostAdapter.io.tlMasterTransmitter <> deviceAdapter.io.tlMasterReceiver + hostAdapter.io.tlSlaveReceiver <> deviceAdapter.io.tlSlaveTransmitter + + sram.io.req <> deviceAdapter.io.reqOut + sram.io.rsp <> deviceAdapter.io.rspIn + +} + +object SramDriverTL extends App { + implicit val config = TilelinkConfig() +// implicit val spiConfig = Config() + (new ChiselStage).emitVerilog(new SramHarnessTL(None)) +} diff --git a/src/main/scala/jigsaw/TimerHarness.scala b/src/main/scala/jigsaw/TimerHarness.scala new file mode 100644 index 0000000..2e0adee --- /dev/null +++ b/src/main/scala/jigsaw/TimerHarness.scala @@ -0,0 +1,78 @@ +package jigsaw +import caravan.bus.tilelink.{TLRequest, TLResponse, TilelinkConfig, TilelinkDevice, TilelinkHost} +import caravan.bus.wishbone.{WBRequest, WBResponse, WishboneConfig, WishboneDevice, WishboneHost} +import chisel3._ +import chisel3.stage.ChiselStage +import chisel3.util.Decoupled +// import jigsaw.peripherals.spiflash.{Config,Spi} +// import jigsaw.rams.sram._ +import jigsaw.peripherals.timer._ + +class TimerHarness(implicit val config: WishboneConfig ) extends Module { + val io = IO(new Bundle { + + // bus interconnect interfaces + val req = Flipped(Decoupled(new WBRequest())) + val rsp = Decoupled(new WBResponse()) + + val cio_timer_intr_cmp = Output(Bool()) + val cio_timer_intr_ovf = Output(Bool()) + }) + val hostAdapter = Module(new WishboneHost()) + val deviceAdapter = Module(new WishboneDevice()) + val timer = Module(new Timer(new WBRequest(), new WBResponse())) + + hostAdapter.io.reqIn <> io.req + io.rsp <> hostAdapter.io.rspOut + hostAdapter.io.wbMasterTransmitter <> deviceAdapter.io.wbMasterReceiver + hostAdapter.io.wbSlaveReceiver <> deviceAdapter.io.wbSlaveTransmitter + + timer.io.req <> deviceAdapter.io.reqOut + timer.io.rsp <> deviceAdapter.io.rspIn + + io.cio_timer_intr_cmp := timer.io.cio_timer_intr_cmp + io.cio_timer_intr_ovf := timer.io.cio_timer_intr_ovf +} + +object TimerDriverWB extends App { + implicit val config = WishboneConfig(32,32) +// implicit val spiConfig = Config() + (new ChiselStage).emitVerilog(new TimerHarness()) +} + + + + +class TimerHarnessTL(implicit val config: TilelinkConfig ) extends Module { + val io = IO(new Bundle { + + // bus interconnect interfaces + val req = Flipped(Decoupled(new TLRequest())) + val rsp = Decoupled(new TLResponse()) + + val cio_timer_intr_cmp = Output(Bool()) + val cio_timer_intr_ovf = Output(Bool()) + + }) + val hostAdapter = Module(new TilelinkHost()) + val deviceAdapter = Module(new TilelinkDevice()) + val timer = Module(new Timer(new TLRequest(), new TLResponse())) + + hostAdapter.io.reqIn <> io.req + io.rsp <> hostAdapter.io.rspOut + hostAdapter.io.tlMasterTransmitter <> deviceAdapter.io.tlMasterReceiver + hostAdapter.io.tlSlaveReceiver <> deviceAdapter.io.tlSlaveTransmitter + + timer.io.req <> deviceAdapter.io.reqOut + timer.io.rsp <> deviceAdapter.io.rspIn + + io.cio_timer_intr_cmp := timer.io.cio_timer_intr_cmp + io.cio_timer_intr_ovf := timer.io.cio_timer_intr_ovf + +} + +object TimerDriverTL extends App { + implicit val config = TilelinkConfig() +// implicit val spiConfig = Config() + (new ChiselStage).emitVerilog(new TimerHarnessTL()) +} diff --git a/src/main/scala/jigsaw/peripherals/programmable_uart/PUart.scala b/src/main/scala/jigsaw/peripherals/programmable_uart/PUart.scala new file mode 100644 index 0000000..12f56b0 --- /dev/null +++ b/src/main/scala/jigsaw/peripherals/programmable_uart/PUart.scala @@ -0,0 +1,81 @@ +package jigsaw.peripherals.programmable_uart + +import chisel3._ +import chisel3.util._ + +class PUart extends Module { + val io = IO(new Bundle { + val isStalled = Input(Bool()) + + val rx_data_o = Output(UInt(32.W)) + val addr_o = Output(UInt(8.W)) + val CLK_PER_BIT = Input(UInt(16.W)) + val rxd = Input(UInt(1.W)) + + val valid = Output(Bool()) + val done = Output(Bool()) + }) + + val regDone = RegInit(false.B) + val count = RegInit(0.U(3.W)) + val regFinalData = RegInit(0.U(32.W)) + val regAddr = RegInit(16383.U(14.W)) + val regValid = RegInit(false.B) + + val rx = Module(new Rx) + + rx.io.CLK_PER_BIT := io.CLK_PER_BIT + rx.io.rxd := io.rxd + + val dataReg = RegInit(0.U(8.W)) + val regLSB1 = RegInit(0.U(8.W)) + val regLSB2 = RegInit(0.U(8.W)) + val regMSB1 = RegInit(0.U(8.W)) + val regMSB2 = RegInit(0.U(8.W)) + + when(io.isStalled && !regDone) { + when(rx.io.valid === 1.U) { + // We get 1 byte of data from the Rx module + // dataReg := rx.io.channel.bits + dataReg := rx.io.data + count := count + 1.U + regValid := false.B + } + } + switch(count) { + is(1.U) { + regLSB1 := dataReg + } + is(2.U) { + regLSB2 := dataReg + } + is(3.U) { + regMSB1 := dataReg + } + is(4.U) { + // Now the 32-Bit data is complete here + val data = Cat(dataReg, regMSB1, regLSB2, regLSB1) + when(data === "h00000fff".U) { + regDone := true.B + regFinalData := 0.U + regAddr := 0.U + regValid := false.B + }.otherwise { + regFinalData := data + regAddr := regAddr + 1.U + regValid := true.B + } + + } + } + + when(count === 4.U) { + count := 0.U + } + + io.addr_o := regAddr + io.rx_data_o := regFinalData + io.valid := regValid + io.done := regDone + +} \ No newline at end of file diff --git a/src/main/scala/jigsaw/peripherals/programmable_uart/Rx.scala b/src/main/scala/jigsaw/peripherals/programmable_uart/Rx.scala new file mode 100644 index 0000000..95d71a1 --- /dev/null +++ b/src/main/scala/jigsaw/peripherals/programmable_uart/Rx.scala @@ -0,0 +1,95 @@ +package jigsaw.peripherals.programmable_uart + +import chisel3._ +import chisel3.util._ +import chisel3.dontTouch + +class Rx extends Module { + val io = IO(new Bundle { + val CLK_PER_BIT = Input(UInt(16.W)) + val rxd = Input(Bits(1.W)) + val valid = Output(Bool()) + val data = Output(Bits(8.W)) + }) + + val CLCK_PER_BIT = dontTouch(Wire(UInt(32.W))) + CLCK_PER_BIT := io.CLK_PER_BIT + + val idle :: start :: data :: stop :: cleanup :: Nil = Enum(5) + val stateReg = RegInit(idle) + + val clockCount = RegInit(0.U(8.W)) + val bitIndex = RegInit(0.U(4.W)) + val validReg = RegInit(0.U(1.W)) + //val dataReg = RegInit(VecInit(Seq.fill(8)(0.U(1.W)))) + val rxReg = RegNext(RegNext(io.rxd, 1.U), 1.U) + val shiftReg = RegInit('A'.U(8.W)) + + switch(stateReg) { + is(idle) { + validReg := 0.U + clockCount := 0.U + bitIndex := 0.U + + when(io.rxd === 0.U) { + stateReg := start + }.otherwise { + stateReg := idle + } + } + + is(start) { + when(clockCount === ((CLCK_PER_BIT - 1.U) / 2.U)) { + when(io.rxd === 0.U) { + clockCount := 0.U + stateReg := data + }.otherwise { + stateReg := idle + } + }.otherwise { + clockCount := clockCount + 1.U + stateReg := start + } + } + + is(data) { + when(clockCount < (CLCK_PER_BIT - 1.U)) { + clockCount := clockCount + 1.U + stateReg := data + }.otherwise { + clockCount := 0.U + shiftReg := Cat(rxReg, shiftReg >> 1) + //dataReg(bitIndex) := io.rxd + + when(bitIndex < 7.U) { + bitIndex := bitIndex + 1.U + stateReg := data + }.otherwise { + bitIndex := 0.U + stateReg := stop + } + } + } + + is(stop) { + when(clockCount < (CLCK_PER_BIT - 1.U)) { + clockCount := clockCount + 1.U + stateReg := stop + }.otherwise { + validReg := 1.U + clockCount := 0.U + stateReg := cleanup + } + } + + is(cleanup) { + stateReg := idle + validReg := 0.U + } + } + + io.data := shiftReg + //io.data := dataReg.asUInt() + io.valid := validReg + +} \ No newline at end of file diff --git a/src/main/scala/jigsaw/peripherals/spi/Config.scala b/src/main/scala/jigsaw/peripherals/spi/Config.scala new file mode 100644 index 0000000..2ed802d --- /dev/null +++ b/src/main/scala/jigsaw/peripherals/spi/Config.scala @@ -0,0 +1,5 @@ +package jigsaw.peripherals.spi + +case class Config( + DW : Int = 32 +) \ No newline at end of file diff --git a/src/main/scala/jigsaw/peripherals/spi/Protocol.scala b/src/main/scala/jigsaw/peripherals/spi/Protocol.scala new file mode 100644 index 0000000..d852892 --- /dev/null +++ b/src/main/scala/jigsaw/peripherals/spi/Protocol.scala @@ -0,0 +1,91 @@ +package jigsaw.peripherals.spi + +import chisel3._ +import chisel3.util._ +import chisel3.experimental.ChiselEnum + + +class Protocol_IO(DW:Int) extends Bundle{ + val miso = Input(Bool()) + val mosi = Output(Bool()) + val ss = Output(Bool()) + val sck = Output(Bool()) + val data_in = Flipped(Decoupled(UInt(DW.W))) + val data_out = Decoupled(UInt(DW.W)) + val CPOL = Input(Bool()) + val CPHA = Input(Bool()) + // val config = Input(UInt(DW.W)) + // val resetProtocol = Input(Bool()) +} + +class Protocol(val DW:Int = 32) extends Module{ + val io = IO(new Protocol_IO(DW)) + + val CPOL = WireInit(io.CPOL) + val CPHA = WireInit(io.CPHA) + + val idle :: busy :: Nil = Enum(2) + val state = RegInit(idle) + + val miso_dataReg = RegInit(0.U(DW.W)) + val count = RegInit(0.U(7.W)) + val dataReg = RegInit(0.U((DW*2).W)) + + val clk = WireInit(clock.asUInt()(0)) + io.sck := Mux(state === busy, Mux(CPOL,~clk,clk), 0.B) + // io.sck := Mux(CPOL,~clk,clk) // Mode 1 and 4 + // io.sck := 0.B + + io.data_in.ready := 0.B + io.data_out.valid := 0.B + io.data_out.bits := 0.U + io.ss := 1.B + io.mosi := 0.B + + // Transmission + switch(state){ + is(idle){ + io.data_in.ready := 1.B + when (io.data_in.valid/* & io.data_in.ready*/){ + dataReg := Cat(io.data_in.bits, Fill(32,0.B)) // it should be this + state := busy + // io.data_in.ready := 1.B + // io.ss := 0.B + // dataReg := Cat("b00000011".U,Fill(24,0.B),io.data_in.bits) // Fill should be at the end + // dataReg := Cat(io.data_in.bits,Fill(32,0.B)) + + } + } + is(busy){ + when (count === (DW*2).U){ + io.data_in.ready := 1.B + io.ss := 1.B + state := idle + count := 0.U + }.otherwise{ + io.ss := 0.B + io.mosi := dataReg((DW*2)-1) + dataReg := dataReg << 1 + count := count + 1.U + } + } + } + + // Receiving + val count1 = RegInit(0.U(7.W)) + switch(state){ + is(busy){ + io.ss := 0.B + when (count1 === (DW*2).U /*& io.data_out.ready*/){ + io.data_out.bits := miso_dataReg + io.data_out.valid := 1.B + count1 := 0.U + }.otherwise{ + miso_dataReg := miso_dataReg << 1 | io.miso + count1 := count1 + 1.U + } + } + } +} + + diff --git a/src/main/scala/jigsaw/peripherals/spiflash/Spi.scala b/src/main/scala/jigsaw/peripherals/spi/Spi.scala similarity index 79% rename from src/main/scala/jigsaw/peripherals/spiflash/Spi.scala rename to src/main/scala/jigsaw/peripherals/spi/Spi.scala index 75262e3..344db87 100644 --- a/src/main/scala/jigsaw/peripherals/spiflash/Spi.scala +++ b/src/main/scala/jigsaw/peripherals/spi/Spi.scala @@ -1,4 +1,4 @@ -package jigsaw.peripherals.spiflash +package jigsaw.peripherals.spi import caravan.bus.common.{AbstrRequest, AbstrResponse} import chisel3._ @@ -22,7 +22,7 @@ class Spi_IO[A <: AbstrRequest, B <: AbstrResponse] } class Spi[A <: AbstrRequest, B <: AbstrResponse] - (gen: A, gen1: B)(implicit val spiConfig: Config) extends Module{ + (gen: A, gen1: B) extends Module{ val io = IO(new Spi_IO(gen, gen1)) val ControlReg = RegInit("b1100000".U(32.W)) // addr 0x0 @@ -57,27 +57,28 @@ class Spi[A <: AbstrRequest, B <: AbstrResponse] // List(io.cs_n, io.sclk, io.mosi) map (_ := DontCare) } .elsewhen(io.req.bits.addrRequest(3,0) === 4.U && io.req.bits.isWrite === 1.B){ - when(ControlReg(4,2) === 0.U){ // READ - TxDataReg := Mux(io.req.valid, Cat("b00000011".U,(io.req.bits.dataRequest & maskedData.asUInt)(23,0)), 0.U) - TxDataValidReg := io.req.valid - } - .elsewhen(ControlReg(4,2) === 1.U){ // WR_EN - TxDataReg := Mux(io.req.valid, Cat("b00000110".U, Fill(24,0.B)), 0.U) - TxDataValidReg := io.req.valid - } - .elsewhen(ControlReg(4,2) === 2.U){ // PP_ADDR - TxDataReg := Mux(io.req.valid, Cat("b00000010".U,(io.req.bits.dataRequest & maskedData.asUInt)(23,0)), 0.U) - TxDataValidReg := io.req.valid - } - .elsewhen(ControlReg(4,2) === 3.U){ // PP_DATA - TxDataReg := Mux(io.req.valid, io.req.bits.dataRequest & maskedData.asUInt, 0.U) - TxDataValidReg := io.req.valid - } - .elsewhen(ControlReg(4,2) === 4.U){ // WR_DI - TxDataReg := Mux(io.req.valid, Cat("b00000100".U, Fill(24,0.B)), 0.U) - TxDataValidReg := io.req.valid - } - + // when(ControlReg(4,2) === 0.U){ // READ + // TxDataReg := Mux(io.req.valid, Cat("b00000011".U,(io.req.bits.dataRequest & maskedData.asUInt)(23,0)), 0.U) + // TxDataValidReg := io.req.valid + // } + // .elsewhen(ControlReg(4,2) === 1.U){ // WR_EN + // TxDataReg := Mux(io.req.valid, Cat("b00000110".U, Fill(24,0.B)), 0.U) + // TxDataValidReg := io.req.valid + // } + // .elsewhen(ControlReg(4,2) === 2.U){ // PP_ADDR + // TxDataReg := Mux(io.req.valid, Cat("b00000010".U,(io.req.bits.dataRequest & maskedData.asUInt)(23,0)), 0.U) + // TxDataValidReg := io.req.valid + // } + // .elsewhen(ControlReg(4,2) === 3.U){ // PP_DATA + // TxDataReg := Mux(io.req.valid, io.req.bits.dataRequest & maskedData.asUInt, 0.U) + // TxDataValidReg := io.req.valid + // } + // .elsewhen(ControlReg(4,2) === 4.U){ // WR_DI + // TxDataReg := Mux(io.req.valid, Cat("b00000100".U, Fill(24,0.B)), 0.U) + // TxDataValidReg := io.req.valid + // } + TxDataReg := Mux(io.req.valid, io.req.bits.dataRequest & maskedData.asUInt, 0.U) + TxDataValidReg := io.req.valid io.rsp.bits.dataResponse := RegNext(Mux(io.rsp.ready, io.req.bits.addrRequest, 0.U)) io.rsp.valid := RegNext(1.B) diff --git a/src/main/scala/jigsaw/peripherals/spiflash/Protocol.scala b/src/main/scala/jigsaw/peripherals/spiflash/Protocol.scala index 1c535d0..5cda432 100644 --- a/src/main/scala/jigsaw/peripherals/spiflash/Protocol.scala +++ b/src/main/scala/jigsaw/peripherals/spiflash/Protocol.scala @@ -18,8 +18,8 @@ class Protocol_IO(DW:Int) extends Bundle{ // val resetProtocol = Input(Bool()) } -class Protocol(implicit val spiConfig: Config) extends Module{ - val io = IO(new Protocol_IO(spiConfig.DW)) +class Protocol(val DW:Int = 32) extends Module{ + val io = IO(new Protocol_IO(DW)) val CPOL = WireInit(io.CPOL) val CPHA = WireInit(io.CPHA) @@ -27,9 +27,9 @@ class Protocol(implicit val spiConfig: Config) extends Module{ val idle :: busy :: Nil = Enum(2) val state = RegInit(idle) - val miso_dataReg = RegInit(0.U(spiConfig.DW.W)) + val miso_dataReg = RegInit(0.U(DW.W)) val count = RegInit(0.U(7.W)) - val dataReg = RegInit(0.U((spiConfig.DW*2).W)) + val dataReg = RegInit(0.U((DW*2).W)) val clk = WireInit(clock.asUInt()(0)) io.sck := Mux(state === busy, Mux(CPOL,~clk,clk), 0.B) @@ -57,14 +57,14 @@ class Protocol(implicit val spiConfig: Config) extends Module{ } } is(busy){ - when (count === (spiConfig.DW*2).U){ + when (count === (DW*2).U){ io.data_in.ready := 1.B io.ss := 1.B state := idle count := 0.U }.otherwise{ io.ss := 0.B - io.mosi := dataReg((spiConfig.DW*2)-1) + io.mosi := dataReg((DW*2)-1) dataReg := dataReg << 1 count := count + 1.U } @@ -76,7 +76,7 @@ class Protocol(implicit val spiConfig: Config) extends Module{ switch(state){ is(busy){ io.ss := 0.B - when (count1 === (spiConfig.DW*2).U /*& io.data_out.ready*/){ + when (count1 === (DW*2).U /*& io.data_out.ready*/){ io.data_out.bits := miso_dataReg io.data_out.valid := 1.B count1 := 0.U diff --git a/src/main/scala/jigsaw/peripherals/spiflash/SpiFlash.scala b/src/main/scala/jigsaw/peripherals/spiflash/SpiFlash.scala new file mode 100644 index 0000000..4b629d0 --- /dev/null +++ b/src/main/scala/jigsaw/peripherals/spiflash/SpiFlash.scala @@ -0,0 +1,165 @@ +package jigsaw.peripherals.spiflash + +import caravan.bus.common.{AbstrRequest, AbstrResponse} +import chisel3._ +import chisel3.experimental.ChiselEnum +import chisel3.stage.ChiselStage +import chisel3.util.{Cat, Decoupled, Fill, MuxCase, Enum} +import jigsaw.peripherals.spiflash._ + +class Spi_IO[A <: AbstrRequest, B <: AbstrResponse] + (gen: A, gen1: B) extends Bundle{ + + // bus interconnect interfaces + val req = Flipped(Decoupled(gen)) + val rsp = Decoupled(gen1) + + // master spi interfaces + val cs_n = Output(Bool()) + val sclk = Output(Bool()) + val mosi = Output(Bool()) + val miso = Input(Bool()) +} + +class SpiFlash[A <: AbstrRequest, B <: AbstrResponse] + (gen: A, gen1: B) extends Module{ + + val io = IO(new Spi_IO(gen, gen1)) + val ControlReg = RegInit("b1100000".U(32.W)) // addr 0x0 + val TxDataReg = RegInit(0.U(32.W)) // addr 0x4 + val TxDataValidReg = RegInit(0.B) + val RxDataReg = RegInit(0.U(32.W)) // addr 0x8 + val RxDataValidReg = RegInit(0.B) + + val maskedData = Wire(Vec(4, UInt(8.W))) + maskedData := io.req.bits.activeByteLane.asTypeOf(Vec(4, Bool())) map (Fill(8,_)) + + io.req.ready := 1.B + io.rsp.valid := 0.B + // io.rsp.bits.ackWrite := 1.B + + when (io.req.bits.addrRequest(3,0) === 0.U && io.req.bits.isWrite === 1.B){ + ControlReg := Mux(io.req.valid, io.req.bits.dataRequest & maskedData.asUInt, ControlReg) + + io.rsp.bits.dataResponse := RegNext(Mux(io.rsp.ready, io.req.bits.dataRequest, 0.U)) + io.rsp.valid := RegNext(io.req.valid) + + + // List(io.req.ready, io.rsp.valid) map (_ := 1.B) + // List(io.cs_n, io.sclk, io.mosi) map (_ := DontCare) + } + .elsewhen(io.req.bits.addrRequest(3,0) === 0.U && io.req.bits.isWrite === 0.B){ + io.rsp.bits.dataResponse := RegNext(Mux(io.rsp.ready, ControlReg, 0.U)) + io.rsp.valid := RegNext(Mux(io.req.valid, 1.B, 0.U)) + + + // List(io.req.ready, io.rsp.valid) map (_ := 1.B) + // List(io.cs_n, io.sclk, io.mosi) map (_ := DontCare) + } + .elsewhen(io.req.bits.addrRequest(3,0) === 4.U && io.req.bits.isWrite === 1.B){ + when(ControlReg(4,2) === 0.U){ // READ + TxDataReg := Mux(io.req.valid, Cat("b00000011".U,(io.req.bits.dataRequest & maskedData.asUInt)(23,0)), 0.U) + TxDataValidReg := io.req.valid + } + .elsewhen(ControlReg(4,2) === 1.U){ // WR_EN + TxDataReg := Mux(io.req.valid, Cat("b00000110".U, Fill(24,0.B)), 0.U) + TxDataValidReg := io.req.valid + } + .elsewhen(ControlReg(4,2) === 2.U){ // PP_ADDR + TxDataReg := Mux(io.req.valid, Cat("b00000010".U,(io.req.bits.dataRequest & maskedData.asUInt)(23,0)), 0.U) + TxDataValidReg := io.req.valid + } + .elsewhen(ControlReg(4,2) === 3.U){ // PP_DATA + TxDataReg := Mux(io.req.valid, io.req.bits.dataRequest & maskedData.asUInt, 0.U) + TxDataValidReg := io.req.valid + } + .elsewhen(ControlReg(4,2) === 4.U){ // WR_DI + TxDataReg := Mux(io.req.valid, Cat("b00000100".U, Fill(24,0.B)), 0.U) + TxDataValidReg := io.req.valid + } + + + io.rsp.bits.dataResponse := RegNext(Mux(io.rsp.ready, io.req.bits.addrRequest, 0.U)) + io.rsp.valid := RegNext(1.B) + + // List(io.req.ready, io.rsp.valid) map (_ := 1.B) + // List(io.cs_n, io.sclk, io.mosi) map (_ := DontCare) + } + .elsewhen(io.req.bits.addrRequest(3,0) === 4.U && io.req.bits.isWrite === 0.B){ + io.rsp.bits.dataResponse := RegNext(Mux(io.rsp.ready, TxDataReg, 0.U)) + io.rsp.valid := RegNext(io.req.valid) + + // List(io.req.ready, io.rsp.valid) map (_ := 1.B) + // List(io.cs_n, io.sclk, io.mosi) map (_ := DontCare) + } + .elsewhen(io.req.bits.addrRequest(3,0) === 8.U && io.req.bits.isWrite === 0.B){ + io.rsp.bits.dataResponse := RegNext(Mux(io.rsp.ready, RxDataReg, 0.U)) + io.rsp.valid := RxDataValidReg + // io.rsp.valid := 1.B + + // List(io.req.ready) map (_ := 1.B) + // List(io.cs_n, io.sclk, io.mosi) map (_ := DontCare) + } + .otherwise{ + // List(io.rsp.bits.error, io.rsp.valid) map (_ := 0.B) + // List(io.rsp.valid) map (_ := 0.B) + List(io.cs_n, io.sclk, io.mosi, io.rsp.valid) map (_ := DontCare) + io.rsp.bits.dataResponse := RegNext(io.req.bits.addrRequest) + } + + // ClockGen + def counter(max: UInt) = { + val x = RegInit(0.asUInt(max.getWidth.W)) + x := Mux(x === max, 0.U, x + 1.U) + x + } + def pulse(n: UInt) = counter(n - 1.U) === 0.U + def toggle(p: Bool) = { + val x = RegInit(false.B) + x := Mux(p, !x, x) + x + } + def clockGen(period: UInt) = toggle(pulse(period >> 1)) + // + + // SPI Protocol Logic + val spiProtocol = Module(new Protocol()) + + spiProtocol.clock := clockGen(ControlReg(31,5)).asClock + spiProtocol.io.data_in.bits := TxDataReg + spiProtocol.io.data_in.valid := TxDataValidReg + spiProtocol.io.CPOL := ControlReg(1) + spiProtocol.io.CPHA := ControlReg(0) + spiProtocol.io.miso := io.miso + spiProtocol.io.data_out.ready := 1.B + List(io.mosi, io.sclk, io.cs_n) zip List(spiProtocol.io.mosi, spiProtocol.io.sck, spiProtocol.io.ss) map (a => a._1 := a._2) + when(spiProtocol.io.data_out.valid){ + RxDataReg := spiProtocol.io.data_out.bits + RxDataValidReg := 1.B + } + // + + // Error Logic + val addr_hit = Wire(Vec(3, Bool())) + val spiRegMap = Seq(0,4,8) + val wireAddr = WireInit(io.req.bits.addrRequest(3,0)) + val addr_miss = Wire(Bool()) + + def go(min:Int, max:Int):Unit = { + if (min == max){ + return + }else{ + addr_hit(min) := wireAddr === spiRegMap(min).asUInt() + go(min+1, max) + } + } + + go(0,3) + + + addr_miss := ~addr_hit.reduce(_ | _)//~addr_hit.contains(true.B) + when(wireAddr === 8.U & io.req.bits.isWrite){io.rsp.bits.error := RegNext(io.req.valid)} + .otherwise{io.rsp.bits.error := RegNext(io.req.valid & addr_miss)} + // + +} diff --git a/src/main/scala/jigsaw/peripherals/timer/Timer.scala b/src/main/scala/jigsaw/peripherals/timer/Timer.scala new file mode 100644 index 0000000..067c2d9 --- /dev/null +++ b/src/main/scala/jigsaw/peripherals/timer/Timer.scala @@ -0,0 +1,114 @@ +package jigsaw.peripherals.timer + +import chisel3._ +import chisel3.util._ +import caravan.bus.common.{AbstrRequest, AbstrResponse} + +class Timer_IO[A <: AbstrRequest, B <: AbstrResponse] (gen: A, gen1: B) extends Bundle{ + + // bus interconnect interfaces + val req = Flipped(Decoupled(gen)) + val rsp = Decoupled(gen1) + + val cio_timer_intr_cmp = Output(Bool()) + val cio_timer_intr_ovf = Output(Bool()) +} + + +// timer in chisel +class Timer[A <: AbstrRequest, B <: AbstrResponse] (gen: A, gen1: B) extends Module{ + val io = IO(new Timer_IO(gen,gen1)) + + // registers + val TimerReg = RegInit(0.U(32.W)) // RO 0x0 + val ControlReg = RegInit(0.U(32.W)) // RW 0x4 + val CompareReg = RegInit(0.U(32.W)) // RW 0x8 + val PreCountReg= RegInit(0.U(32.W)) // RO 0xC + + val maskedData = Wire(Vec(4, UInt(8.W))) + maskedData := io.req.bits.activeByteLane.asTypeOf(Vec(4, Bool())) map (Fill(8,_)) + + io.req.ready := 1.B + io.rsp.valid := 0.B + + // io.cio_timer_intr_cmp := DontCare + + when (io.req.bits.addrRequest(3,0) === 0.U && io.req.bits.isWrite === 0.B){ + io.rsp.bits.dataResponse := RegNext(Mux(io.rsp.ready, TimerReg, 0.U)) + io.rsp.valid := RegNext(io.req.valid) + } + .elsewhen (io.req.bits.addrRequest(3,0) === 4.U && io.req.bits.isWrite === 1.B){ + ControlReg := Mux(io.req.valid, io.req.bits.dataRequest & maskedData.asUInt, ControlReg) + + io.rsp.bits.dataResponse := RegNext(Mux(io.rsp.ready, io.req.bits.dataRequest, 0.U)) + io.rsp.valid := RegNext(io.req.valid) + } + .elsewhen (io.req.bits.addrRequest(3,0) === 4.U && io.req.bits.isWrite === 0.B){ + io.rsp.bits.dataResponse := RegNext(Mux(io.rsp.ready, ControlReg, 0.U)) + io.rsp.valid := RegNext(io.req.valid) + } + .elsewhen (io.req.bits.addrRequest(3,0) === 8.U && io.req.bits.isWrite === 1.B){ + CompareReg := Mux(io.req.valid, io.req.bits.dataRequest & maskedData.asUInt, CompareReg) + + io.rsp.bits.dataResponse := RegNext(Mux(io.rsp.ready, io.req.bits.dataRequest, 0.U)) + io.rsp.valid := RegNext(io.req.valid) + } + .elsewhen (io.req.bits.addrRequest(3,0) === 8.U && io.req.bits.isWrite === 0.B){ + io.rsp.bits.dataResponse := RegNext(Mux(io.rsp.ready, CompareReg, 0.U)) + io.rsp.valid := RegNext(io.req.valid) + } + .elsewhen (io.req.bits.addrRequest(3,0) === 8.U && io.req.bits.isWrite === 0.B){ + io.rsp.bits.dataResponse := RegNext(Mux(io.rsp.ready, PreCountReg, 0.U)) + io.rsp.valid := RegNext(io.req.valid) + } + .otherwise{ + List(io.cio_timer_intr_cmp, io.rsp.valid) map (_ := DontCare) + io.rsp.bits.dataResponse := RegNext(io.req.bits.addrRequest) + } + + val enable = WireInit(ControlReg(0)) + val prescalar = WireInit(ControlReg(31,1)) + + // Prescalar+Timer Logic + when(PreCountReg === 0.U && enable){ + PreCountReg := PreCountReg + 1.U + } + .elsewhen(TimerReg === CompareReg || TimerReg === "hffffffff".U){ + TimerReg := 0.U + } + .elsewhen(PreCountReg === prescalar && enable){ + TimerReg := TimerReg + 1.U + PreCountReg := 0.U + }.elsewhen(PreCountReg < prescalar){ + PreCountReg := PreCountReg + 1.U + } + + // Interupts + io.cio_timer_intr_cmp := Mux(enable, TimerReg === CompareReg, 0.B) + io.cio_timer_intr_ovf := Mux(enable, TimerReg === "hffffffff".U, 0.B) + + + + // Error Logic + val addr_hit = Wire(Vec(4, Bool())) + val timerRegMap = Seq(0,4,8,12) + val wireAddr = WireInit(io.req.bits.addrRequest(3,0)) + val addr_miss = Wire(Bool()) + + def go(min:Int, max:Int):Unit = { + if (min == max){ + return + }else{ + addr_hit(min) := wireAddr === timerRegMap(min).asUInt() + go(min+1, max) + } + } + + go(0,4) + + + addr_miss := ~addr_hit.reduce(_ | _)//~addr_hit.contains(true.B) + when(wireAddr === 0.U & io.req.bits.isWrite){io.rsp.bits.error := RegNext(io.req.valid)} + .elsewhen(wireAddr === 12.U & io.req.bits.isWrite){io.rsp.bits.error := RegNext(io.req.valid)} + .otherwise{io.rsp.bits.error := RegNext(io.req.valid & addr_miss)} +} \ No newline at end of file diff --git a/src/main/scala/jigsaw/rams/sram/SRAM1kb.scala b/src/main/scala/jigsaw/rams/sram/SRAM1kb.scala new file mode 100644 index 0000000..fb0a606 --- /dev/null +++ b/src/main/scala/jigsaw/rams/sram/SRAM1kb.scala @@ -0,0 +1,95 @@ +package jigsaw.rams.sram + +import chisel3._ +import chisel3.util._ +import chisel3.experimental._ +import chisel3.util.experimental._ + +import caravan.bus.common.{AbstrRequest, AbstrResponse, BusConfig} + +class SRAM1kb[A <: AbstrRequest, B <: AbstrResponse](gen: A, gen1: B)(programFile:Option[String], val AW:Int = 10) extends Module { + val io = IO(new Bundle { + val req = Flipped(Decoupled(gen)) + val rsp = Decoupled(gen1) + }) + + // the register that sends valid along with the data read from memory + // a register is used so that it synchronizes along with the data that comes after one cycle + val validReg = RegInit(false.B) + io.rsp.valid := validReg + io.rsp.bits.error := false.B // assuming memory controller would never return an error + io.req.ready := true.B // assuming we are always ready to accept requests from device + + val rdata = Wire(UInt(32.W)) + + // the memory + val sram = Module(new sram(programFile=programFile, AW=AW)) + + val clk = WireInit(clock.asUInt()(0)) + + sram.io.clk0 := clk + sram.io.csb0 := 1.B + sram.io.web0 := DontCare + sram.io.wmask0 := DontCare + sram.io.addr0 := DontCare + sram.io.din0 := DontCare + // io.dout0 := a.io.dout0 + + sram.io.clk1 := DontCare + sram.io.csb1 := DontCare + sram.io.addr1 := DontCare + + dontTouch(io.req.valid) + + when(io.req.valid && !io.req.bits.isWrite) { + // READ + // rdata := mem.read(io.req.bits.addrRequest/4.U) + validReg := true.B + sram.io.csb0 := false.B + sram.io.web0 := true.B + sram.io.addr0 := io.req.bits.addrRequest + + rdata := sram.io.dout0 + } .elsewhen(io.req.valid && io.req.bits.isWrite) { + // WRITE + // mem.write(io.req.bits.addrRequest/4.U, wdata, mask) + // validReg := true.B + // rdata map (_ := DontCare) + sram.io.csb0 := false.B + sram.io.web0 := false.B + sram.io.wmask0 := io.req.bits.activeByteLane + sram.io.addr0 := io.req.bits.addrRequest + sram.io.din0 := io.req.bits.dataRequest + validReg := true.B + rdata := DontCare + } .otherwise { + validReg := false.B + // rdata map (_ := DontCare) + rdata := DontCare + } + + io.rsp.bits.dataResponse := rdata +} + +class SRAMIO(AW:Int) extends Bundle { + val clk0 = Input(Bool()) + val csb0 = Input(Bool()) + val web0 = Input(Bool()) + val wmask0 = Input(UInt(4.W)) + val addr0 = Input(UInt(AW.W)) + val din0 = Input(UInt(32.W)) + val dout0 = Output(UInt(32.W)) + + val clk1 = Input(Bool()) + val csb1 = Input(Bool()) + val addr1 = Input(UInt(AW.W)) + val dout1 = Output(UInt(32.W)) + +} +class sram(programFile:Option[String], AW:Int) extends BlackBox( + Map("IFILE" -> {if (programFile.isDefined) programFile.get else ""}, + "ADDR_WIDTH" -> AW) + ) with HasBlackBoxResource { + val io = IO(new SRAMIO(AW=AW)) + addResource("/sram/sram.v") +} \ No newline at end of file diff --git a/src/test/scala/jigsaw/peripherals/programmable_uart/PUartTester.scala b/src/test/scala/jigsaw/peripherals/programmable_uart/PUartTester.scala new file mode 100644 index 0000000..669afd6 --- /dev/null +++ b/src/test/scala/jigsaw/peripherals/programmable_uart/PUartTester.scala @@ -0,0 +1,94 @@ +package jigsaw.peripherals.programmable_uart + +import chisel3._ +import chisel3 . util._ +import caravan.bus.tilelink._ +import org.scalatest._ +import chisel3.experimental._ +import chiseltest._ +import chisel3.experimental.BundleLiterals._ +import chiseltest.experimental.TestOptionBuilder._ +import chiseltest.internal.VerilatorBackendAnnotation +// import jigsaw.peripherals.spi._ +// import jigsaw.SpiHarness +// import caravan.bus.wishbone.WishboneConfig +// import caravan.bus.tilelink.TilelinkConfig +import jigsaw.peripherals.programmable_uart.PUart + +class PUartTester extends FreeSpec with ChiselScalatestTester { + + "Programable Uart Tests" in { + test(new PUart()).withAnnotations(Seq(VerilatorBackendAnnotation)) { c => + + // poke(c.io.CLK_PER_BIT, 4.U) + c.io.CLK_PER_BIT.poke(4.U) + c.io.isStalled.poke(true.B) + // val bufferedSource = Source.fromFile(filePath) + // val fileData = bufferedSource.getLines.toArray + // We create an array insts by reading the lines from the text file and parsing the string + // as hexadecimal. The parse function does not accept 0x literals so we used substring(2) + // to get rid of the first two characters which are 0x finally "yielding" it into an array. +// val insts = for (i <- fileData) yield java.lang.Long.parseLong(i, 16) + // val insts = for (i <- fileData) yield java.lang.Long.parseLong(i.substring(2), 16) + // closing the opened file + // bufferedSource.close + + // poke(c.io.rxd, 1) + c.io.rxd.poke(1.U) + c.clock.step(10) + val insts = Array(0xf0f0f0f0, 0x0f0f0f0f, 0x00000fff) + for (inst <- insts) { + // val inst = 0xf0f0f0f0 + val half_byte1 = inst & 0x0f // 3 + val half_byte2 = (inst & 0xf0) >> 4 // 1 + val byte1 = (half_byte2 << 4) | half_byte1 // 0x13 + + val half_byte3 = (inst & 0xf00) >> 8 // 1 + val half_byte4 = (inst & 0xf000) >> 12 // 0 + val byte2 = (half_byte4 << 4) | half_byte3 // 0x01 + + val half_byte5 = (inst & 0xf0000) >> 16 // 0 + val half_byte6 = (inst & 0xf00000) >> 20 // 2 + val byte3 = (half_byte6 << 4) | half_byte5 // 0x20 + + val half_byte7 = (inst & 0xf000000) >> 24 // 0 + val half_byte8 = (inst & 0xf0000000) >> 28 // 0 + val byte4 = (half_byte8 << 4) | half_byte7 // 0x00 + + //printf("The instruction is %x".format(byte4)) + pokeUart(byte1.toInt) + pokeUart(byte2.toInt) + pokeUart(byte3.toInt) + pokeUart(byte4.toInt) + } + + def pokeUart(value: Int): Unit = { + + // start bit + // poke(c.io.rxd, 0) + c.io.rxd.poke(0.U) + // step(4) + c.clock.step(4) + // 8 data bits + for (i <- 0 until 8) { + // poke(c.io.rxd, (value >> i) & 0x01) + c.io.rxd.poke(((value >> i) & 0x01).U) + // step(4) + c.clock.step(4) + } + // stop bit + // poke(c.io.rxd, 1) + c.io.rxd.poke(1.U) + // step(4) + c.clock.step(4) + } + // step(200) + c.clock.step(200) + + + + + + } + } +} \ No newline at end of file diff --git a/src/test/scala/jigsaw/peripherals/spi/SpiTester.scala b/src/test/scala/jigsaw/peripherals/spi/SpiTester.scala index 571af75..7a6ff58 100644 --- a/src/test/scala/jigsaw/peripherals/spi/SpiTester.scala +++ b/src/test/scala/jigsaw/peripherals/spi/SpiTester.scala @@ -14,6 +14,7 @@ import jigsaw.SpiHarness import caravan.bus.wishbone.WishboneConfig import caravan.bus.tilelink.TilelinkConfig import jigsaw.peripherals.spiflash._ +import jigsaw.peripherals.spi._ class SpiTester extends FreeSpec with ChiselScalatestTester { @@ -53,7 +54,7 @@ class SpiTester extends FreeSpec with ChiselScalatestTester { "Spi Flash" in { implicit val config = WishboneConfig(32,32) // implicit val config = TilelinkConfig() - implicit val spiConfig = jigsaw.peripherals.spiflash.Config() + // implicit val spiConfig = jigsaw.peripherals.spi.Config() test(new SpiHarness()).withAnnotations(Seq(VerilatorBackendAnnotation)) { c => // c.io.req.bits.addrRequest.poke(0.U) // c.io.req.bits.dataRequest.poke(0.U) diff --git a/src/test/scala/jigsaw/peripherals/timer/TimerTester.scala b/src/test/scala/jigsaw/peripherals/timer/TimerTester.scala new file mode 100644 index 0000000..c56acae --- /dev/null +++ b/src/test/scala/jigsaw/peripherals/timer/TimerTester.scala @@ -0,0 +1,48 @@ +package jigsaw.peripherals.timer + +import chisel3._ +import chisel3 . util._ +import caravan.bus.tilelink._ +import org.scalatest._ +import chisel3.experimental._ +import chiseltest._ +import chisel3.experimental.BundleLiterals._ +import chiseltest.experimental.TestOptionBuilder._ +import chiseltest.internal.VerilatorBackendAnnotation +import caravan.bus.wishbone.WishboneConfig +import caravan.bus.tilelink.TilelinkConfig +import jigsaw.peripherals.timer._ +import jigsaw._ +// import TimerHarness + +class TimerTester extends FreeSpec with ChiselScalatestTester { + + "Timer Tests" in { + implicit val config = WishboneConfig(32,32) + // implicit val config = TilelinkConfig() + test(new TimerHarness()) { c => + ///////////Set Tx Register//////////// + c.io.req.bits.addrRequest.poke(8.U) + c.io.req.bits.dataRequest.poke(1.U) + c.io.req.bits.activeByteLane.poke("b1111".U) + c.io.req.bits.isWrite.poke(1.B) + c.io.req.valid.poke(1.B) + c.clock.step(1) + c.io.req.valid.poke(0.B) + // c.clock.step(1) + // c.io.req.bits.addrRequest.poke(4.U) + // c.io.req.bits.dataRequest.poke("b11000".U) + // c.io.req.bits.activeByteLane.poke("b1111".U) + // c.io.req.bits.isWrite.poke(1.B) + // c.io.req.valid.poke(1.B) + c.clock.step(2) + c.io.req.bits.addrRequest.poke(4.U) + c.io.req.bits.dataRequest.poke("b11".U) + c.io.req.bits.activeByteLane.poke("b1111".U) + c.io.req.bits.isWrite.poke(1.B) + c.io.req.valid.poke(1.B) + // c.io.req.valid.poke(0.B) + c.clock.step(200) + } + } +} \ No newline at end of file diff --git a/src/test/scala/jigsaw/rams/sram/SRAMTests.scala b/src/test/scala/jigsaw/rams/sram/SRAMTests.scala new file mode 100644 index 0000000..9c9ad2a --- /dev/null +++ b/src/test/scala/jigsaw/rams/sram/SRAMTests.scala @@ -0,0 +1,77 @@ +package jigsaw.rams.sram + +import chisel3._ +import chisel3.util._ +import org.scalatest._ +import chisel3.experimental._ +import chiseltest._ +import chisel3.experimental.BundleLiterals._ +import chiseltest.experimental.TestOptionBuilder._ +import chiseltest.internal.VerilatorBackendAnnotation +// import org.scalatest.flatspec.AnyFlatSpec +import jigsaw.SramHarness +import caravan.bus.wishbone.WishboneConfig +import caravan.bus.tilelink.TilelinkConfig + +class SRAMTests extends FreeSpec with ChiselScalatestTester { + + def getFile: Option[String] = { + if (scalaTestContext.value.get.configMap.contains("memFile")) { + Some(scalaTestContext.value.get.configMap("memFile").toString) + } else { + None + } + } + + implicit val config = WishboneConfig(32,32) + "SRAM" in { + // val programFile = Some("/home/talha/inst") + val programFile = getFile + // test(new SramHarness(programFile))/*.withAnnotations(Seq(VerilatorBackendAnnotation))*/ { c => + test(new SramHarness(programFile, 10)).withAnnotations(Seq(VerilatorBackendAnnotation)) { c => + c.io.req.valid.poke(1.B) + c.io.req.bits.addrRequest.poke(3.U) + c.io.req.bits.dataRequest.poke("h12345678".U) + c.io.req.bits.activeByteLane.poke("b1000".U) + c.io.req.bits.isWrite.poke(1.B) + c.clock.step(1) + c.io.req.valid.poke(0.B) + c.clock.step(1) + c.io.req.valid.poke(1.B) + c.io.req.bits.isWrite.poke(0.B) + c.io.req.bits.addrRequest.poke(3.U) + + + // c.io.csb0.poke(0.B) + // c.io.web0.poke(0.B) + // c.io.addr0.poke(4.U) + // c.io.din0.poke(8.U) + // c.io.wmask0.poke(15.U) + // // c.clock.step(1) + // // c.io.csb0.poke(1.B) + // c.clock.step(1) + // c.io.csb0.poke(0.B) + // c.io.web0.poke(1.B) + // c.io.addr0.poke(4.U) + // c.clock.step(1) + // c.io.csb0.poke(1.B) + // c.io.web0.poke(0.B) + + // var count = 0 + // while(count != 15){ + // c.io.req.bits.addrRequest.poke(count.U) + // // c.io.req.bits.dataRequest.poke(count.U) + // c.io.req.bits.isWrite.poke(0.B) + // c.clock.step(10) + // count += 1 + // } + + // c.io.req.bits.isWrite.poke(0.B) + // c.io.addr0.poke(3.U) + // c.clock.step(1) + // c.io.addr0.poke(1.U) + + c.clock.step(100) + } + } +}