-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial structure with gateware directory to store cores sources.
Example SpinalHDL core handling ov7670 registered inputs Example litex firmware to access ov7670 control bus
- Loading branch information
Showing
105 changed files
with
2,301 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"name":"sbt","version":"1.6.0","bspVersion":"2.0.0-M5","languages":["scala"],"argv":["/usr/lib/jvm/java-11-openjdk-amd64/bin/java","-Xms100m","-Xmx100m","-classpath","/home/dlobato/.local/share/JetBrains/IdeaIC2022.2/Scala/launcher/sbt-launch.jar","-Dsbt.script=/usr/bin/sbt","xsbt.boot.Boot","-bsp"]} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
ThisBuild / version := "1.0" | ||
ThisBuild / scalaVersion := "2.12.16" | ||
ThisBuild / organization := "org.jderobot" | ||
|
||
val spinalVersion = "1.7.3" | ||
val spinalCore = "com.github.spinalhdl" %% "spinalhdl-core" % spinalVersion | ||
val spinalLib = "com.github.spinalhdl" %% "spinalhdl-lib" % spinalVersion | ||
val spinalIdslPlugin = compilerPlugin("com.github.spinalhdl" %% "spinalhdl-idsl-plugin" % spinalVersion) | ||
val scalatest = "org.scalatest" %% "scalatest-funsuite" % "3.2.14" % "test" | ||
|
||
lazy val mylib = (project in file(".")) | ||
.settings( | ||
name := "fpga-robotics", | ||
Compile / scalaSource := baseDirectory.value / "gateware" / "main" / "scala", | ||
Test / scalaSource := baseDirectory.value / "gateware" / "test" / "scala", | ||
libraryDependencies ++= Seq(spinalCore, spinalLib, spinalIdslPlugin) | ||
) | ||
|
||
fork := true |
Binary file not shown.
Binary file not shown.
73 changes: 73 additions & 0 deletions
73
gateware/main/scala/fpga_robotics/video/input/OV7670.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package fpga_robotics.video.input | ||
|
||
import spinal.core._ | ||
import spinal.lib.graphic.Rgb | ||
import spinal.lib.{Flow, _} | ||
|
||
case class OV7670CAMIF() extends Bundle with IMasterSlave { | ||
val pclk = Bool() | ||
val vsync = Bool() | ||
val href = Bool() | ||
val data = Bits(8 bits) | ||
|
||
override def asMaster(): Unit = { | ||
out(pclk) | ||
out(vsync) | ||
out(href) | ||
out(data) | ||
} | ||
|
||
def slaveResync(): OV7670CAMIF = { | ||
val ret = cloneOf(this) | ||
ret := BufferCC(this) | ||
ret | ||
} | ||
|
||
def toFlow(): Flow[OV7670CAMIF] = { | ||
val f = Flow(OV7670CAMIF()) | ||
f.valid := pclk.rise() | ||
f.pclk := pclk | ||
f.vsync := vsync | ||
f.href := href | ||
f.data := data | ||
f | ||
} | ||
|
||
def toFlowInSync(): Flow[OV7670CAMIF] = { | ||
val f = Flow(OV7670CAMIF()) | ||
val inSync = RegNextWhen(True, vsync.rise(), False) | ||
f.valid := pclk.rise() & (inSync | vsync.rise()) | ||
f.pclk := pclk | ||
f.vsync := vsync | ||
f.href := href | ||
f.data := data | ||
f | ||
} | ||
} | ||
|
||
case class OV7670() extends Component { | ||
val io = new Bundle { | ||
val camif: OV7670CAMIF = slave(OV7670CAMIF()) | ||
val frame_count = out UInt(32 bits) | ||
} | ||
|
||
val camif = io.camif.slaveResync() | ||
|
||
val counter = Counter(32 bits) | ||
when(camif.toFlowInSync().fire) { | ||
when(camif.vsync.rise()) { | ||
counter.increment() | ||
} | ||
} | ||
|
||
io.frame_count := counter | ||
} | ||
|
||
object OV7670 { | ||
def main(args: Array[String]): Unit = { | ||
val outRtlDir = if (!args.isEmpty) args(0) else "gateware/main/verilog/video/input" | ||
SpinalConfig( | ||
targetDirectory = outRtlDir, | ||
).generateVerilog(OV7670()) | ||
} | ||
} |
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
// Generator : SpinalHDL v1.7.3 git head : aeaeece704fe43c766e0d36a93f2ecbb8a9f2003 | ||
// Component : OV7670 | ||
// Git hash : ec22d55dd561d6161102dac82b90d4fa1fa8591f | ||
|
||
`timescale 1ns/1ps | ||
|
||
module OV7670 ( | ||
input io_camif_pclk, | ||
input io_camif_vsync, | ||
input io_camif_href, | ||
input [7:0] io_camif_data, | ||
output [31:0] io_frame_count, | ||
input clk, | ||
input reset | ||
); | ||
|
||
wire io_camif_buffercc_io_dataOut_pclk; | ||
wire io_camif_buffercc_io_dataOut_vsync; | ||
wire io_camif_buffercc_io_dataOut_href; | ||
wire [7:0] io_camif_buffercc_io_dataOut_data; | ||
wire [31:0] _zz_counter_valueNext; | ||
wire [0:0] _zz_counter_valueNext_1; | ||
wire camif_pclk; | ||
wire camif_vsync; | ||
wire camif_href; | ||
wire [7:0] camif_data; | ||
reg counter_willIncrement; | ||
wire counter_willClear; | ||
reg [31:0] counter_valueNext; | ||
reg [31:0] counter_value; | ||
wire counter_willOverflowIfInc; | ||
wire counter_willOverflow; | ||
reg camif_vsync_regNext; | ||
wire when_OV7670_l38; | ||
reg _zz_1; | ||
reg camif_pclk_regNext; | ||
reg camif_vsync_regNext_1; | ||
reg camif_vsync_regNext_2; | ||
wire when_OV7670_l58; | ||
|
||
assign _zz_counter_valueNext_1 = counter_willIncrement; | ||
assign _zz_counter_valueNext = {31'd0, _zz_counter_valueNext_1}; | ||
BufferCC io_camif_buffercc ( | ||
.io_dataIn_pclk (io_camif_pclk ), //i | ||
.io_dataIn_vsync (io_camif_vsync ), //i | ||
.io_dataIn_href (io_camif_href ), //i | ||
.io_dataIn_data (io_camif_data[7:0] ), //i | ||
.io_dataOut_pclk (io_camif_buffercc_io_dataOut_pclk ), //o | ||
.io_dataOut_vsync (io_camif_buffercc_io_dataOut_vsync ), //o | ||
.io_dataOut_href (io_camif_buffercc_io_dataOut_href ), //o | ||
.io_dataOut_data (io_camif_buffercc_io_dataOut_data[7:0]), //o | ||
.clk (clk ), //i | ||
.reset (reset ) //i | ||
); | ||
assign camif_pclk = io_camif_buffercc_io_dataOut_pclk; | ||
assign camif_vsync = io_camif_buffercc_io_dataOut_vsync; | ||
assign camif_href = io_camif_buffercc_io_dataOut_href; | ||
assign camif_data = io_camif_buffercc_io_dataOut_data; | ||
always @(*) begin | ||
counter_willIncrement = 1'b0; | ||
if(((camif_pclk && (! camif_pclk_regNext)) && (_zz_1 || (camif_vsync && (! camif_vsync_regNext_1))))) begin | ||
if(when_OV7670_l58) begin | ||
counter_willIncrement = 1'b1; | ||
end | ||
end | ||
end | ||
|
||
assign counter_willClear = 1'b0; | ||
assign counter_willOverflowIfInc = (counter_value == 32'hffffffff); | ||
assign counter_willOverflow = (counter_willOverflowIfInc && counter_willIncrement); | ||
always @(*) begin | ||
counter_valueNext = (counter_value + _zz_counter_valueNext); | ||
if(counter_willClear) begin | ||
counter_valueNext = 32'h0; | ||
end | ||
end | ||
|
||
assign when_OV7670_l38 = (camif_vsync && (! camif_vsync_regNext)); | ||
assign when_OV7670_l58 = (camif_vsync && (! camif_vsync_regNext_2)); | ||
assign io_frame_count = counter_value; | ||
always @(posedge clk or posedge reset) begin | ||
if(reset) begin | ||
counter_value <= 32'h0; | ||
_zz_1 <= 1'b0; | ||
end else begin | ||
counter_value <= counter_valueNext; | ||
if(when_OV7670_l38) begin | ||
_zz_1 <= 1'b1; | ||
end | ||
end | ||
end | ||
|
||
always @(posedge clk) begin | ||
camif_vsync_regNext <= camif_vsync; | ||
camif_pclk_regNext <= camif_pclk; | ||
camif_vsync_regNext_1 <= camif_vsync; | ||
end | ||
|
||
always @(posedge clk) begin | ||
camif_vsync_regNext_2 <= camif_vsync; | ||
end | ||
|
||
|
||
endmodule | ||
|
||
module BufferCC ( | ||
input io_dataIn_pclk, | ||
input io_dataIn_vsync, | ||
input io_dataIn_href, | ||
input [7:0] io_dataIn_data, | ||
output io_dataOut_pclk, | ||
output io_dataOut_vsync, | ||
output io_dataOut_href, | ||
output [7:0] io_dataOut_data, | ||
input clk, | ||
input reset | ||
); | ||
|
||
(* async_reg = "true" *) reg buffers_0_pclk; | ||
(* async_reg = "true" *) reg buffers_0_vsync; | ||
(* async_reg = "true" *) reg buffers_0_href; | ||
(* async_reg = "true" *) reg [7:0] buffers_0_data; | ||
(* async_reg = "true" *) reg buffers_1_pclk; | ||
(* async_reg = "true" *) reg buffers_1_vsync; | ||
(* async_reg = "true" *) reg buffers_1_href; | ||
(* async_reg = "true" *) reg [7:0] buffers_1_data; | ||
|
||
assign io_dataOut_pclk = buffers_1_pclk; | ||
assign io_dataOut_vsync = buffers_1_vsync; | ||
assign io_dataOut_href = buffers_1_href; | ||
assign io_dataOut_data = buffers_1_data; | ||
always @(posedge clk) begin | ||
buffers_0_pclk <= io_dataIn_pclk; | ||
buffers_0_vsync <= io_dataIn_vsync; | ||
buffers_0_href <= io_dataIn_href; | ||
buffers_0_data <= io_dataIn_data; | ||
buffers_1_pclk <= buffers_0_pclk; | ||
buffers_1_vsync <= buffers_0_vsync; | ||
buffers_1_href <= buffers_0_href; | ||
buffers_1_data <= buffers_0_data; | ||
end | ||
|
||
|
||
endmodule |
33 changes: 33 additions & 0 deletions
33
gateware/test/scala/fpga_robotics/video/input/OV7670Test.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package fpga_robotics.video.input | ||
|
||
import org.scalatest.funsuite.AnyFunSuite | ||
import spinal.core.sim._ | ||
|
||
class OV7670Test extends AnyFunSuite { | ||
val compiled: SimCompiled[OV7670] = SimConfig.withWave.compile(OV7670()) | ||
|
||
test("frame count") { | ||
compiled.doSim{ dut => | ||
dut.clockDomain.forkStimulus(10) | ||
|
||
dut.io.camif.pclk #= false | ||
dut.io.camif.vsync #= false | ||
dut.io.camif.href #= false | ||
|
||
val pclkThread = fork { | ||
while (true) { | ||
dut.clockDomain.waitSampling(4) | ||
dut.io.camif.pclk #= !dut.io.camif.pclk.toBoolean | ||
} | ||
} | ||
|
||
dut.clockDomain.waitSampling(10) | ||
|
||
for(i <- 0 until 100) { | ||
waitUntil(dut.io.camif.pclk.toBoolean) | ||
dut.io.camif.vsync #= !dut.io.camif.vsync.toBoolean | ||
dut.clockDomain.waitSampling(16) | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
sbt.version=1.6.0 |
Empty file.
Oops, something went wrong.