Initial commit
This commit is contained in:
parent
ff795d2b6e
commit
2fbacc0544
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
build
|
||||||
|
*~
|
||||||
|
GPATH
|
||||||
|
GRTAGS
|
||||||
|
GTAGS
|
||||||
|
TAGS
|
||||||
56
Makefile
Normal file
56
Makefile
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
SOURCES = $(wildcard source/*.sv)
|
||||||
|
TOP = sugar_lissajous
|
||||||
|
PCF = icesugar.pcf
|
||||||
|
|
||||||
|
FAMILY = up5k
|
||||||
|
PACKAGE = sg48
|
||||||
|
FREQ = 30
|
||||||
|
|
||||||
|
#DOSVG = --placed-svg place.svg --routed-svg route.svg
|
||||||
|
# nextpnr --randomize-seed write_verilog $(TOP).v
|
||||||
|
|
||||||
|
BUILD_DIR ?= build
|
||||||
|
|
||||||
|
TOP_BIN = $(BUILD_DIR)/$(TOP).bin
|
||||||
|
TOP_ASC = $(BUILD_DIR)/$(TOP).asc
|
||||||
|
TOP_JSON = $(BUILD_DIR)/$(TOP).json
|
||||||
|
|
||||||
|
all: $(TOP_BIN)
|
||||||
|
|
||||||
|
# Make bitstream
|
||||||
|
$(TOP_BIN): $(TOP_ASC)
|
||||||
|
icepack $(TOP_ASC) $(TOP_BIN)
|
||||||
|
|
||||||
|
# Place and rouite
|
||||||
|
$(TOP_ASC): $(TOP_JSON) $(PCF)
|
||||||
|
nextpnr-ice40 -q -l $(BUILD_DIR)/nextpnr.log --$(FAMILY) --package $(PACKAGE) \
|
||||||
|
--freq $(FREQ) --top $(TOP) --pcf $(PCF) --asc $(TOP_ASC) --json $(TOP_JSON) \
|
||||||
|
$(DOSVG)
|
||||||
|
|
||||||
|
# Synthesys
|
||||||
|
$(TOP_JSON): $(SOURCES)
|
||||||
|
mkdir -p $(BUILD_DIR)
|
||||||
|
yosys -q -l $(BUILD_DIR)/yosys.log -p \
|
||||||
|
"proc; alumacc; share -fast; opt -full; synth_ice40 -top $(TOP) -json $(TOP_JSON) -abc2" \
|
||||||
|
$(SOURCES)
|
||||||
|
|
||||||
|
# Timing analysis
|
||||||
|
timing: $(TOP_ASC)
|
||||||
|
icetime -d $(FAMILY) -t -c $(FREQ) -r $(BUILD_DIR)/timing.log $(TOP_ASC)
|
||||||
|
|
||||||
|
# Program
|
||||||
|
prog: $(TOP_BIN)
|
||||||
|
icesprog -w $(TOP_BIN)
|
||||||
|
|
||||||
|
# Clean
|
||||||
|
clean:
|
||||||
|
rm -rf $(BUILD_DIR)
|
||||||
|
|
||||||
|
# Convert SVG to PNG
|
||||||
|
png: route.png place.png
|
||||||
|
|
||||||
|
route.png: route.svg
|
||||||
|
inkscape --export-type=png -o route.png -D -d 100 route.svg
|
||||||
|
|
||||||
|
place.png: place.svg
|
||||||
|
inkscape --export-type=png -o place.png -D -d 150 place.svg
|
||||||
16
README.md
Normal file
16
README.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
Light-organ based on [iCESugar 1.5](https://github.com/wuxx/icesugar)
|
||||||
|
board (Lattice iCE40UP5k), nameless SPI TFT LCD display from AliExpress,
|
||||||
|
and sound capture board [Dual MCP3102](https://github.com/punzik/dual-mcp3201-pmod).
|
||||||
|
|
||||||
|
Project is synthesized by [Yosys](https://github.com/YosysHQ/yosys), routed and
|
||||||
|
placed by [nextpnr](https://github.com/YosysHQ/nextpnr), verefied by
|
||||||
|
[iverilog](https://github.com/steveicarus/iverilog) and
|
||||||
|
[verilator](https://github.com/verilator/verilator). For scripting, prototyping and
|
||||||
|
GUI use [Racket](https://racket-lang.org/) and [GNU
|
||||||
|
Octave](https://www.gnu.org/software/octave/index).
|
||||||
|
|
||||||
|
Video 1: https://youtu.be/R9meEMrbPAM
|
||||||
|
|
||||||
|
Video 2: https://youtu.be/H2083E0BFIM
|
||||||
|
|
||||||
|

|
||||||
BIN
doc/ILI9341 Datasheet.pdf
Normal file
BIN
doc/ILI9341 Datasheet.pdf
Normal file
Binary file not shown.
61
icesugar.pcf
Normal file
61
icesugar.pcf
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
# iCESugar Board (iCE40UP5K-QFN48)
|
||||||
|
|
||||||
|
set_io -nowarn LED_R_N 39
|
||||||
|
set_io -nowarn LED_G_N 40
|
||||||
|
set_io -nowarn LED_B_N 41
|
||||||
|
|
||||||
|
set_io -nowarn SW[0] 18
|
||||||
|
set_io -nowarn SW[1] 19
|
||||||
|
set_io -nowarn SW[2] 20
|
||||||
|
set_io -nowarn SW[3] 21
|
||||||
|
|
||||||
|
set_io -nowarn CLK12 35
|
||||||
|
|
||||||
|
set_io -nowarn UART_RX 4
|
||||||
|
set_io -nowarn UART_TX 6
|
||||||
|
|
||||||
|
set_io -nowarn USB_DP 10
|
||||||
|
set_io -nowarn USB_DN 9
|
||||||
|
set_io -nowarn USB_PUP 11
|
||||||
|
|
||||||
|
# PMOD 1
|
||||||
|
set_io -nowarn P1_1 10
|
||||||
|
set_io -nowarn P1_2 6
|
||||||
|
set_io -nowarn P1_3 3
|
||||||
|
set_io -nowarn P1_4 48
|
||||||
|
set_io -nowarn P1_9 47
|
||||||
|
set_io -nowarn P1_10 2
|
||||||
|
set_io -nowarn P1_11 4
|
||||||
|
set_io -nowarn P1_12 9
|
||||||
|
|
||||||
|
# PMOD 2
|
||||||
|
set_io -nowarn P2_1 46
|
||||||
|
set_io -nowarn P2_2 44
|
||||||
|
set_io -nowarn P2_3 42
|
||||||
|
set_io -nowarn P2_4 37
|
||||||
|
set_io -nowarn P2_9 36
|
||||||
|
set_io -nowarn P2_10 38
|
||||||
|
set_io -nowarn P2_11 43
|
||||||
|
set_io -nowarn P2_12 45
|
||||||
|
|
||||||
|
# PMOD 3
|
||||||
|
set_io -nowarn P3_1 34
|
||||||
|
set_io -nowarn P3_2 31
|
||||||
|
set_io -nowarn P3_3 27
|
||||||
|
set_io -nowarn P3_4 25
|
||||||
|
set_io -nowarn P3_9 23
|
||||||
|
set_io -nowarn P3_10 26
|
||||||
|
set_io -nowarn P3_11 28
|
||||||
|
set_io -nowarn P3_12 32
|
||||||
|
|
||||||
|
# PMOD 4
|
||||||
|
set_io -nowarn P4_1 21
|
||||||
|
set_io -nowarn P4_2 20
|
||||||
|
set_io -nowarn P4_3 19
|
||||||
|
set_io -nowarn P4_4 18
|
||||||
|
|
||||||
|
#spi
|
||||||
|
set_io -nowarn SPI_SS 16
|
||||||
|
set_io -nowarn SPI_SCK 15
|
||||||
|
set_io -nowarn SPI_MOSI 17
|
||||||
|
set_io -nowarn SPI_MISO 14
|
||||||
5
source/.dir-locals.el
Normal file
5
source/.dir-locals.el
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
;;; Directory Local Variables
|
||||||
|
;;; For more information see (info "(emacs) Directory Variables")
|
||||||
|
|
||||||
|
((verilog-mode . ((flycheck-verilator-include-path . ("." "../../local/share/yosys/ice40"))
|
||||||
|
(verilog-library-directories . ("." "../../local/share/yosys/ice40")))))
|
||||||
9
source/assert.vh
Normal file
9
source/assert.vh
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
`ifndef _ASSERT_VH_
|
||||||
|
`define _ASSERT_VH_
|
||||||
|
|
||||||
|
`define assert(assertion) \
|
||||||
|
if (!(assertion)) begin \
|
||||||
|
$error("ERROR: Assertion failed in %m: assertion");\
|
||||||
|
end
|
||||||
|
|
||||||
|
`endif
|
||||||
29
source/circle-table.rkt
Normal file
29
source/circle-table.rkt
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#lang racket
|
||||||
|
|
||||||
|
(define (gen-circle-quadrant len)
|
||||||
|
(map (lambda (n)
|
||||||
|
(let ((angle (/ (* 2 pi n) len)))
|
||||||
|
(cons (sin angle)
|
||||||
|
(cos angle))))
|
||||||
|
(range (/ len 4))))
|
||||||
|
|
||||||
|
(define (print-xy-table table)
|
||||||
|
(define (->hex x)
|
||||||
|
(~a (number->string (inexact->exact (round x)) 16)
|
||||||
|
#:min-width 2 #:align 'right #:pad-string "0"))
|
||||||
|
(for-each
|
||||||
|
(lambda (c)
|
||||||
|
(printf "~a~a\n"
|
||||||
|
(->hex (* 255 (car c)))
|
||||||
|
(->hex (* 255 (cdr c)))))
|
||||||
|
table))
|
||||||
|
|
||||||
|
;;; MAIN
|
||||||
|
(let ((x0 0)
|
||||||
|
(y0 0)
|
||||||
|
(len 1024))
|
||||||
|
|
||||||
|
(with-output-to-file (format "quadrant_~a.rom" (/ len 4))
|
||||||
|
(lambda ()
|
||||||
|
(print-xy-table
|
||||||
|
(gen-circle-quadrant len)))))
|
||||||
82
source/circle_1024.sv
Normal file
82
source/circle_1024.sv
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
module circle_1024
|
||||||
|
(input wire clock,
|
||||||
|
input wire reset,
|
||||||
|
|
||||||
|
input wire [9:0] angle,
|
||||||
|
input wire [7:0] r,
|
||||||
|
input wire [7:0] x0,
|
||||||
|
input wire [7:0] y0,
|
||||||
|
|
||||||
|
output wire [7:0] x,
|
||||||
|
output wire [7:0] y,
|
||||||
|
|
||||||
|
input wire req_i,
|
||||||
|
output reg ack_o);
|
||||||
|
|
||||||
|
localparam QUADR_LEN = 256;
|
||||||
|
localparam QUADR_ROM_FILE = "quadrant_256.rom";
|
||||||
|
localparam QUADR_CW = $clog2(QUADR_LEN);
|
||||||
|
logic [15:0] q_rom[QUADR_LEN];
|
||||||
|
initial $readmemh(QUADR_ROM_FILE, q_rom, 0, QUADR_LEN-1);
|
||||||
|
|
||||||
|
logic [QUADR_CW-1:0] q_addr;
|
||||||
|
logic [7:0] kx, ky;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
{kx, ky} <= q_rom[q_addr];
|
||||||
|
|
||||||
|
logic [15:0] macx_o, macy_o;
|
||||||
|
logic xsub, ysub;
|
||||||
|
|
||||||
|
ice40_2mac8x8 circle_mac
|
||||||
|
(.clock, .reset,
|
||||||
|
.a0(r),
|
||||||
|
.b0(kx),
|
||||||
|
.s0({x0, 8'b0}),
|
||||||
|
.sub0(xsub),
|
||||||
|
.y0(macx_o),
|
||||||
|
|
||||||
|
.a1(r),
|
||||||
|
.b1(ky),
|
||||||
|
.s1({y0, 8'b0}),
|
||||||
|
.sub1(ysub),
|
||||||
|
.y1(macy_o));
|
||||||
|
|
||||||
|
assign q_addr = angle[8] ? 8'd255 - angle[7:0] : angle[7:0];
|
||||||
|
assign xsub = angle[9];
|
||||||
|
assign ysub = angle[8] == angle[9] ? 1'b0 : 1'b1;
|
||||||
|
assign x = macx_o[15:8];
|
||||||
|
assign y = macy_o[15:8];
|
||||||
|
|
||||||
|
enum int unsigned {
|
||||||
|
ST_IDLE = 0,
|
||||||
|
ST_GET_K,
|
||||||
|
ST_MAC
|
||||||
|
} state;
|
||||||
|
|
||||||
|
always_ff @(posedge clock, posedge reset)
|
||||||
|
if (reset) begin
|
||||||
|
state <= ST_IDLE;
|
||||||
|
ack_o <= 1'b0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
case (state)
|
||||||
|
ST_IDLE:
|
||||||
|
if (req_i)
|
||||||
|
state <= ST_GET_K;
|
||||||
|
|
||||||
|
ST_GET_K: begin
|
||||||
|
ack_o <= 1'b1;
|
||||||
|
state <= ST_MAC;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_MAC: begin
|
||||||
|
ack_o <= 1'b0;
|
||||||
|
state <= ST_IDLE;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
endmodule // circle
|
||||||
8
source/fig_circle_8x8.rom
Normal file
8
source/fig_circle_8x8.rom
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
00 00 3f 3f 3f 3f 00 00
|
||||||
|
00 3f 7f 7f 7f 7f 3f 00
|
||||||
|
3f 7f bf bf bf bf 7f 3f
|
||||||
|
3f 7f bf ff ff bf 7f 3f
|
||||||
|
3f 7f bf ff ff bf 7f 3f
|
||||||
|
3f 7f bf bf bf bf 7f 3f
|
||||||
|
00 3f 7f 7f 7f 7f 3f 00
|
||||||
|
00 00 3f 3f 3f 3f 00 00
|
||||||
223
source/fig_drawer.sv
Normal file
223
source/fig_drawer.sv
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
`default_nettype none
|
||||||
|
`include "assert.vh"
|
||||||
|
|
||||||
|
module fig_drawer #(parameter FIG_W = 8,
|
||||||
|
parameter FIG_H = 8,
|
||||||
|
parameter FIG_ROM_FILE = "fig_circle_8x8.rom")
|
||||||
|
(input wire clock,
|
||||||
|
input wire reset,
|
||||||
|
|
||||||
|
input wire [7:0] x_i,
|
||||||
|
input wire [8:0] y_i,
|
||||||
|
input wire [7:0] h_i,
|
||||||
|
input wire [7:0] s_i,
|
||||||
|
input wire [7:0] v_i,
|
||||||
|
input wire req_i,
|
||||||
|
output reg ack_o,
|
||||||
|
|
||||||
|
output reg [7:0] fb_x_o,
|
||||||
|
output reg [8:0] fb_y_o,
|
||||||
|
output reg [15:0] fb_color_o,
|
||||||
|
output reg fb_req_o,
|
||||||
|
input wire fb_ack_i);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
`assert(FIG_W > 0);
|
||||||
|
`assert(FIG_H > 0);
|
||||||
|
|
||||||
|
/* Check power of 2 */
|
||||||
|
`assert(FIG_W == 1 << $clog2(FIG_W));
|
||||||
|
`assert(FIG_H == 1 << $clog2(FIG_H));
|
||||||
|
end
|
||||||
|
|
||||||
|
/* Figure bitmap */
|
||||||
|
localparam FIG_SIZE = FIG_W * FIG_H;
|
||||||
|
localparam FIG_W_CW = $clog2(FIG_W);
|
||||||
|
localparam FIG_H_CW = $clog2(FIG_H);
|
||||||
|
localparam FIG_CW = $clog2(FIG_SIZE);
|
||||||
|
|
||||||
|
logic [7:0] fig[FIG_SIZE];
|
||||||
|
initial $readmemh(FIG_ROM_FILE, fig, 0, FIG_SIZE-1);
|
||||||
|
|
||||||
|
logic [FIG_CW-1:0] fig_addr;
|
||||||
|
logic [7:0] fig_data;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
fig_data <= fig[fig_addr];
|
||||||
|
|
||||||
|
/* Scale brightness */
|
||||||
|
logic [31:0] mac_v_o;
|
||||||
|
logic [7:0] fig_v;
|
||||||
|
|
||||||
|
assign fig_v = mac_v_o[15:8];
|
||||||
|
|
||||||
|
ice40_mac16x16 mac_v
|
||||||
|
(.clock, .reset,
|
||||||
|
.a({8'b0, fig_data}),
|
||||||
|
.b({8'b0, v_i}),
|
||||||
|
.s(32'b0),
|
||||||
|
.sub(1'b0),
|
||||||
|
.y(mac_v_o));
|
||||||
|
|
||||||
|
/* Convert HSV ro RGB */
|
||||||
|
logic hsv_ready;
|
||||||
|
logic rgb_valid;
|
||||||
|
logic [7:0] r, g, b;
|
||||||
|
|
||||||
|
hsv2rgb hsv2rgb_i
|
||||||
|
(.clock, .reset,
|
||||||
|
.h(h_i), .s(s_i), .v(fig_v),
|
||||||
|
.ready_i(hsv_ready),
|
||||||
|
.r(r), .g(g), .b(b),
|
||||||
|
.valid_o(rgb_valid));
|
||||||
|
|
||||||
|
/* FSM states */
|
||||||
|
enum int unsigned {
|
||||||
|
ST_IDLE = 0, // 0
|
||||||
|
ST_READ_PIX, // 1
|
||||||
|
ST_MULT_V, // 2
|
||||||
|
ST_HSV_READY, // 3
|
||||||
|
ST_RGB_WAIT, // 4
|
||||||
|
ST_WAIT_FB, // 5
|
||||||
|
ST_NEXT_PIXEL, // 6
|
||||||
|
ST_DONE // 7
|
||||||
|
} state, next;
|
||||||
|
|
||||||
|
/* FSM sync part */
|
||||||
|
always_ff @(posedge clock, posedge reset)
|
||||||
|
if (reset) state <= ST_IDLE;
|
||||||
|
else state <= next;
|
||||||
|
|
||||||
|
/* Pixel coordinate */
|
||||||
|
logic [FIG_W_CW-1:0] pix_x;
|
||||||
|
logic [FIG_H_CW-1:0] pix_y;
|
||||||
|
logic pix_reset, pix_next;
|
||||||
|
|
||||||
|
assign fig_addr = {pix_y, pix_x};
|
||||||
|
|
||||||
|
always_ff @(posedge clock)
|
||||||
|
if (pix_reset) begin
|
||||||
|
pix_x <= '0;
|
||||||
|
pix_y <= '0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if (pix_next)
|
||||||
|
if (pix_x == FIG_H_CW'(FIG_H-1)) begin
|
||||||
|
pix_x <= '0;
|
||||||
|
|
||||||
|
if (pix_y == FIG_W_CW'(FIG_W-1))
|
||||||
|
pix_y <= '0;
|
||||||
|
else
|
||||||
|
pix_y <= pix_y + 1'b1;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
pix_x <= pix_x + 1'b1;
|
||||||
|
|
||||||
|
/* Frame buffer control */
|
||||||
|
logic [7:0] fb_x;
|
||||||
|
logic [8:0] fb_y;
|
||||||
|
logic [15:0] fb_color;
|
||||||
|
logic fb_hold, fb_restore;
|
||||||
|
logic fb_req;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock, posedge reset)
|
||||||
|
if (reset)
|
||||||
|
fb_req_o <= 1'b0;
|
||||||
|
else
|
||||||
|
if (fb_req)
|
||||||
|
fb_req_o <= 1'b1;
|
||||||
|
else
|
||||||
|
if (fb_ack_i)
|
||||||
|
fb_req_o <= 1'b0;
|
||||||
|
|
||||||
|
assign fb_x = x_i + 8'(pix_x);
|
||||||
|
assign fb_y = y_i + 9'(pix_y);
|
||||||
|
|
||||||
|
always_ff @ (posedge clock) begin
|
||||||
|
if (rgb_valid) begin
|
||||||
|
fb_color <= {r[7:3], g[7:2], b[7:3]};
|
||||||
|
|
||||||
|
if (~fb_hold)
|
||||||
|
fb_color_o <= {r[7:3], g[7:2], b[7:3]};
|
||||||
|
end
|
||||||
|
|
||||||
|
if (fb_restore)
|
||||||
|
fb_color_o <= fb_color;
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
if (fb_req) begin
|
||||||
|
fb_x_o <= fb_x;
|
||||||
|
fb_y_o <= fb_y;
|
||||||
|
end
|
||||||
|
|
||||||
|
/* FSM comb part */
|
||||||
|
always_comb begin
|
||||||
|
next = state;
|
||||||
|
pix_reset = 1'b0;
|
||||||
|
pix_next = 1'b0;
|
||||||
|
fb_req = 1'b0;
|
||||||
|
fb_hold = 1'b0;
|
||||||
|
fb_restore = 1'b0;
|
||||||
|
ack_o = 1'b0;
|
||||||
|
hsv_ready = 1'b0;
|
||||||
|
|
||||||
|
case (state)
|
||||||
|
ST_IDLE:
|
||||||
|
if (req_i) begin
|
||||||
|
pix_reset = 1'b1;
|
||||||
|
next = ST_READ_PIX;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_READ_PIX:
|
||||||
|
next = ST_MULT_V;
|
||||||
|
|
||||||
|
ST_MULT_V:
|
||||||
|
if (fig_data == '0) begin
|
||||||
|
pix_next = 1'b1;
|
||||||
|
next = ST_NEXT_PIXEL;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
next = ST_HSV_READY;
|
||||||
|
|
||||||
|
ST_HSV_READY: begin
|
||||||
|
hsv_ready = 1'b1;
|
||||||
|
next = ST_RGB_WAIT;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_RGB_WAIT:
|
||||||
|
if (rgb_valid) begin
|
||||||
|
if (fb_req_o && !fb_ack_i) begin
|
||||||
|
fb_hold = 1'b1;
|
||||||
|
next = ST_WAIT_FB;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
fb_req = 1'b1;
|
||||||
|
pix_next = 1'b1;
|
||||||
|
next = ST_NEXT_PIXEL;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_WAIT_FB:
|
||||||
|
if (fb_ack_i) begin
|
||||||
|
fb_restore = 1'b1;
|
||||||
|
fb_req = 1'b1;
|
||||||
|
pix_next = 1'b1;
|
||||||
|
next = ST_NEXT_PIXEL;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_NEXT_PIXEL:
|
||||||
|
if (pix_x == '0 && pix_y == '0)
|
||||||
|
next = ST_DONE;
|
||||||
|
else
|
||||||
|
next = ST_MULT_V;
|
||||||
|
|
||||||
|
ST_DONE: begin
|
||||||
|
ack_o = 1'b1;
|
||||||
|
next = ST_IDLE;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // fig_drawer
|
||||||
168
source/fig_ring.sv
Normal file
168
source/fig_ring.sv
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
`default_nettype none
|
||||||
|
`include "assert.vh"
|
||||||
|
|
||||||
|
module fig_ring #(parameter POINT_COUNT = 32,
|
||||||
|
parameter FADING = 1)
|
||||||
|
(input wire clock,
|
||||||
|
input wire reset,
|
||||||
|
|
||||||
|
input wire [7:0] pt_x,
|
||||||
|
input wire [7:0] pt_y,
|
||||||
|
input wire [7:0] pt_h,
|
||||||
|
input wire pt_req_i,
|
||||||
|
output reg pt_ack_o,
|
||||||
|
|
||||||
|
output reg [7:0] fig_x_o,
|
||||||
|
output reg [8:0] fig_y_o,
|
||||||
|
output reg [7:0] fig_h_o,
|
||||||
|
output reg [7:0] fig_s_o,
|
||||||
|
output reg [7:0] fig_v_o,
|
||||||
|
output reg fig_req_o,
|
||||||
|
input wire fig_ack_i);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
`assert(POINT_COUNT > 0);
|
||||||
|
`assert(POINT_COUNT == (1 << $clog2(POINT_COUNT)));
|
||||||
|
end
|
||||||
|
|
||||||
|
/* Points coordinate RAM */
|
||||||
|
localparam POINT_CW = $clog2(POINT_COUNT);
|
||||||
|
localparam [7:0] V_INC = FADING == 0 ? 8'd255 : 8'('h100 / POINT_COUNT);
|
||||||
|
|
||||||
|
logic [23:0] pt_ram[POINT_COUNT];
|
||||||
|
logic [POINT_CW-1:0] pt_raddr;
|
||||||
|
logic [POINT_CW-1:0] pt_waddr;
|
||||||
|
logic pt_wr;
|
||||||
|
|
||||||
|
logic [7:0] pt_xw, pt_xr;
|
||||||
|
logic [7:0] pt_yw, pt_yr;
|
||||||
|
logic [7:0] pt_hw, pt_hr;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock) begin
|
||||||
|
if (pt_wr)
|
||||||
|
pt_ram[pt_waddr] <= {pt_hw, pt_xw, pt_yw};
|
||||||
|
|
||||||
|
{pt_hr, pt_xr, pt_yr} <= pt_ram[pt_raddr];
|
||||||
|
end
|
||||||
|
|
||||||
|
`ifdef TESTBENCH
|
||||||
|
integer i;
|
||||||
|
initial
|
||||||
|
for (i = 0; i < POINT_COUNT; i ++)
|
||||||
|
pt_ram[i] = {8'(i*5), 8'(i*5 + 20), 8'(i*5 + 30)};
|
||||||
|
`endif
|
||||||
|
|
||||||
|
/* FSM */
|
||||||
|
enum int unsigned {
|
||||||
|
ST_IDLE = 0, // 0
|
||||||
|
ST_READ_LAST_PT, // 1
|
||||||
|
ST_STORE_LAST_PT, // 2
|
||||||
|
ST_WRITE_NEW_PT, // 3
|
||||||
|
ST_DRAW_LAST, // 4
|
||||||
|
ST_FIG_DRAW, // 5
|
||||||
|
ST_NEXT_PT, // 6
|
||||||
|
ST_READ_PT, // 7
|
||||||
|
ST_STORE_PT, // 8
|
||||||
|
ST_ACK // 9
|
||||||
|
} state;
|
||||||
|
|
||||||
|
logic [POINT_CW-1:0] pt_last;
|
||||||
|
|
||||||
|
assign pt_xw = pt_x;
|
||||||
|
assign pt_yw = pt_y;
|
||||||
|
assign pt_hw = pt_h;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock, posedge reset)
|
||||||
|
if (reset) begin
|
||||||
|
state <= ST_IDLE;
|
||||||
|
pt_wr <= 1'b0;
|
||||||
|
pt_last <= '0;
|
||||||
|
pt_ack_o <= 1'b0;
|
||||||
|
fig_req_o <= 1'b0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
case (state)
|
||||||
|
ST_IDLE: begin
|
||||||
|
if (pt_req_i) begin
|
||||||
|
pt_raddr <= pt_last;
|
||||||
|
pt_waddr <= pt_last;
|
||||||
|
pt_wr <= 1'b0;
|
||||||
|
fig_v_o <= '0;
|
||||||
|
state <= ST_READ_LAST_PT;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_READ_LAST_PT:
|
||||||
|
state <= ST_STORE_LAST_PT;
|
||||||
|
|
||||||
|
ST_STORE_LAST_PT: begin
|
||||||
|
fig_x_o <= pt_xr;
|
||||||
|
fig_y_o <= {1'b0, pt_yr};
|
||||||
|
fig_h_o <= pt_hr;
|
||||||
|
fig_s_o <= 8'hff; // TODO: add saturation to ring mem
|
||||||
|
pt_wr <= 1'b1;
|
||||||
|
state <= ST_WRITE_NEW_PT;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_WRITE_NEW_PT: begin
|
||||||
|
pt_wr <= 1'b0;
|
||||||
|
fig_req_o <= 1'b1;
|
||||||
|
pt_raddr <= pt_last + 1'b1;
|
||||||
|
state <= ST_DRAW_LAST;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_DRAW_LAST:
|
||||||
|
if (fig_ack_i) begin
|
||||||
|
fig_req_o <= 1'b0;
|
||||||
|
state <= ST_READ_PT;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_FIG_DRAW: begin
|
||||||
|
fig_req_o <= 1'b1;
|
||||||
|
state <= ST_NEXT_PT;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_NEXT_PT:
|
||||||
|
if (fig_ack_i) begin
|
||||||
|
fig_req_o <= 1'b0;
|
||||||
|
|
||||||
|
if (pt_raddr == pt_last) begin
|
||||||
|
pt_last <= pt_last + 1'b1;
|
||||||
|
pt_ack_o <= 1'b1;
|
||||||
|
state <= ST_ACK;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
if (pt_raddr == POINT_CW'(POINT_COUNT-1))
|
||||||
|
pt_raddr <= '0;
|
||||||
|
else
|
||||||
|
pt_raddr <= pt_raddr + 1'b1;
|
||||||
|
|
||||||
|
state <= ST_READ_PT;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_READ_PT:
|
||||||
|
state <= ST_STORE_PT;
|
||||||
|
|
||||||
|
ST_STORE_PT: begin
|
||||||
|
fig_x_o <= pt_xr;
|
||||||
|
fig_y_o <= {1'b0, pt_yr};
|
||||||
|
fig_h_o <= pt_hr;
|
||||||
|
fig_s_o <= 8'hff; // TODO: add saturation to ring mem
|
||||||
|
|
||||||
|
if (fig_v_o > (255-V_INC))
|
||||||
|
fig_v_o <= 8'hff;
|
||||||
|
else
|
||||||
|
fig_v_o <= fig_v_o + V_INC;
|
||||||
|
|
||||||
|
state <= ST_FIG_DRAW;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_ACK: begin
|
||||||
|
pt_ack_o <= 1'b0;
|
||||||
|
state <= ST_IDLE;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
endmodule // fig_ring
|
||||||
64
source/fir-filter.m
Normal file
64
source/fir-filter.m
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
pkg load signal
|
||||||
|
|
||||||
|
%% filter length
|
||||||
|
flen = 511;
|
||||||
|
|
||||||
|
%% window
|
||||||
|
#win = ones(flen,1);
|
||||||
|
#win = chebwin(flen);
|
||||||
|
#win = blackmanharris(flen);
|
||||||
|
win = flattopwin(flen);
|
||||||
|
|
||||||
|
%% data width
|
||||||
|
bits = 16;
|
||||||
|
|
||||||
|
%% sampling frequency
|
||||||
|
fs = 20000
|
||||||
|
|
||||||
|
%% cutoff frequency
|
||||||
|
fc = 50;
|
||||||
|
|
||||||
|
%% stopband frequency
|
||||||
|
fb = 100;
|
||||||
|
|
||||||
|
%% amplification (dB)
|
||||||
|
amp_db = 10;
|
||||||
|
|
||||||
|
%% stopband attenuation (dB)
|
||||||
|
stop_db = -40;
|
||||||
|
|
||||||
|
%% filter
|
||||||
|
amp_k = 10^(amp_db/20);
|
||||||
|
stop_k = 10^((stop_db+amp_k)/20);
|
||||||
|
f = [0 fc/fs fb/fs 1];
|
||||||
|
m = [amp_k amp_k stop_k stop_k];
|
||||||
|
fcoeff = firls(flen-1, f, m) .* win;
|
||||||
|
|
||||||
|
%% scale and round to 16 bit
|
||||||
|
fcoeff_i16 = round(fcoeff .* 65536);
|
||||||
|
|
||||||
|
%% remove leading and trailing zeroes
|
||||||
|
fcoeff_i16_ms = fcoeff_i16(find(fcoeff_i16,1,'first'):find(fcoeff_i16,1,'last'));
|
||||||
|
|
||||||
|
function ret = to_hex(x)
|
||||||
|
if (x < 0)
|
||||||
|
ret = 65536+x;
|
||||||
|
else
|
||||||
|
ret = x;
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
%% convert negative coeffs to 16-bit two's complement
|
||||||
|
fcoeff_i16_hex = arrayfun(@to_hex, fcoeff_i16_ms);
|
||||||
|
|
||||||
|
%% printf coeffs to file
|
||||||
|
filename = sprintf("fir_%d_%dhz_%dhz_%ddb_%ddb.rom", length(fcoeff_i16_ms), fc, fb, amp_db, -stop_db);
|
||||||
|
printf("Write %d coefficients to file %s\n", length(fcoeff_i16_ms), filename);
|
||||||
|
|
||||||
|
file = fopen(filename, "w");
|
||||||
|
fprintf(file, "%04x\n", fcoeff_i16_hex);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
%% make real coeffs for freqz
|
||||||
|
fcoeff_i = fcoeff_i16_ms ./ 65536;
|
||||||
|
freqz(fcoeff_i);
|
||||||
363
source/fir_363_250hz_400hz_0db_40db.rom
Normal file
363
source/fir_363_250hz_400hz_0db_40db.rom
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
0000
|
||||||
|
0000
|
||||||
|
0000
|
||||||
|
0001
|
||||||
|
0001
|
||||||
|
0001
|
||||||
|
0001
|
||||||
|
0001
|
||||||
|
0001
|
||||||
|
0001
|
||||||
|
0001
|
||||||
|
0001
|
||||||
|
0001
|
||||||
|
0000
|
||||||
|
0000
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
fffe
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffc
|
||||||
|
fffb
|
||||||
|
fff9
|
||||||
|
fff8
|
||||||
|
fff7
|
||||||
|
fff5
|
||||||
|
fff4
|
||||||
|
fff2
|
||||||
|
fff1
|
||||||
|
ffef
|
||||||
|
ffed
|
||||||
|
ffeb
|
||||||
|
ffe9
|
||||||
|
ffe7
|
||||||
|
ffe6
|
||||||
|
ffe4
|
||||||
|
ffe2
|
||||||
|
ffe0
|
||||||
|
ffde
|
||||||
|
ffdc
|
||||||
|
ffda
|
||||||
|
ffd9
|
||||||
|
ffd7
|
||||||
|
ffd6
|
||||||
|
ffd5
|
||||||
|
ffd4
|
||||||
|
ffd3
|
||||||
|
ffd2
|
||||||
|
ffd2
|
||||||
|
ffd2
|
||||||
|
ffd2
|
||||||
|
ffd3
|
||||||
|
ffd4
|
||||||
|
ffd6
|
||||||
|
ffd8
|
||||||
|
ffda
|
||||||
|
ffdd
|
||||||
|
ffe0
|
||||||
|
ffe4
|
||||||
|
ffe9
|
||||||
|
ffee
|
||||||
|
fff3
|
||||||
|
fff9
|
||||||
|
0000
|
||||||
|
0008
|
||||||
|
0010
|
||||||
|
0019
|
||||||
|
0023
|
||||||
|
002d
|
||||||
|
0038
|
||||||
|
0044
|
||||||
|
0051
|
||||||
|
005e
|
||||||
|
006c
|
||||||
|
007b
|
||||||
|
008b
|
||||||
|
009b
|
||||||
|
00ac
|
||||||
|
00be
|
||||||
|
00d0
|
||||||
|
00e3
|
||||||
|
00f7
|
||||||
|
010b
|
||||||
|
0120
|
||||||
|
0136
|
||||||
|
014c
|
||||||
|
0162
|
||||||
|
0179
|
||||||
|
0190
|
||||||
|
01a8
|
||||||
|
01c0
|
||||||
|
01d8
|
||||||
|
01f1
|
||||||
|
0209
|
||||||
|
0222
|
||||||
|
023b
|
||||||
|
0253
|
||||||
|
026c
|
||||||
|
0284
|
||||||
|
029c
|
||||||
|
02b4
|
||||||
|
02cc
|
||||||
|
02e3
|
||||||
|
02fa
|
||||||
|
0311
|
||||||
|
0326
|
||||||
|
033b
|
||||||
|
0350
|
||||||
|
0364
|
||||||
|
0377
|
||||||
|
0389
|
||||||
|
039a
|
||||||
|
03aa
|
||||||
|
03b9
|
||||||
|
03c7
|
||||||
|
03d4
|
||||||
|
03e0
|
||||||
|
03eb
|
||||||
|
03f5
|
||||||
|
03fd
|
||||||
|
0404
|
||||||
|
040a
|
||||||
|
040f
|
||||||
|
0412
|
||||||
|
0414
|
||||||
|
06f4
|
||||||
|
0414
|
||||||
|
0412
|
||||||
|
040f
|
||||||
|
040a
|
||||||
|
0404
|
||||||
|
03fd
|
||||||
|
03f5
|
||||||
|
03eb
|
||||||
|
03e0
|
||||||
|
03d4
|
||||||
|
03c7
|
||||||
|
03b9
|
||||||
|
03aa
|
||||||
|
039a
|
||||||
|
0389
|
||||||
|
0377
|
||||||
|
0364
|
||||||
|
0350
|
||||||
|
033b
|
||||||
|
0326
|
||||||
|
0311
|
||||||
|
02fa
|
||||||
|
02e3
|
||||||
|
02cc
|
||||||
|
02b4
|
||||||
|
029c
|
||||||
|
0284
|
||||||
|
026c
|
||||||
|
0253
|
||||||
|
023b
|
||||||
|
0222
|
||||||
|
0209
|
||||||
|
01f1
|
||||||
|
01d8
|
||||||
|
01c0
|
||||||
|
01a8
|
||||||
|
0190
|
||||||
|
0179
|
||||||
|
0162
|
||||||
|
014c
|
||||||
|
0136
|
||||||
|
0120
|
||||||
|
010b
|
||||||
|
00f7
|
||||||
|
00e3
|
||||||
|
00d0
|
||||||
|
00be
|
||||||
|
00ac
|
||||||
|
009b
|
||||||
|
008b
|
||||||
|
007b
|
||||||
|
006c
|
||||||
|
005e
|
||||||
|
0051
|
||||||
|
0044
|
||||||
|
0038
|
||||||
|
002d
|
||||||
|
0023
|
||||||
|
0019
|
||||||
|
0010
|
||||||
|
0008
|
||||||
|
0000
|
||||||
|
fff9
|
||||||
|
fff3
|
||||||
|
ffee
|
||||||
|
ffe9
|
||||||
|
ffe4
|
||||||
|
ffe0
|
||||||
|
ffdd
|
||||||
|
ffda
|
||||||
|
ffd8
|
||||||
|
ffd6
|
||||||
|
ffd4
|
||||||
|
ffd3
|
||||||
|
ffd2
|
||||||
|
ffd2
|
||||||
|
ffd2
|
||||||
|
ffd2
|
||||||
|
ffd3
|
||||||
|
ffd4
|
||||||
|
ffd5
|
||||||
|
ffd6
|
||||||
|
ffd7
|
||||||
|
ffd9
|
||||||
|
ffda
|
||||||
|
ffdc
|
||||||
|
ffde
|
||||||
|
ffe0
|
||||||
|
ffe2
|
||||||
|
ffe4
|
||||||
|
ffe6
|
||||||
|
ffe7
|
||||||
|
ffe9
|
||||||
|
ffeb
|
||||||
|
ffed
|
||||||
|
ffef
|
||||||
|
fff1
|
||||||
|
fff2
|
||||||
|
fff4
|
||||||
|
fff5
|
||||||
|
fff7
|
||||||
|
fff8
|
||||||
|
fff9
|
||||||
|
fffb
|
||||||
|
fffc
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffe
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
0000
|
||||||
|
0000
|
||||||
|
0001
|
||||||
|
0001
|
||||||
|
0001
|
||||||
|
0001
|
||||||
|
0001
|
||||||
|
0001
|
||||||
|
0001
|
||||||
|
0001
|
||||||
|
0001
|
||||||
|
0001
|
||||||
|
0000
|
||||||
|
0000
|
||||||
|
0000
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
425
source/fir_425_50hz_100hz_0db_40db.rom
Normal file
425
source/fir_425_50hz_100hz_0db_40db.rom
Normal file
@ -0,0 +1,425 @@
|
|||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fff9
|
||||||
|
fff9
|
||||||
|
fff9
|
||||||
|
fff9
|
||||||
|
fff9
|
||||||
|
fff9
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff9
|
||||||
|
fff9
|
||||||
|
fff9
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffc
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffe
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
0000
|
||||||
|
0001
|
||||||
|
0002
|
||||||
|
0003
|
||||||
|
0004
|
||||||
|
0005
|
||||||
|
0006
|
||||||
|
0007
|
||||||
|
0008
|
||||||
|
0009
|
||||||
|
000b
|
||||||
|
000c
|
||||||
|
000d
|
||||||
|
000f
|
||||||
|
0010
|
||||||
|
0012
|
||||||
|
0013
|
||||||
|
0015
|
||||||
|
0017
|
||||||
|
0018
|
||||||
|
001a
|
||||||
|
001c
|
||||||
|
001e
|
||||||
|
0020
|
||||||
|
0022
|
||||||
|
0024
|
||||||
|
0026
|
||||||
|
0028
|
||||||
|
002a
|
||||||
|
002d
|
||||||
|
002f
|
||||||
|
0031
|
||||||
|
0034
|
||||||
|
0036
|
||||||
|
0039
|
||||||
|
003b
|
||||||
|
003e
|
||||||
|
0040
|
||||||
|
0043
|
||||||
|
0046
|
||||||
|
0048
|
||||||
|
004b
|
||||||
|
004e
|
||||||
|
0051
|
||||||
|
0054
|
||||||
|
0057
|
||||||
|
0059
|
||||||
|
005c
|
||||||
|
005f
|
||||||
|
0062
|
||||||
|
0065
|
||||||
|
0068
|
||||||
|
006c
|
||||||
|
006f
|
||||||
|
0072
|
||||||
|
0075
|
||||||
|
0078
|
||||||
|
007b
|
||||||
|
007e
|
||||||
|
0081
|
||||||
|
0084
|
||||||
|
0088
|
||||||
|
008b
|
||||||
|
008e
|
||||||
|
0091
|
||||||
|
0094
|
||||||
|
0097
|
||||||
|
009a
|
||||||
|
009d
|
||||||
|
00a0
|
||||||
|
00a3
|
||||||
|
00a6
|
||||||
|
00a9
|
||||||
|
00ac
|
||||||
|
00af
|
||||||
|
00b2
|
||||||
|
00b4
|
||||||
|
00b7
|
||||||
|
00ba
|
||||||
|
00bc
|
||||||
|
00bf
|
||||||
|
00c1
|
||||||
|
00c4
|
||||||
|
00c6
|
||||||
|
00c9
|
||||||
|
00cb
|
||||||
|
00cd
|
||||||
|
00cf
|
||||||
|
00d1
|
||||||
|
00d3
|
||||||
|
00d5
|
||||||
|
00d7
|
||||||
|
00d9
|
||||||
|
00db
|
||||||
|
00dc
|
||||||
|
00de
|
||||||
|
00df
|
||||||
|
00e1
|
||||||
|
00e2
|
||||||
|
00e3
|
||||||
|
00e4
|
||||||
|
00e5
|
||||||
|
00e6
|
||||||
|
00e7
|
||||||
|
00e8
|
||||||
|
00e8
|
||||||
|
00e9
|
||||||
|
00e9
|
||||||
|
00e9
|
||||||
|
00ea
|
||||||
|
00ea
|
||||||
|
03c9
|
||||||
|
00ea
|
||||||
|
00ea
|
||||||
|
00e9
|
||||||
|
00e9
|
||||||
|
00e9
|
||||||
|
00e8
|
||||||
|
00e8
|
||||||
|
00e7
|
||||||
|
00e6
|
||||||
|
00e5
|
||||||
|
00e4
|
||||||
|
00e3
|
||||||
|
00e2
|
||||||
|
00e1
|
||||||
|
00df
|
||||||
|
00de
|
||||||
|
00dc
|
||||||
|
00db
|
||||||
|
00d9
|
||||||
|
00d7
|
||||||
|
00d5
|
||||||
|
00d3
|
||||||
|
00d1
|
||||||
|
00cf
|
||||||
|
00cd
|
||||||
|
00cb
|
||||||
|
00c9
|
||||||
|
00c6
|
||||||
|
00c4
|
||||||
|
00c1
|
||||||
|
00bf
|
||||||
|
00bc
|
||||||
|
00ba
|
||||||
|
00b7
|
||||||
|
00b4
|
||||||
|
00b2
|
||||||
|
00af
|
||||||
|
00ac
|
||||||
|
00a9
|
||||||
|
00a6
|
||||||
|
00a3
|
||||||
|
00a0
|
||||||
|
009d
|
||||||
|
009a
|
||||||
|
0097
|
||||||
|
0094
|
||||||
|
0091
|
||||||
|
008e
|
||||||
|
008b
|
||||||
|
0088
|
||||||
|
0084
|
||||||
|
0081
|
||||||
|
007e
|
||||||
|
007b
|
||||||
|
0078
|
||||||
|
0075
|
||||||
|
0072
|
||||||
|
006f
|
||||||
|
006c
|
||||||
|
0068
|
||||||
|
0065
|
||||||
|
0062
|
||||||
|
005f
|
||||||
|
005c
|
||||||
|
0059
|
||||||
|
0057
|
||||||
|
0054
|
||||||
|
0051
|
||||||
|
004e
|
||||||
|
004b
|
||||||
|
0048
|
||||||
|
0046
|
||||||
|
0043
|
||||||
|
0040
|
||||||
|
003e
|
||||||
|
003b
|
||||||
|
0039
|
||||||
|
0036
|
||||||
|
0034
|
||||||
|
0031
|
||||||
|
002f
|
||||||
|
002d
|
||||||
|
002a
|
||||||
|
0028
|
||||||
|
0026
|
||||||
|
0024
|
||||||
|
0022
|
||||||
|
0020
|
||||||
|
001e
|
||||||
|
001c
|
||||||
|
001a
|
||||||
|
0018
|
||||||
|
0017
|
||||||
|
0015
|
||||||
|
0013
|
||||||
|
0012
|
||||||
|
0010
|
||||||
|
000f
|
||||||
|
000d
|
||||||
|
000c
|
||||||
|
000b
|
||||||
|
0009
|
||||||
|
0008
|
||||||
|
0007
|
||||||
|
0006
|
||||||
|
0005
|
||||||
|
0004
|
||||||
|
0003
|
||||||
|
0002
|
||||||
|
0001
|
||||||
|
0000
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
fffe
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffc
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fff9
|
||||||
|
fff9
|
||||||
|
fff9
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff9
|
||||||
|
fff9
|
||||||
|
fff9
|
||||||
|
fff9
|
||||||
|
fff9
|
||||||
|
fff9
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
449
source/fir_449_50hz_100hz_10db_40db.rom
Normal file
449
source/fir_449_50hz_100hz_10db_40db.rom
Normal file
@ -0,0 +1,449 @@
|
|||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fff9
|
||||||
|
fff9
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff6
|
||||||
|
fff6
|
||||||
|
fff6
|
||||||
|
fff5
|
||||||
|
fff5
|
||||||
|
fff4
|
||||||
|
fff4
|
||||||
|
fff3
|
||||||
|
fff3
|
||||||
|
fff2
|
||||||
|
fff1
|
||||||
|
fff1
|
||||||
|
fff0
|
||||||
|
fff0
|
||||||
|
ffef
|
||||||
|
ffef
|
||||||
|
ffee
|
||||||
|
ffed
|
||||||
|
ffed
|
||||||
|
ffec
|
||||||
|
ffec
|
||||||
|
ffeb
|
||||||
|
ffeb
|
||||||
|
ffea
|
||||||
|
ffe9
|
||||||
|
ffe9
|
||||||
|
ffe8
|
||||||
|
ffe8
|
||||||
|
ffe7
|
||||||
|
ffe7
|
||||||
|
ffe6
|
||||||
|
ffe6
|
||||||
|
ffe5
|
||||||
|
ffe5
|
||||||
|
ffe4
|
||||||
|
ffe4
|
||||||
|
ffe4
|
||||||
|
ffe3
|
||||||
|
ffe3
|
||||||
|
ffe3
|
||||||
|
ffe2
|
||||||
|
ffe2
|
||||||
|
ffe2
|
||||||
|
ffe2
|
||||||
|
ffe2
|
||||||
|
ffe2
|
||||||
|
ffe2
|
||||||
|
ffe2
|
||||||
|
ffe2
|
||||||
|
ffe2
|
||||||
|
ffe3
|
||||||
|
ffe3
|
||||||
|
ffe4
|
||||||
|
ffe4
|
||||||
|
ffe5
|
||||||
|
ffe5
|
||||||
|
ffe6
|
||||||
|
ffe7
|
||||||
|
ffe8
|
||||||
|
ffe9
|
||||||
|
ffea
|
||||||
|
ffeb
|
||||||
|
ffed
|
||||||
|
ffee
|
||||||
|
fff0
|
||||||
|
fff1
|
||||||
|
fff3
|
||||||
|
fff5
|
||||||
|
fff7
|
||||||
|
fff9
|
||||||
|
fffc
|
||||||
|
fffe
|
||||||
|
0001
|
||||||
|
0003
|
||||||
|
0006
|
||||||
|
0009
|
||||||
|
000c
|
||||||
|
000f
|
||||||
|
0013
|
||||||
|
0016
|
||||||
|
001a
|
||||||
|
001e
|
||||||
|
0022
|
||||||
|
0026
|
||||||
|
002b
|
||||||
|
002f
|
||||||
|
0034
|
||||||
|
0039
|
||||||
|
003e
|
||||||
|
0043
|
||||||
|
0048
|
||||||
|
004e
|
||||||
|
0054
|
||||||
|
0059
|
||||||
|
005f
|
||||||
|
0066
|
||||||
|
006c
|
||||||
|
0072
|
||||||
|
0079
|
||||||
|
0080
|
||||||
|
0087
|
||||||
|
008e
|
||||||
|
0095
|
||||||
|
009d
|
||||||
|
00a4
|
||||||
|
00ac
|
||||||
|
00b4
|
||||||
|
00bc
|
||||||
|
00c4
|
||||||
|
00cd
|
||||||
|
00d5
|
||||||
|
00de
|
||||||
|
00e6
|
||||||
|
00ef
|
||||||
|
00f8
|
||||||
|
0101
|
||||||
|
010a
|
||||||
|
0113
|
||||||
|
011d
|
||||||
|
0126
|
||||||
|
0130
|
||||||
|
0139
|
||||||
|
0143
|
||||||
|
014d
|
||||||
|
0156
|
||||||
|
0160
|
||||||
|
016a
|
||||||
|
0174
|
||||||
|
017e
|
||||||
|
0188
|
||||||
|
0192
|
||||||
|
019c
|
||||||
|
01a6
|
||||||
|
01b0
|
||||||
|
01ba
|
||||||
|
01c3
|
||||||
|
01cd
|
||||||
|
01d7
|
||||||
|
01e1
|
||||||
|
01eb
|
||||||
|
01f4
|
||||||
|
01fe
|
||||||
|
0207
|
||||||
|
0211
|
||||||
|
021a
|
||||||
|
0223
|
||||||
|
022c
|
||||||
|
0235
|
||||||
|
023e
|
||||||
|
0247
|
||||||
|
024f
|
||||||
|
0258
|
||||||
|
0260
|
||||||
|
0268
|
||||||
|
0270
|
||||||
|
0277
|
||||||
|
027f
|
||||||
|
0286
|
||||||
|
028d
|
||||||
|
0294
|
||||||
|
029a
|
||||||
|
02a1
|
||||||
|
02a7
|
||||||
|
02ad
|
||||||
|
02b3
|
||||||
|
02b8
|
||||||
|
02bd
|
||||||
|
02c2
|
||||||
|
02c7
|
||||||
|
02cb
|
||||||
|
02cf
|
||||||
|
02d3
|
||||||
|
02d6
|
||||||
|
02d9
|
||||||
|
02dc
|
||||||
|
02df
|
||||||
|
02e1
|
||||||
|
02e3
|
||||||
|
02e5
|
||||||
|
02e6
|
||||||
|
02e7
|
||||||
|
02e8
|
||||||
|
02e8
|
||||||
|
0698
|
||||||
|
02e8
|
||||||
|
02e8
|
||||||
|
02e7
|
||||||
|
02e6
|
||||||
|
02e5
|
||||||
|
02e3
|
||||||
|
02e1
|
||||||
|
02df
|
||||||
|
02dc
|
||||||
|
02d9
|
||||||
|
02d6
|
||||||
|
02d3
|
||||||
|
02cf
|
||||||
|
02cb
|
||||||
|
02c7
|
||||||
|
02c2
|
||||||
|
02bd
|
||||||
|
02b8
|
||||||
|
02b3
|
||||||
|
02ad
|
||||||
|
02a7
|
||||||
|
02a1
|
||||||
|
029a
|
||||||
|
0294
|
||||||
|
028d
|
||||||
|
0286
|
||||||
|
027f
|
||||||
|
0277
|
||||||
|
0270
|
||||||
|
0268
|
||||||
|
0260
|
||||||
|
0258
|
||||||
|
024f
|
||||||
|
0247
|
||||||
|
023e
|
||||||
|
0235
|
||||||
|
022c
|
||||||
|
0223
|
||||||
|
021a
|
||||||
|
0211
|
||||||
|
0207
|
||||||
|
01fe
|
||||||
|
01f4
|
||||||
|
01eb
|
||||||
|
01e1
|
||||||
|
01d7
|
||||||
|
01cd
|
||||||
|
01c3
|
||||||
|
01ba
|
||||||
|
01b0
|
||||||
|
01a6
|
||||||
|
019c
|
||||||
|
0192
|
||||||
|
0188
|
||||||
|
017e
|
||||||
|
0174
|
||||||
|
016a
|
||||||
|
0160
|
||||||
|
0156
|
||||||
|
014d
|
||||||
|
0143
|
||||||
|
0139
|
||||||
|
0130
|
||||||
|
0126
|
||||||
|
011d
|
||||||
|
0113
|
||||||
|
010a
|
||||||
|
0101
|
||||||
|
00f8
|
||||||
|
00ef
|
||||||
|
00e6
|
||||||
|
00de
|
||||||
|
00d5
|
||||||
|
00cd
|
||||||
|
00c4
|
||||||
|
00bc
|
||||||
|
00b4
|
||||||
|
00ac
|
||||||
|
00a4
|
||||||
|
009d
|
||||||
|
0095
|
||||||
|
008e
|
||||||
|
0087
|
||||||
|
0080
|
||||||
|
0079
|
||||||
|
0072
|
||||||
|
006c
|
||||||
|
0066
|
||||||
|
005f
|
||||||
|
0059
|
||||||
|
0054
|
||||||
|
004e
|
||||||
|
0048
|
||||||
|
0043
|
||||||
|
003e
|
||||||
|
0039
|
||||||
|
0034
|
||||||
|
002f
|
||||||
|
002b
|
||||||
|
0026
|
||||||
|
0022
|
||||||
|
001e
|
||||||
|
001a
|
||||||
|
0016
|
||||||
|
0013
|
||||||
|
000f
|
||||||
|
000c
|
||||||
|
0009
|
||||||
|
0006
|
||||||
|
0003
|
||||||
|
0001
|
||||||
|
fffe
|
||||||
|
fffc
|
||||||
|
fff9
|
||||||
|
fff7
|
||||||
|
fff5
|
||||||
|
fff3
|
||||||
|
fff1
|
||||||
|
fff0
|
||||||
|
ffee
|
||||||
|
ffed
|
||||||
|
ffeb
|
||||||
|
ffea
|
||||||
|
ffe9
|
||||||
|
ffe8
|
||||||
|
ffe7
|
||||||
|
ffe6
|
||||||
|
ffe5
|
||||||
|
ffe5
|
||||||
|
ffe4
|
||||||
|
ffe4
|
||||||
|
ffe3
|
||||||
|
ffe3
|
||||||
|
ffe2
|
||||||
|
ffe2
|
||||||
|
ffe2
|
||||||
|
ffe2
|
||||||
|
ffe2
|
||||||
|
ffe2
|
||||||
|
ffe2
|
||||||
|
ffe2
|
||||||
|
ffe2
|
||||||
|
ffe2
|
||||||
|
ffe3
|
||||||
|
ffe3
|
||||||
|
ffe3
|
||||||
|
ffe4
|
||||||
|
ffe4
|
||||||
|
ffe4
|
||||||
|
ffe5
|
||||||
|
ffe5
|
||||||
|
ffe6
|
||||||
|
ffe6
|
||||||
|
ffe7
|
||||||
|
ffe7
|
||||||
|
ffe8
|
||||||
|
ffe8
|
||||||
|
ffe9
|
||||||
|
ffe9
|
||||||
|
ffea
|
||||||
|
ffeb
|
||||||
|
ffeb
|
||||||
|
ffec
|
||||||
|
ffec
|
||||||
|
ffed
|
||||||
|
ffed
|
||||||
|
ffee
|
||||||
|
ffef
|
||||||
|
ffef
|
||||||
|
fff0
|
||||||
|
fff0
|
||||||
|
fff1
|
||||||
|
fff1
|
||||||
|
fff2
|
||||||
|
fff3
|
||||||
|
fff3
|
||||||
|
fff4
|
||||||
|
fff4
|
||||||
|
fff5
|
||||||
|
fff5
|
||||||
|
fff6
|
||||||
|
fff6
|
||||||
|
fff6
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff8
|
||||||
|
fff9
|
||||||
|
fff9
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
465
source/fir_465_50hz_100hz_20db_40db.rom
Normal file
465
source/fir_465_50hz_100hz_20db_40db.rom
Normal file
@ -0,0 +1,465 @@
|
|||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fff9
|
||||||
|
fff9
|
||||||
|
fff8
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff6
|
||||||
|
fff5
|
||||||
|
fff5
|
||||||
|
fff4
|
||||||
|
fff3
|
||||||
|
fff2
|
||||||
|
fff2
|
||||||
|
fff1
|
||||||
|
fff0
|
||||||
|
ffef
|
||||||
|
ffee
|
||||||
|
ffed
|
||||||
|
ffec
|
||||||
|
ffeb
|
||||||
|
ffe9
|
||||||
|
ffe8
|
||||||
|
ffe7
|
||||||
|
ffe6
|
||||||
|
ffe4
|
||||||
|
ffe3
|
||||||
|
ffe2
|
||||||
|
ffe0
|
||||||
|
ffdf
|
||||||
|
ffdd
|
||||||
|
ffdc
|
||||||
|
ffda
|
||||||
|
ffd9
|
||||||
|
ffd7
|
||||||
|
ffd5
|
||||||
|
ffd4
|
||||||
|
ffd2
|
||||||
|
ffd0
|
||||||
|
ffce
|
||||||
|
ffcd
|
||||||
|
ffcb
|
||||||
|
ffc9
|
||||||
|
ffc7
|
||||||
|
ffc5
|
||||||
|
ffc3
|
||||||
|
ffc2
|
||||||
|
ffc0
|
||||||
|
ffbe
|
||||||
|
ffbc
|
||||||
|
ffba
|
||||||
|
ffb8
|
||||||
|
ffb6
|
||||||
|
ffb5
|
||||||
|
ffb3
|
||||||
|
ffb1
|
||||||
|
ffb0
|
||||||
|
ffae
|
||||||
|
ffac
|
||||||
|
ffab
|
||||||
|
ffaa
|
||||||
|
ffa8
|
||||||
|
ffa7
|
||||||
|
ffa6
|
||||||
|
ffa5
|
||||||
|
ffa4
|
||||||
|
ffa3
|
||||||
|
ffa2
|
||||||
|
ffa2
|
||||||
|
ffa1
|
||||||
|
ffa1
|
||||||
|
ffa1
|
||||||
|
ffa1
|
||||||
|
ffa1
|
||||||
|
ffa1
|
||||||
|
ffa2
|
||||||
|
ffa2
|
||||||
|
ffa3
|
||||||
|
ffa4
|
||||||
|
ffa6
|
||||||
|
ffa7
|
||||||
|
ffa9
|
||||||
|
ffab
|
||||||
|
ffae
|
||||||
|
ffb1
|
||||||
|
ffb4
|
||||||
|
ffb7
|
||||||
|
ffba
|
||||||
|
ffbe
|
||||||
|
ffc3
|
||||||
|
ffc7
|
||||||
|
ffcc
|
||||||
|
ffd2
|
||||||
|
ffd7
|
||||||
|
ffdd
|
||||||
|
ffe4
|
||||||
|
ffeb
|
||||||
|
fff2
|
||||||
|
fffa
|
||||||
|
0002
|
||||||
|
000a
|
||||||
|
0013
|
||||||
|
001d
|
||||||
|
0027
|
||||||
|
0031
|
||||||
|
003c
|
||||||
|
0047
|
||||||
|
0053
|
||||||
|
005f
|
||||||
|
006c
|
||||||
|
007a
|
||||||
|
0087
|
||||||
|
0096
|
||||||
|
00a5
|
||||||
|
00b4
|
||||||
|
00c4
|
||||||
|
00d4
|
||||||
|
00e5
|
||||||
|
00f7
|
||||||
|
0109
|
||||||
|
011b
|
||||||
|
012e
|
||||||
|
0142
|
||||||
|
0156
|
||||||
|
016a
|
||||||
|
0180
|
||||||
|
0195
|
||||||
|
01ab
|
||||||
|
01c2
|
||||||
|
01d9
|
||||||
|
01f1
|
||||||
|
0209
|
||||||
|
0221
|
||||||
|
023a
|
||||||
|
0254
|
||||||
|
026e
|
||||||
|
0288
|
||||||
|
02a3
|
||||||
|
02be
|
||||||
|
02d9
|
||||||
|
02f5
|
||||||
|
0312
|
||||||
|
032e
|
||||||
|
034b
|
||||||
|
0368
|
||||||
|
0386
|
||||||
|
03a4
|
||||||
|
03c2
|
||||||
|
03e0
|
||||||
|
03ff
|
||||||
|
041d
|
||||||
|
043c
|
||||||
|
045b
|
||||||
|
047b
|
||||||
|
049a
|
||||||
|
04b9
|
||||||
|
04d9
|
||||||
|
04f8
|
||||||
|
0518
|
||||||
|
0537
|
||||||
|
0557
|
||||||
|
0576
|
||||||
|
0596
|
||||||
|
05b5
|
||||||
|
05d4
|
||||||
|
05f3
|
||||||
|
0612
|
||||||
|
0630
|
||||||
|
064f
|
||||||
|
066d
|
||||||
|
068a
|
||||||
|
06a8
|
||||||
|
06c5
|
||||||
|
06e2
|
||||||
|
06fe
|
||||||
|
071a
|
||||||
|
0735
|
||||||
|
0750
|
||||||
|
076b
|
||||||
|
0785
|
||||||
|
079e
|
||||||
|
07b7
|
||||||
|
07cf
|
||||||
|
07e7
|
||||||
|
07fe
|
||||||
|
0814
|
||||||
|
082a
|
||||||
|
083f
|
||||||
|
0853
|
||||||
|
0866
|
||||||
|
0879
|
||||||
|
088b
|
||||||
|
089c
|
||||||
|
08ac
|
||||||
|
08bb
|
||||||
|
08ca
|
||||||
|
08d8
|
||||||
|
08e4
|
||||||
|
08f0
|
||||||
|
08fb
|
||||||
|
0905
|
||||||
|
090f
|
||||||
|
0917
|
||||||
|
091e
|
||||||
|
0924
|
||||||
|
092a
|
||||||
|
092e
|
||||||
|
0932
|
||||||
|
0934
|
||||||
|
0935
|
||||||
|
114e
|
||||||
|
0935
|
||||||
|
0934
|
||||||
|
0932
|
||||||
|
092e
|
||||||
|
092a
|
||||||
|
0924
|
||||||
|
091e
|
||||||
|
0917
|
||||||
|
090f
|
||||||
|
0905
|
||||||
|
08fb
|
||||||
|
08f0
|
||||||
|
08e4
|
||||||
|
08d8
|
||||||
|
08ca
|
||||||
|
08bb
|
||||||
|
08ac
|
||||||
|
089c
|
||||||
|
088b
|
||||||
|
0879
|
||||||
|
0866
|
||||||
|
0853
|
||||||
|
083f
|
||||||
|
082a
|
||||||
|
0814
|
||||||
|
07fe
|
||||||
|
07e7
|
||||||
|
07cf
|
||||||
|
07b7
|
||||||
|
079e
|
||||||
|
0785
|
||||||
|
076b
|
||||||
|
0750
|
||||||
|
0735
|
||||||
|
071a
|
||||||
|
06fe
|
||||||
|
06e2
|
||||||
|
06c5
|
||||||
|
06a8
|
||||||
|
068a
|
||||||
|
066d
|
||||||
|
064f
|
||||||
|
0630
|
||||||
|
0612
|
||||||
|
05f3
|
||||||
|
05d4
|
||||||
|
05b5
|
||||||
|
0596
|
||||||
|
0576
|
||||||
|
0557
|
||||||
|
0537
|
||||||
|
0518
|
||||||
|
04f8
|
||||||
|
04d9
|
||||||
|
04b9
|
||||||
|
049a
|
||||||
|
047b
|
||||||
|
045b
|
||||||
|
043c
|
||||||
|
041d
|
||||||
|
03ff
|
||||||
|
03e0
|
||||||
|
03c2
|
||||||
|
03a4
|
||||||
|
0386
|
||||||
|
0368
|
||||||
|
034b
|
||||||
|
032e
|
||||||
|
0312
|
||||||
|
02f5
|
||||||
|
02d9
|
||||||
|
02be
|
||||||
|
02a3
|
||||||
|
0288
|
||||||
|
026e
|
||||||
|
0254
|
||||||
|
023a
|
||||||
|
0221
|
||||||
|
0209
|
||||||
|
01f1
|
||||||
|
01d9
|
||||||
|
01c2
|
||||||
|
01ab
|
||||||
|
0195
|
||||||
|
0180
|
||||||
|
016a
|
||||||
|
0156
|
||||||
|
0142
|
||||||
|
012e
|
||||||
|
011b
|
||||||
|
0109
|
||||||
|
00f7
|
||||||
|
00e5
|
||||||
|
00d4
|
||||||
|
00c4
|
||||||
|
00b4
|
||||||
|
00a5
|
||||||
|
0096
|
||||||
|
0087
|
||||||
|
007a
|
||||||
|
006c
|
||||||
|
005f
|
||||||
|
0053
|
||||||
|
0047
|
||||||
|
003c
|
||||||
|
0031
|
||||||
|
0027
|
||||||
|
001d
|
||||||
|
0013
|
||||||
|
000a
|
||||||
|
0002
|
||||||
|
fffa
|
||||||
|
fff2
|
||||||
|
ffeb
|
||||||
|
ffe4
|
||||||
|
ffdd
|
||||||
|
ffd7
|
||||||
|
ffd2
|
||||||
|
ffcc
|
||||||
|
ffc7
|
||||||
|
ffc3
|
||||||
|
ffbe
|
||||||
|
ffba
|
||||||
|
ffb7
|
||||||
|
ffb4
|
||||||
|
ffb1
|
||||||
|
ffae
|
||||||
|
ffab
|
||||||
|
ffa9
|
||||||
|
ffa7
|
||||||
|
ffa6
|
||||||
|
ffa4
|
||||||
|
ffa3
|
||||||
|
ffa2
|
||||||
|
ffa2
|
||||||
|
ffa1
|
||||||
|
ffa1
|
||||||
|
ffa1
|
||||||
|
ffa1
|
||||||
|
ffa1
|
||||||
|
ffa1
|
||||||
|
ffa2
|
||||||
|
ffa2
|
||||||
|
ffa3
|
||||||
|
ffa4
|
||||||
|
ffa5
|
||||||
|
ffa6
|
||||||
|
ffa7
|
||||||
|
ffa8
|
||||||
|
ffaa
|
||||||
|
ffab
|
||||||
|
ffac
|
||||||
|
ffae
|
||||||
|
ffb0
|
||||||
|
ffb1
|
||||||
|
ffb3
|
||||||
|
ffb5
|
||||||
|
ffb6
|
||||||
|
ffb8
|
||||||
|
ffba
|
||||||
|
ffbc
|
||||||
|
ffbe
|
||||||
|
ffc0
|
||||||
|
ffc2
|
||||||
|
ffc3
|
||||||
|
ffc5
|
||||||
|
ffc7
|
||||||
|
ffc9
|
||||||
|
ffcb
|
||||||
|
ffcd
|
||||||
|
ffce
|
||||||
|
ffd0
|
||||||
|
ffd2
|
||||||
|
ffd4
|
||||||
|
ffd5
|
||||||
|
ffd7
|
||||||
|
ffd9
|
||||||
|
ffda
|
||||||
|
ffdc
|
||||||
|
ffdd
|
||||||
|
ffdf
|
||||||
|
ffe0
|
||||||
|
ffe2
|
||||||
|
ffe3
|
||||||
|
ffe4
|
||||||
|
ffe6
|
||||||
|
ffe7
|
||||||
|
ffe8
|
||||||
|
ffe9
|
||||||
|
ffeb
|
||||||
|
ffec
|
||||||
|
ffed
|
||||||
|
ffee
|
||||||
|
ffef
|
||||||
|
fff0
|
||||||
|
fff1
|
||||||
|
fff2
|
||||||
|
fff2
|
||||||
|
fff3
|
||||||
|
fff4
|
||||||
|
fff5
|
||||||
|
fff5
|
||||||
|
fff6
|
||||||
|
fff7
|
||||||
|
fff7
|
||||||
|
fff8
|
||||||
|
fff9
|
||||||
|
fff9
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffa
|
||||||
|
fffb
|
||||||
|
fffb
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffc
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffd
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
fffe
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
|
ffff
|
||||||
123
source/fir_filter.sv
Normal file
123
source/fir_filter.sv
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
module fir_filter #(parameter LEN = 449,
|
||||||
|
parameter COEFFS_ROM_FILE = "fir_449_50hz_100hz_10db_40db.rom")
|
||||||
|
(input wire clock,
|
||||||
|
input wire reset,
|
||||||
|
|
||||||
|
input wire signed [15:0] data_i,
|
||||||
|
input wire ready_i,
|
||||||
|
|
||||||
|
output wire signed [15:0] data_o,
|
||||||
|
output reg valid_o);
|
||||||
|
|
||||||
|
localparam LEN_CW = $clog2(LEN);
|
||||||
|
localparam MEM_LEN = 1 << LEN_CW;
|
||||||
|
|
||||||
|
/* Coeffs */
|
||||||
|
logic signed [15:0] coeffs[LEN];
|
||||||
|
initial $readmemh(COEFFS_ROM_FILE, coeffs, 0, LEN-1);
|
||||||
|
|
||||||
|
logic signed [15:0] coeff;
|
||||||
|
logic [LEN_CW-1:0] coeff_addr;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
coeff <= coeffs[coeff_addr];
|
||||||
|
|
||||||
|
/* Z-1 BlockRAM */
|
||||||
|
logic signed [15:0] mem[MEM_LEN];
|
||||||
|
logic signed [15:0] mem_wdata;
|
||||||
|
logic signed [15:0] mem_rdata;
|
||||||
|
logic [LEN_CW-1:0] mem_addr;
|
||||||
|
logic mem_wr;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock) begin
|
||||||
|
if (mem_wr)
|
||||||
|
mem[mem_addr] <= mem_wdata;
|
||||||
|
mem_rdata <= mem[mem_addr];
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
integer i;
|
||||||
|
for (i = 0; i < MEM_LEN; i++)
|
||||||
|
mem[i] = '0;
|
||||||
|
end
|
||||||
|
|
||||||
|
/* MAC */
|
||||||
|
logic [31:0] mac_o;
|
||||||
|
logic signed [15:0] a;
|
||||||
|
logic signed [15:0] b;
|
||||||
|
logic signed [15:0] s;
|
||||||
|
|
||||||
|
ice40_mac16x16 #(.SIGNED(1)) mac
|
||||||
|
(.clock, .reset,
|
||||||
|
.a(a),
|
||||||
|
.b(b),
|
||||||
|
.s({s, 16'b0}),
|
||||||
|
.sub(1'b0),
|
||||||
|
.y(mac_o));
|
||||||
|
|
||||||
|
/* FSM */
|
||||||
|
enum int unsigned {
|
||||||
|
ST_IDLE = 0,
|
||||||
|
ST_WRITE,
|
||||||
|
ST_CONV,
|
||||||
|
ST_DONE
|
||||||
|
} state;
|
||||||
|
|
||||||
|
logic [LEN_CW-1:0] new_addr;
|
||||||
|
|
||||||
|
assign mem_wdata = data_i;
|
||||||
|
assign data_o = s;
|
||||||
|
assign s = coeff_addr == '0 ? '0 : mac_o[31:16];
|
||||||
|
|
||||||
|
always_ff @ (posedge clock, posedge reset)
|
||||||
|
if (reset) begin
|
||||||
|
state <= ST_IDLE;
|
||||||
|
new_addr <= '0;
|
||||||
|
mem_wr <= 1'b0;
|
||||||
|
valid_o <= 1'b0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
case (state)
|
||||||
|
ST_IDLE: begin
|
||||||
|
a <= '0;
|
||||||
|
b <= '0;
|
||||||
|
mem_addr <= new_addr;
|
||||||
|
coeff_addr <= '0;
|
||||||
|
|
||||||
|
if (ready_i) begin
|
||||||
|
mem_wr <= 1'b1;
|
||||||
|
state <= ST_WRITE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_WRITE: begin
|
||||||
|
mem_wr <= 1'b0;
|
||||||
|
state <= ST_CONV;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_CONV: begin
|
||||||
|
a <= mem_rdata;
|
||||||
|
b <= coeff;
|
||||||
|
|
||||||
|
if (coeff_addr == LEN_CW'(LEN-1)) begin
|
||||||
|
valid_o <= 1'b1;
|
||||||
|
state <= ST_DONE;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
coeff_addr <= coeff_addr + 1'b1;
|
||||||
|
mem_addr <= mem_addr - 1'b1;
|
||||||
|
state <= ST_CONV;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_DONE: begin
|
||||||
|
new_addr <= new_addr + 1'b1;
|
||||||
|
valid_o <= 1'b0;
|
||||||
|
state <= ST_IDLE;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
endmodule // fir_filter
|
||||||
239
source/hsl2rgb.sv
Normal file
239
source/hsl2rgb.sv
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HSL to RGB translation.
|
||||||
|
*
|
||||||
|
* H, S, L = [0..1)
|
||||||
|
*
|
||||||
|
* Q = | L < 0.5 ? L + L*S
|
||||||
|
* | L >= 0.5 ? L + S - L*S
|
||||||
|
*
|
||||||
|
* P = 2 * L - Q
|
||||||
|
*
|
||||||
|
* TR = H < 2/3 ? H + 1/3 : 1/3 - (1 - H)
|
||||||
|
* TG = H
|
||||||
|
* TB = H >= 1/3 ? H - 1/3 : 1 - H
|
||||||
|
*
|
||||||
|
* COLORX = | TX < 1/6 ? P + ((Q - P) * 6 * TX)
|
||||||
|
* | 1/6 <= TX < 1/2 ? Q
|
||||||
|
* | 1/2 <= TX < 2/3 ? P + ((Q - P) * (2/3 - TX) * 6)
|
||||||
|
* | else : P
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Datapath:
|
||||||
|
*
|
||||||
|
* if l < [1/2]
|
||||||
|
* then: lls = l + (l * s)
|
||||||
|
* else: lls = l - (l * s)
|
||||||
|
*
|
||||||
|
* m1h = ~(h - 1)
|
||||||
|
*
|
||||||
|
* tr =
|
||||||
|
* if h < [2/3]
|
||||||
|
* then: h + [1/3]
|
||||||
|
* else: [1/3] - m1h
|
||||||
|
*
|
||||||
|
* tg = h
|
||||||
|
*
|
||||||
|
* tb =
|
||||||
|
* if h >= [1/3]
|
||||||
|
* then: h - [1/3]
|
||||||
|
* else: m1h
|
||||||
|
*
|
||||||
|
* q =
|
||||||
|
* if l < [1/2]
|
||||||
|
* then: lls
|
||||||
|
* else: lls + s
|
||||||
|
*
|
||||||
|
* p = l * 2 - q
|
||||||
|
* qp = (q - l) * 2
|
||||||
|
*
|
||||||
|
* r =
|
||||||
|
* p + 6 * qp * tr
|
||||||
|
* p + 6 * qp * ([2/3] - tr)
|
||||||
|
*
|
||||||
|
* g =
|
||||||
|
* p + 6 * qp * tg
|
||||||
|
* p + 6 * qp * ([2/3] - tg)
|
||||||
|
*
|
||||||
|
* b =
|
||||||
|
* p + 6 * qp * tb
|
||||||
|
* p + 6 * qp * ([2/3] - tb)
|
||||||
|
*/
|
||||||
|
|
||||||
|
module hsl2rgb
|
||||||
|
(input wire clock,
|
||||||
|
input wire reset,
|
||||||
|
|
||||||
|
input wire [7:0] h,
|
||||||
|
input wire [7:0] s,
|
||||||
|
input wire [7:0] l,
|
||||||
|
input wire ready_i,
|
||||||
|
|
||||||
|
output reg [7:0] r,
|
||||||
|
output reg [7:0] g,
|
||||||
|
output reg [7:0] b,
|
||||||
|
output wire valid_o);
|
||||||
|
|
||||||
|
`define C1_6 43
|
||||||
|
`define C1_3 85
|
||||||
|
`define C1_2 128
|
||||||
|
`define C2_3 171
|
||||||
|
`define C1_1 256
|
||||||
|
|
||||||
|
localparam STAGES = 5;
|
||||||
|
logic [STAGES-1:0] valid;
|
||||||
|
|
||||||
|
assign valid_o = valid[STAGES-1];
|
||||||
|
|
||||||
|
always_ff @ (posedge clock, posedge reset)
|
||||||
|
if (reset)
|
||||||
|
valid <= '0;
|
||||||
|
else
|
||||||
|
valid <= { valid[STAGES-2:0], ready_i };
|
||||||
|
|
||||||
|
/* ---------------- Stage 1 ---------------- */
|
||||||
|
logic [8:0] lls; // lls = l0 ± (l0 * s0)
|
||||||
|
logic ls_sub;
|
||||||
|
|
||||||
|
/* verilator lint_off UNUSED */
|
||||||
|
logic [31:0] mac_lls_o;
|
||||||
|
/* verilator lint_on UNUSED */
|
||||||
|
|
||||||
|
assign lls = {mac_lls_o[16:8]};
|
||||||
|
assign ls_sub = l < `C1_2 ? 1'b0 : 1'b1;
|
||||||
|
|
||||||
|
ice40_mac16x16 mac_lls
|
||||||
|
(.clock, .reset,
|
||||||
|
.a({8'b0, l}),
|
||||||
|
.b({8'b0, s}),
|
||||||
|
.s({16'b0, l, 8'b0}),
|
||||||
|
.sub(ls_sub),
|
||||||
|
.y(mac_lls_o));
|
||||||
|
|
||||||
|
/* propagate to next stage */
|
||||||
|
logic [7:0] h1, s1, l1;
|
||||||
|
always_ff @ (posedge clock) begin
|
||||||
|
h1 <= h;
|
||||||
|
s1 <= s;
|
||||||
|
l1 <= l;
|
||||||
|
end
|
||||||
|
|
||||||
|
/* ---------------- stage 2 ---------------- */
|
||||||
|
logic [8:0] q_pre;
|
||||||
|
logic [7:0] q;
|
||||||
|
logic [7:0] minus1h; // minus1h = 256 - h = ~(h - 1)
|
||||||
|
|
||||||
|
always_ff @ (posedge clock) begin
|
||||||
|
q_pre <= l1 < `C1_2 ? lls : lls + s1;
|
||||||
|
minus1h <= ~(h1 - 1);
|
||||||
|
end
|
||||||
|
|
||||||
|
assign q = q_pre[8] ? 8'hff : q_pre[7:0];
|
||||||
|
|
||||||
|
/* propagate to next stage */
|
||||||
|
logic [7:0] h2, l2;
|
||||||
|
always_ff @ (posedge clock) begin
|
||||||
|
h2 <= h1;
|
||||||
|
l2 <= l1;
|
||||||
|
end
|
||||||
|
|
||||||
|
/* ---------------- stage 3 ---------------- */
|
||||||
|
logic [7:0] tr, tg, tb;
|
||||||
|
logic [8:0] p_pre;
|
||||||
|
logic [7:0] p; // p = l * 2 - q
|
||||||
|
logic [7:0] qp; // qp = q - p
|
||||||
|
|
||||||
|
always_ff @ (posedge clock) begin
|
||||||
|
tr <= h2 < 8'(`C2_3) ? h2 + 8'(`C1_3) : 8'(`C1_3) - minus1h;
|
||||||
|
tg <= h2;
|
||||||
|
tb <= h2 >= 8'(`C1_3) ? h2 - 8'(`C1_3) : minus1h;
|
||||||
|
|
||||||
|
p_pre <= (9'(l2) << 1) - q;
|
||||||
|
qp <= 8'((q - l2) << 1);
|
||||||
|
end
|
||||||
|
|
||||||
|
assign p = p_pre[8] ? 8'hff : p_pre[7:0];
|
||||||
|
|
||||||
|
/* propagate to next stage */
|
||||||
|
logic [7:0] q3;
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
q3 <= q;
|
||||||
|
|
||||||
|
/* ---------------- stage 4 ---------------- */
|
||||||
|
logic [7:0] trx, tgx, tbx;
|
||||||
|
logic [10:0] qp6;
|
||||||
|
|
||||||
|
/* verilator lint_off UNUSED */
|
||||||
|
logic [31:0] mac_r_o;
|
||||||
|
logic [31:0] mac_g_o;
|
||||||
|
logic [31:0] mac_b_o;
|
||||||
|
/* verilator lint_on UNUSED */
|
||||||
|
|
||||||
|
assign qp6 = (11'(qp) << 1) + (11'(qp) << 2);
|
||||||
|
assign trx = (tr < `C1_6) ? tr : `C2_3 - tr;
|
||||||
|
assign tgx = (tg < `C1_6) ? tg : `C2_3 - tg;
|
||||||
|
assign tbx = (tb < `C1_6) ? tb : `C2_3 - tb;
|
||||||
|
|
||||||
|
ice40_mac16x16 mac_r
|
||||||
|
(.clock, .reset,
|
||||||
|
.a({5'b0, qp6}),
|
||||||
|
.b({8'b0, trx}),
|
||||||
|
.s({16'b0, p, 8'b0}),
|
||||||
|
.sub(1'b0),
|
||||||
|
.y(mac_r_o));
|
||||||
|
|
||||||
|
ice40_mac16x16 mac_g
|
||||||
|
(.clock, .reset,
|
||||||
|
.a({5'b0, qp6}),
|
||||||
|
.b({8'b0, tgx}),
|
||||||
|
.s({16'b0, p, 8'b0}),
|
||||||
|
.sub(1'b0),
|
||||||
|
.y(mac_g_o));
|
||||||
|
|
||||||
|
ice40_mac16x16 mac_b
|
||||||
|
(.clock, .reset,
|
||||||
|
.a({5'b0, qp6}),
|
||||||
|
.b({8'b0, tbx}),
|
||||||
|
.s({16'b0, p, 8'b0}),
|
||||||
|
.sub(1'b0),
|
||||||
|
.y(mac_b_o));
|
||||||
|
|
||||||
|
/* propagate to next stage */
|
||||||
|
logic [7:0] tr4, tg4, tb4;
|
||||||
|
logic [7:0] p4;
|
||||||
|
logic [7:0] q4;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock) begin
|
||||||
|
tr4 <= tr;
|
||||||
|
tg4 <= tg;
|
||||||
|
tb4 <= tb;
|
||||||
|
p4 <= p;
|
||||||
|
q4 <= q3;
|
||||||
|
end
|
||||||
|
|
||||||
|
/* ---------------- stage 5 ---------------- */
|
||||||
|
always_ff @ (posedge clock) begin
|
||||||
|
if (tr4 < `C1_6) r <= mac_r_o[16] ? 8'hff : mac_r_o[15:8];
|
||||||
|
else if (tr4 < `C1_2) r <= q4;
|
||||||
|
else if (tr4 < `C2_3) r <= mac_r_o[16] ? 8'hff : mac_r_o[15:8];
|
||||||
|
else r <= p4;
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @ (posedge clock) begin
|
||||||
|
if (tg4 < `C1_6) g <= mac_g_o[16] ? 8'hff : mac_g_o[15:8];
|
||||||
|
else if (tg4 < `C1_2) g <= q4;
|
||||||
|
else if (tg4 < `C2_3) g <= mac_g_o[16] ? 8'hff : mac_g_o[15:8];
|
||||||
|
else g <= p4;
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @ (posedge clock) begin
|
||||||
|
if (tb4 < `C1_6) b <= mac_b_o[16] ? 8'hff : mac_b_o[15:8];
|
||||||
|
else if (tb4 < `C1_2) b <= q4;
|
||||||
|
else if (tb4 < `C2_3) b <= mac_b_o[16] ? 8'hff : mac_b_o[15:8];
|
||||||
|
else b <= p4;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // hsl2rgb
|
||||||
98
source/hsv2rgb.sv
Normal file
98
source/hsv2rgb.sv
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
module hsv2rgb
|
||||||
|
(input wire clock,
|
||||||
|
input wire reset,
|
||||||
|
|
||||||
|
input wire [7:0] h,
|
||||||
|
input wire [7:0] s,
|
||||||
|
input wire [7:0] v,
|
||||||
|
input wire ready_i,
|
||||||
|
|
||||||
|
output reg [7:0] r,
|
||||||
|
output reg [7:0] g,
|
||||||
|
output reg [7:0] b,
|
||||||
|
output wire valid_o);
|
||||||
|
|
||||||
|
localparam STAGES = 2;
|
||||||
|
logic [STAGES-1:0] valid;
|
||||||
|
|
||||||
|
assign valid_o = valid[STAGES-1];
|
||||||
|
always_ff @ (posedge clock, posedge reset)
|
||||||
|
if (reset) valid <= '0;
|
||||||
|
else valid <= { valid[STAGES-2:0], ready_i };
|
||||||
|
|
||||||
|
/* ---------------- Stage 1 ---------------- */
|
||||||
|
logic [7:0] flip_s;
|
||||||
|
logic [7:0] vmin;
|
||||||
|
logic [31:0] mac_vmin_o;
|
||||||
|
logic [5:0] h_mod_43;
|
||||||
|
|
||||||
|
assign flip_s = 8'd255 - s;
|
||||||
|
assign vmin = mac_vmin_o[15:8];
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
h_mod_43
|
||||||
|
<= (h < 43) ? 6'(h) :
|
||||||
|
(h < 86) ? 6'(h - 8'd43) :
|
||||||
|
(h < 128) ? 6'(h - 8'd86) :
|
||||||
|
(h < 171) ? 6'(h - 8'd128) :
|
||||||
|
(h < 214) ? 6'(h - 8'd171) :
|
||||||
|
6'(h - 8'd214);
|
||||||
|
|
||||||
|
ice40_mac16x16 mac_lls
|
||||||
|
(.clock, .reset,
|
||||||
|
.a({8'b0, flip_s}),
|
||||||
|
.b({8'b0, v}),
|
||||||
|
.s(32'b0),
|
||||||
|
.sub(1'b0),
|
||||||
|
.y(mac_vmin_o));
|
||||||
|
|
||||||
|
logic [7:0] h1, v1;
|
||||||
|
always_ff @ (posedge clock) begin
|
||||||
|
h1 <= h;
|
||||||
|
v1 <= v;
|
||||||
|
end
|
||||||
|
|
||||||
|
/* ---------------- Stage 2 ---------------- */
|
||||||
|
logic [31:0] mac_a_o;
|
||||||
|
logic [7:0] h_mod_43_6;
|
||||||
|
logic [7:0] v_vmin;
|
||||||
|
logic [7:0] a;
|
||||||
|
|
||||||
|
assign a = mac_a_o[15:8];
|
||||||
|
|
||||||
|
assign h_mod_43_6 = (8'(h_mod_43) << 1) + (8'(h_mod_43) << 2);
|
||||||
|
assign v_vmin = v1 - vmin;
|
||||||
|
|
||||||
|
ice40_mac16x16 mac_a
|
||||||
|
(.clock, .reset,
|
||||||
|
.a({8'b0, v_vmin}),
|
||||||
|
.b({8'b0, h_mod_43_6}),
|
||||||
|
.s(32'b0),
|
||||||
|
.sub(1'b0),
|
||||||
|
.y(mac_a_o));
|
||||||
|
|
||||||
|
logic [7:0] h2, v2, vmin2;
|
||||||
|
always_ff @ (posedge clock) begin
|
||||||
|
h2 <= h1;
|
||||||
|
v2 <= v1;
|
||||||
|
vmin2 <= vmin;
|
||||||
|
end
|
||||||
|
|
||||||
|
/* ---------------- Output ---------------- */
|
||||||
|
logic [7:0] vinc, vdec;
|
||||||
|
|
||||||
|
assign vinc = vmin2 + a;
|
||||||
|
assign vdec = v2 - a;
|
||||||
|
|
||||||
|
always_comb
|
||||||
|
if (h2 < 43) {r, g, b} = {v2, vinc, vmin2};
|
||||||
|
else if (h2 < 86) {r, g, b} = {vdec, v2, vmin2};
|
||||||
|
else if (h2 < 128) {r, g, b} = {vmin2, v2, vinc};
|
||||||
|
else if (h2 < 171) {r, g, b} = {vmin2, vdec, v2};
|
||||||
|
else if (h2 < 214) {r, g, b} = {vinc, vmin2, v2};
|
||||||
|
else {r, g, b} = {v2, vmin2, vdec};
|
||||||
|
|
||||||
|
endmodule // hsv2rgb
|
||||||
135
source/hsx2rgb.rkt
Normal file
135
source/hsx2rgb.rkt
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#lang racket
|
||||||
|
|
||||||
|
(define (hsl2rgb h s l)
|
||||||
|
(define (color q p h)
|
||||||
|
(let ((tc (cond
|
||||||
|
((> h 1) (- h 1))
|
||||||
|
((< h 0) (+ h 1))
|
||||||
|
(else h))))
|
||||||
|
(cond
|
||||||
|
((< tc 1/6) (+ p (* (- q p) tc 6)))
|
||||||
|
((< tc 1/2) q)
|
||||||
|
((< tc 2/3) (+ p (* (- q p) (- 2/3 tc) 6)))
|
||||||
|
(else p))))
|
||||||
|
(let* ((q (if (< l 0.5)
|
||||||
|
(* l (+ 1 s))
|
||||||
|
(+ l s (- (* l s)))))
|
||||||
|
(p (- (* 2 l) q)))
|
||||||
|
(values
|
||||||
|
(inexact->exact (round (* 256 (color q p (+ h 1/3)))))
|
||||||
|
(inexact->exact (round (* 256 (color q p h))))
|
||||||
|
(inexact->exact (round (* 256 (color q p (- h 1/3))))))))
|
||||||
|
|
||||||
|
(define (hsl2rgb-ref h s l)
|
||||||
|
(hsl2rgb (/ h 256) (/ s 256) (/ l 256)))
|
||||||
|
|
||||||
|
(define (hsv2rgb h s v)
|
||||||
|
(let* ((hi (modulo (floor (/ h 256/6)) 6))
|
||||||
|
(vmin (/ (* v (- 256 s)) 256))
|
||||||
|
(a (* (- v vmin) (/ (modulo h 43) 256/6)))
|
||||||
|
(vinc (+ vmin a))
|
||||||
|
(vdec (- v a))
|
||||||
|
|
||||||
|
(vmin (inexact->exact (round vmin)))
|
||||||
|
(vinc (inexact->exact (round vinc)))
|
||||||
|
(vdec (inexact->exact (round vdec))))
|
||||||
|
(cond
|
||||||
|
((= hi 0) (values v vinc vmin))
|
||||||
|
((= hi 1) (values vdec v vmin))
|
||||||
|
((= hi 2) (values vmin v vinc))
|
||||||
|
((= hi 3) (values vmin vdec v))
|
||||||
|
((= hi 4) (values vinc vmin v))
|
||||||
|
((= hi 5) (values v vmin vdec)))))
|
||||||
|
|
||||||
|
(define (hsv2rgb-int h s v)
|
||||||
|
(define (byte-div-43-mod-6 x)
|
||||||
|
(cond
|
||||||
|
((< x 43) 0)
|
||||||
|
((< x 86) 1)
|
||||||
|
((< x 128) 2)
|
||||||
|
((< x 171) 3)
|
||||||
|
((< x 214) 4)
|
||||||
|
(else 5)))
|
||||||
|
|
||||||
|
(define (byte-mod-43 x)
|
||||||
|
(cond
|
||||||
|
((< x 43) x)
|
||||||
|
((< x 86) (- x 43))
|
||||||
|
((< x 128) (- x 86))
|
||||||
|
((< x 171) (- x 128))
|
||||||
|
((< x 214) (- x 171))
|
||||||
|
(else (- x 214))))
|
||||||
|
|
||||||
|
(define (*6 a) (+ (arithmetic-shift a 1)
|
||||||
|
(arithmetic-shift a 2)))
|
||||||
|
|
||||||
|
(let* ((hi (byte-div-43-mod-6 h))
|
||||||
|
(vmin (arithmetic-shift
|
||||||
|
(* (- 255 s) v) -8))
|
||||||
|
(a (arithmetic-shift
|
||||||
|
(* (- v vmin)
|
||||||
|
(*6 (byte-mod-43 h))) -8))
|
||||||
|
(vinc (+ vmin a))
|
||||||
|
(vdec (- v a)))
|
||||||
|
(printf "hi=~a, vmin=~a, a=~a, vinc=~a, vdec=~a\n" hi vmin a vinc vdec)
|
||||||
|
(cond
|
||||||
|
((= hi 0) (values v vinc vmin))
|
||||||
|
((= hi 1) (values vdec v vmin))
|
||||||
|
((= hi 2) (values vmin v vinc))
|
||||||
|
((= hi 3) (values vmin vdec v))
|
||||||
|
((= hi 4) (values vinc vmin v))
|
||||||
|
((= hi 5) (values v vmin vdec)))))
|
||||||
|
|
||||||
|
(define (hsl2rgb-int h s l)
|
||||||
|
(define (*fp8 a b) (arithmetic-shift (* a b) -8))
|
||||||
|
(define (*2 a) (arithmetic-shift a 1))
|
||||||
|
(define (*6 a) (+ (arithmetic-shift a 1)
|
||||||
|
(arithmetic-shift a 2)))
|
||||||
|
|
||||||
|
(define c1/6 43)
|
||||||
|
(define c1/3 85)
|
||||||
|
(define c1/2 128)
|
||||||
|
(define c2/3 171)
|
||||||
|
(define c1 256)
|
||||||
|
|
||||||
|
(let* ((l*s (*fp8 l s))
|
||||||
|
(q (if (< l c1/2)
|
||||||
|
(+ l l*s)
|
||||||
|
(+ l s (- l*s))))
|
||||||
|
(p (- (*2 l) q))
|
||||||
|
(q-p ;;(- q p)
|
||||||
|
(*2 (- q l)))
|
||||||
|
(tr (if (< h c2/3) [+ h c1/3] [- c1/3 (- c1 h)]))
|
||||||
|
(tg h)
|
||||||
|
(tb (if (>= h c1/3) [- h c1/3] [- c1 h]))
|
||||||
|
(q-p*6 (*6 q-p))
|
||||||
|
|
||||||
|
(r (cond
|
||||||
|
((< tr c1/6) [+ p (*fp8 q-p*6 tr)])
|
||||||
|
((< tr c1/2) q)
|
||||||
|
((< tr c2/3) [+ p (*fp8 q-p*6 (- c2/3 tr))])
|
||||||
|
(else p)))
|
||||||
|
|
||||||
|
(g (cond
|
||||||
|
((< tg c1/6) [+ p (*fp8 q-p*6 tg)])
|
||||||
|
((< tg c1/2) q)
|
||||||
|
((< tg c2/3) [+ p (*fp8 q-p*6 (- c2/3 tg))])
|
||||||
|
(else p)))
|
||||||
|
|
||||||
|
(b (cond
|
||||||
|
((< tb c1/6) [+ p (*fp8 q-p*6 tb)])
|
||||||
|
((< tb c1/2) q)
|
||||||
|
((< tb c2/3) [+ p (*fp8 q-p*6 (- c2/3 tb))])
|
||||||
|
(else p))))
|
||||||
|
;; (printf "q=~a p=~a q-p=~a tr=~a tg=~a tb=~a\n" q p q-p tr tg tb)
|
||||||
|
(values r g b)))
|
||||||
|
|
||||||
|
(define (p f h s x)
|
||||||
|
(let-values (((r g b) (f h s x)))
|
||||||
|
(printf "HSX ~a ~a ~a -> " h s x)
|
||||||
|
(printf "RGB ~a ~a ~a\n\n" r g b)))
|
||||||
|
|
||||||
|
;;(p 20 255 100)
|
||||||
|
(p hsv2rgb-int 50 100 150)
|
||||||
|
(p hsv2rgb-int 111 222 33)
|
||||||
|
(p hsv2rgb-int 200 150 50)
|
||||||
81
source/ice40_2mac8x8.sv
Normal file
81
source/ice40_2mac8x8.sv
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
/* verilator lint_off PINCONNECTEMPTY */
|
||||||
|
|
||||||
|
module ice40_2mac8x8 #(parameter SIGNED = 0)
|
||||||
|
(input wire clock,
|
||||||
|
input wire reset,
|
||||||
|
input wire [7:0] a0,
|
||||||
|
input wire [7:0] b0,
|
||||||
|
input wire [15:0] s0,
|
||||||
|
input wire sub0,
|
||||||
|
output wire [15:0] y0,
|
||||||
|
|
||||||
|
input wire [7:0] a1,
|
||||||
|
input wire [7:0] b1,
|
||||||
|
input wire [15:0] s1,
|
||||||
|
input wire sub1,
|
||||||
|
output wire [15:0] y1);
|
||||||
|
|
||||||
|
/* register 'sub' input */
|
||||||
|
logic sub0_r, sub1_r;
|
||||||
|
always_ff @ (posedge clock) begin
|
||||||
|
sub0_r <= sub0;
|
||||||
|
sub1_r <= sub1;
|
||||||
|
end
|
||||||
|
|
||||||
|
logic [31:0] mac_o;
|
||||||
|
assign {y0, y1} = mac_o;
|
||||||
|
|
||||||
|
SB_MAC16
|
||||||
|
#(.NEG_TRIGGER(1'b0),
|
||||||
|
.C_REG(1'b1), // Registered C
|
||||||
|
.A_REG(1'b1), // Registered A
|
||||||
|
.B_REG(1'b1), // Registered B
|
||||||
|
.D_REG(1'b1), // Registered D
|
||||||
|
.TOP_8x8_MULT_REG(1'b0),
|
||||||
|
.BOT_8x8_MULT_REG(1'b0),
|
||||||
|
.PIPELINE_16x16_MULT_REG1(1'b0),
|
||||||
|
.PIPELINE_16x16_MULT_REG2(1'b0),
|
||||||
|
.TOPOUTPUT_SELECT(2'b00), // TOP output - ADD/SUB unregistered
|
||||||
|
.TOPADDSUB_LOWERINPUT(2'b01), // TOP adder input 1 - 8x8 top multiplier output
|
||||||
|
.TOPADDSUB_UPPERINPUT(1'b1), // TOP adder input 2 - input C
|
||||||
|
.TOPADDSUB_CARRYSELECT(2'b00), // TOP adder carry input - constant 0
|
||||||
|
.BOTOUTPUT_SELECT(2'b00), // BOT output - ADD/SUB unregistered
|
||||||
|
.BOTADDSUB_LOWERINPUT(2'b01), // BOT adder input 1 - 8x8 bot multiplier output
|
||||||
|
.BOTADDSUB_UPPERINPUT(1'b1), // BOT adder input 2 - input D
|
||||||
|
.BOTADDSUB_CARRYSELECT(2'b00), // BOT adder carry input - constant 0
|
||||||
|
.MODE_8x8(1'b1),
|
||||||
|
.A_SIGNED(SIGNED),
|
||||||
|
.B_SIGNED(SIGNED))
|
||||||
|
mac_r
|
||||||
|
(.CLK(clock),
|
||||||
|
.CE(1'b1),
|
||||||
|
.C(s0),
|
||||||
|
.A({a0, a1}),
|
||||||
|
.B({b0, b1}),
|
||||||
|
.D(s1),
|
||||||
|
.AHOLD(1'b0),
|
||||||
|
.BHOLD(1'b0),
|
||||||
|
.CHOLD(1'b0),
|
||||||
|
.DHOLD(1'b0),
|
||||||
|
.IRSTTOP(reset),
|
||||||
|
.IRSTBOT(reset),
|
||||||
|
.ORSTTOP(reset),
|
||||||
|
.ORSTBOT(reset),
|
||||||
|
.OLOADTOP(1'b0),
|
||||||
|
.OLOADBOT(1'b0),
|
||||||
|
.ADDSUBTOP(sub0_r),
|
||||||
|
.ADDSUBBOT(sub1_r),
|
||||||
|
.OHOLDTOP(1'b0),
|
||||||
|
.OHOLDBOT(1'b0),
|
||||||
|
.CI(1'b0),
|
||||||
|
.ACCUMCI(1'b0),
|
||||||
|
.SIGNEXTIN(1'b0),
|
||||||
|
.O(mac_o),
|
||||||
|
.CO(),
|
||||||
|
.ACCUMCO(),
|
||||||
|
.SIGNEXTOUT());
|
||||||
|
|
||||||
|
endmodule // ice40_macadd16x16
|
||||||
70
source/ice40_mac16x16.sv
Normal file
70
source/ice40_mac16x16.sv
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
/* verilator lint_off PINCONNECTEMPTY */
|
||||||
|
|
||||||
|
module ice40_mac16x16 #(parameter SIGNED = 0)
|
||||||
|
(input wire clock,
|
||||||
|
input wire reset,
|
||||||
|
input wire [15:0] a,
|
||||||
|
input wire [15:0] b,
|
||||||
|
input wire [31:0] s,
|
||||||
|
input wire sub,
|
||||||
|
output wire [31:0] y);
|
||||||
|
|
||||||
|
/* register 'sub' input */
|
||||||
|
logic sub_r;
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
sub_r <= sub;
|
||||||
|
|
||||||
|
SB_MAC16
|
||||||
|
#(.NEG_TRIGGER(1'b0),
|
||||||
|
.C_REG(1'b1), // Registered C
|
||||||
|
.A_REG(1'b1), // Registered A
|
||||||
|
.B_REG(1'b1), // Registered B
|
||||||
|
.D_REG(1'b1), // Registered D
|
||||||
|
.TOP_8x8_MULT_REG(1'b0),
|
||||||
|
.BOT_8x8_MULT_REG(1'b0),
|
||||||
|
.PIPELINE_16x16_MULT_REG1(1'b0),
|
||||||
|
.PIPELINE_16x16_MULT_REG2(1'b0),
|
||||||
|
.TOPOUTPUT_SELECT(2'b00), // TOP output - ADD/SUB unregistered
|
||||||
|
.TOPADDSUB_LOWERINPUT(2'b10), // TOP adder input 1 - 16x16 multiplier upper word
|
||||||
|
.TOPADDSUB_UPPERINPUT(1'b1), // TOP adder input 2 - input C
|
||||||
|
.TOPADDSUB_CARRYSELECT(2'b00), // TOP adder carry input - constant 0
|
||||||
|
.BOTOUTPUT_SELECT(2'b00), // BOT output - ADD/SUB unregistered
|
||||||
|
.BOTADDSUB_LOWERINPUT(2'b10), // BOT adder input 1 - 16x16 multiplier lower word
|
||||||
|
.BOTADDSUB_UPPERINPUT(1'b1), // BOT adder input 2 - input D
|
||||||
|
.BOTADDSUB_CARRYSELECT(2'b00), // BOT adder carry input - constant 0
|
||||||
|
.MODE_8x8(1'b0),
|
||||||
|
.A_SIGNED(SIGNED),
|
||||||
|
.B_SIGNED(SIGNED))
|
||||||
|
mac_r
|
||||||
|
(.CLK(clock),
|
||||||
|
.CE(1'b1),
|
||||||
|
.C(s[31:16]),
|
||||||
|
.A(a),
|
||||||
|
.B(b),
|
||||||
|
.D(s[15:0]),
|
||||||
|
.AHOLD(1'b0),
|
||||||
|
.BHOLD(1'b0),
|
||||||
|
.CHOLD(1'b0),
|
||||||
|
.DHOLD(1'b0),
|
||||||
|
.IRSTTOP(reset),
|
||||||
|
.IRSTBOT(reset),
|
||||||
|
.ORSTTOP(reset),
|
||||||
|
.ORSTBOT(reset),
|
||||||
|
.OLOADTOP(1'b0),
|
||||||
|
.OLOADBOT(1'b0),
|
||||||
|
.ADDSUBTOP(sub_r),
|
||||||
|
.ADDSUBBOT(sub_r),
|
||||||
|
.OHOLDTOP(1'b0),
|
||||||
|
.OHOLDBOT(1'b0),
|
||||||
|
.CI(1'b0),
|
||||||
|
.ACCUMCI(1'b0),
|
||||||
|
.SIGNEXTIN(1'b0),
|
||||||
|
.O(y),
|
||||||
|
.CO(),
|
||||||
|
.ACCUMCO(),
|
||||||
|
.SIGNEXTOUT());
|
||||||
|
|
||||||
|
endmodule // ice40_macadd16x16
|
||||||
94
source/ice40_spram.sv
Normal file
94
source/ice40_spram.sv
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
module ice40_spram
|
||||||
|
(input wire clock,
|
||||||
|
input wire [15:0] addr,
|
||||||
|
input wire [15:0] data_i,
|
||||||
|
output wire [15:0] data_o,
|
||||||
|
input wire wr);
|
||||||
|
|
||||||
|
logic [15:0] data0_o;
|
||||||
|
logic [15:0] data1_o;
|
||||||
|
logic [15:0] data2_o;
|
||||||
|
logic [15:0] data3_o;
|
||||||
|
logic w0, w1, w2, w3;
|
||||||
|
|
||||||
|
logic [15:0] datax_o;
|
||||||
|
assign data_o = datax_o;
|
||||||
|
|
||||||
|
always @(*) begin
|
||||||
|
{w0, w1, w2, w3} = '0;
|
||||||
|
|
||||||
|
case (addr[15:14])
|
||||||
|
2'd0: begin
|
||||||
|
datax_o = data0_o;
|
||||||
|
w0 = wr;
|
||||||
|
end
|
||||||
|
|
||||||
|
2'd1: begin
|
||||||
|
datax_o = data1_o;
|
||||||
|
w1 = wr;
|
||||||
|
end
|
||||||
|
|
||||||
|
2'd2: begin
|
||||||
|
datax_o = data2_o;
|
||||||
|
w2 = wr;
|
||||||
|
end
|
||||||
|
|
||||||
|
2'd3: begin
|
||||||
|
datax_o = data3_o;
|
||||||
|
w3 = wr;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
SB_SPRAM256KA spram0
|
||||||
|
(.CLOCK(clock),
|
||||||
|
.ADDRESS(addr[13:0]),
|
||||||
|
.DATAIN(data_i),
|
||||||
|
.DATAOUT(data0_o),
|
||||||
|
.WREN(w0),
|
||||||
|
.MASKWREN({w0, w0, w0, w0}),
|
||||||
|
.CHIPSELECT(1'b1),
|
||||||
|
.STANDBY(1'b0),
|
||||||
|
.SLEEP(1'b0),
|
||||||
|
.POWEROFF(1'b1));
|
||||||
|
|
||||||
|
SB_SPRAM256KA spram1
|
||||||
|
(.CLOCK(clock),
|
||||||
|
.ADDRESS(addr[13:0]),
|
||||||
|
.DATAIN(data_i),
|
||||||
|
.DATAOUT(data1_o),
|
||||||
|
.WREN(w1),
|
||||||
|
.MASKWREN({w1, w1, w1, w1}),
|
||||||
|
.CHIPSELECT(1'b1),
|
||||||
|
.STANDBY(1'b0),
|
||||||
|
.SLEEP(1'b0),
|
||||||
|
.POWEROFF(1'b1));
|
||||||
|
|
||||||
|
SB_SPRAM256KA spram2
|
||||||
|
(.CLOCK(clock),
|
||||||
|
.ADDRESS(addr[13:0]),
|
||||||
|
.DATAIN(data_i),
|
||||||
|
.DATAOUT(data2_o),
|
||||||
|
.WREN(w2),
|
||||||
|
.MASKWREN({w2, w2, w2, w2}),
|
||||||
|
.CHIPSELECT(1'b1),
|
||||||
|
.STANDBY(1'b0),
|
||||||
|
.SLEEP(1'b0),
|
||||||
|
.POWEROFF(1'b1));
|
||||||
|
|
||||||
|
SB_SPRAM256KA spram3
|
||||||
|
(.CLOCK(clock),
|
||||||
|
.ADDRESS(addr[13:0]),
|
||||||
|
.DATAIN(data_i),
|
||||||
|
.DATAOUT(data3_o),
|
||||||
|
.WREN(w3),
|
||||||
|
.MASKWREN({w3, w3, w3, w3}),
|
||||||
|
.CHIPSELECT(1'b1),
|
||||||
|
.STANDBY(1'b0),
|
||||||
|
.SLEEP(1'b0),
|
||||||
|
.POWEROFF(1'b1));
|
||||||
|
|
||||||
|
endmodule // ice40_spram
|
||||||
80
source/lcd_init.rom
Normal file
80
source/lcd_init.rom
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
0CF // ---- Power control B
|
||||||
|
100 // default
|
||||||
|
1C9 // (or C1) непонятно что это. По документу вообще нужно 89 или 81
|
||||||
|
130 // default
|
||||||
|
|
||||||
|
0ED // ---- Power on sequence
|
||||||
|
164 // ?
|
||||||
|
103 // ?
|
||||||
|
112 // ?
|
||||||
|
181 // DDVDH enhance mode
|
||||||
|
|
||||||
|
0E8 // ---- Driver timing control A
|
||||||
|
185 // Gate driver overlap timing +1unit (?)
|
||||||
|
110 // ?
|
||||||
|
17A // Precharge (default)
|
||||||
|
|
||||||
|
0CB // ---- Power control A
|
||||||
|
139 // default
|
||||||
|
12C // default
|
||||||
|
100 // default
|
||||||
|
134 // default (Vcore = 1.6V)
|
||||||
|
102 // default (DDVDH = 5.6V)
|
||||||
|
|
||||||
|
0F7 // ---- Pump ratio control
|
||||||
|
120 // DDVDH = 2xVCI
|
||||||
|
|
||||||
|
0EA // ---- Driver timing control B
|
||||||
|
100 // ?
|
||||||
|
100 // default
|
||||||
|
|
||||||
|
0C0 // ---- Power control 1
|
||||||
|
11B // VRH = 4.2V
|
||||||
|
|
||||||
|
0C1 // ---- Power control 2
|
||||||
|
100 // ?
|
||||||
|
|
||||||
|
0C5 // ---- VCOM control 1
|
||||||
|
130 // (or 3F) VCOMH = 3.9V
|
||||||
|
130 // (or 3C) VCOML = -1.3V
|
||||||
|
|
||||||
|
0C7 // ---- VCOM control 2
|
||||||
|
1B7 // VCOMH = VMH-9, VCOML = VML-9
|
||||||
|
|
||||||
|
036 // ---- Memory Access Control
|
||||||
|
108 // RGB reverse
|
||||||
|
|
||||||
|
03A // ---- Pixel format set
|
||||||
|
155 // 66 - 18 bit per pixel, 55 - 16 bit per pixel
|
||||||
|
|
||||||
|
0F6 // ---- Interface control
|
||||||
|
101 // default
|
||||||
|
110 // EPF=01 (RGB mapping to 16-bit word)
|
||||||
|
|
||||||
|
0B1 // ---- Frame rate control
|
||||||
|
100 // fosc/1
|
||||||
|
11A // 26 clock per line (default - 1B)
|
||||||
|
|
||||||
|
0B6 // ---- Display Function Control (отсутствуют два параметра)
|
||||||
|
10A // default
|
||||||
|
1A2 // Reverse shift direction
|
||||||
|
|
||||||
|
0F2 // ---- 3Gamma Function Disable
|
||||||
|
100
|
||||||
|
|
||||||
|
026 // ---- Gamma curve
|
||||||
|
101 // default
|
||||||
|
|
||||||
|
02B // ---- Page address set 0..319
|
||||||
|
100
|
||||||
|
100
|
||||||
|
101
|
||||||
|
13f
|
||||||
|
|
||||||
|
02A // ---- Column address set 0..239
|
||||||
|
100
|
||||||
|
100
|
||||||
|
100
|
||||||
|
1ef
|
||||||
|
|
||||||
|
011 // ---- Exit Sleep
|
||||||
98
source/lcd_spi.sv
Normal file
98
source/lcd_spi.sv
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
`include "assert.vh"
|
||||||
|
|
||||||
|
module lcd_spi #(parameter DATA_WIDTH = 8,
|
||||||
|
parameter SPI_CLK_PERIOD = 10,
|
||||||
|
parameter PUSH_ON_DONE = 0)
|
||||||
|
(input wire clock,
|
||||||
|
input wire reset,
|
||||||
|
|
||||||
|
input wire [DATA_WIDTH-1:0] data_i,
|
||||||
|
input wire push_i,
|
||||||
|
output reg done_o,
|
||||||
|
|
||||||
|
output reg spi_clk_o,
|
||||||
|
output wire spi_dat_o);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
`assert(DATA_WIDTH > 0);
|
||||||
|
`assert(SPI_CLK_PERIOD >= 2);
|
||||||
|
end
|
||||||
|
|
||||||
|
localparam SCLK_LOW = SPI_CLK_PERIOD / 2;
|
||||||
|
|
||||||
|
logic [$clog2(SPI_CLK_PERIOD)-1:0] sclk_cntr;
|
||||||
|
logic sclk_one;
|
||||||
|
logic sclk_nededge;
|
||||||
|
logic do_push;
|
||||||
|
|
||||||
|
assign sclk_one = (sclk_cntr < SCLK_LOW) ? 1'b0 : 1'b1;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock, posedge reset)
|
||||||
|
if (reset) begin
|
||||||
|
sclk_cntr <= '0;
|
||||||
|
sclk_nededge <= 1'b0;
|
||||||
|
spi_clk_o <= 1'b0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
sclk_nededge <= 1'b0;
|
||||||
|
spi_clk_o <= do_push ? sclk_one : 1'b0;
|
||||||
|
|
||||||
|
if (do_push || sclk_one) begin
|
||||||
|
if (sclk_cntr == (SPI_CLK_PERIOD-1)) begin
|
||||||
|
sclk_cntr <= '0;
|
||||||
|
sclk_nededge <= 1'b1;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
sclk_cntr <= sclk_cntr + 1'b1;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
sclk_cntr <= '0;
|
||||||
|
end
|
||||||
|
|
||||||
|
localparam BIT_CW = $clog2(DATA_WIDTH);
|
||||||
|
logic [BIT_CW-1:0] sbit_cntr;
|
||||||
|
logic [DATA_WIDTH-1:0] data_sr;
|
||||||
|
|
||||||
|
assign spi_dat_o = data_sr[DATA_WIDTH-1];
|
||||||
|
|
||||||
|
logic push;
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (PUSH_ON_DONE == 0)
|
||||||
|
assign push = push_i & done_o;
|
||||||
|
else
|
||||||
|
assign push = push_i;
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
always_ff @(posedge clock, posedge reset)
|
||||||
|
if (reset) begin
|
||||||
|
do_push <= 1'b0;
|
||||||
|
done_o <= 1'b0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
if (do_push) begin
|
||||||
|
if (sclk_nededge) begin
|
||||||
|
data_sr <= data_sr << 1;
|
||||||
|
sbit_cntr <= sbit_cntr + 1'b1;
|
||||||
|
|
||||||
|
if (sbit_cntr == BIT_CW'(DATA_WIDTH-1)) begin
|
||||||
|
do_push <= 1'b0;
|
||||||
|
done_o <= 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
done_o <= 1'b0;
|
||||||
|
|
||||||
|
if (push) begin
|
||||||
|
data_sr <= data_i;
|
||||||
|
sbit_cntr <= '0;
|
||||||
|
do_push <= 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // lcd_spi
|
||||||
737
source/lcd_top.sv
Normal file
737
source/lcd_top.sv
Normal file
@ -0,0 +1,737 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
/* Yosys do not support SPRAM and MAC inferring */
|
||||||
|
`define USE_SPRAM_PRIMITIVE
|
||||||
|
`define USE_MAC_PRIMITIVE
|
||||||
|
|
||||||
|
module lcd_top #(parameter SPI_CLK_PERIOD = 6)
|
||||||
|
(input logic clock,
|
||||||
|
input logic reset,
|
||||||
|
|
||||||
|
output logic lcd_spi_csn_o,
|
||||||
|
output logic lcd_spi_clk_o,
|
||||||
|
output logic lcd_spi_dat_o,
|
||||||
|
output logic lcd_spi_dcn_o,
|
||||||
|
|
||||||
|
input logic redraw_i,
|
||||||
|
output logic done_o,
|
||||||
|
|
||||||
|
input logic [7:0] x_i,
|
||||||
|
input logic [8:0] y_i,
|
||||||
|
input logic [15:0] color_i,
|
||||||
|
output logic [15:0] color_o,
|
||||||
|
input logic req_i,
|
||||||
|
output logic ack_o,
|
||||||
|
input logic wr_i);
|
||||||
|
|
||||||
|
/* Display size */
|
||||||
|
localparam DISPLAY_MEM_SIZE = 320 * 240 * 2; // 2 byte per pixel
|
||||||
|
localparam DISPLAY_MEM_CW = $clog2(DISPLAY_MEM_SIZE);
|
||||||
|
|
||||||
|
/* Display x/y address width */
|
||||||
|
localparam DISPLAY_XCW = 8,
|
||||||
|
DISPLAY_YCW = 9;
|
||||||
|
|
||||||
|
/* Screen size and origin */
|
||||||
|
localparam XSIZE = 240,
|
||||||
|
YSIZE = 272,
|
||||||
|
XORIG = 0,
|
||||||
|
YORIG = 24;
|
||||||
|
|
||||||
|
localparam FBSIZE = XSIZE * YSIZE;
|
||||||
|
localparam FBCW = $clog2(FBSIZE);
|
||||||
|
|
||||||
|
/* Drawing block size */
|
||||||
|
localparam BLOCK_XS = 16, // must be power of 2
|
||||||
|
BLOCK_YS = 16; // must be power of 2
|
||||||
|
|
||||||
|
localparam GRID_XS = XSIZE / BLOCK_XS,
|
||||||
|
GRID_YS = YSIZE / BLOCK_YS;
|
||||||
|
|
||||||
|
localparam BLOCK_XS_CW = $clog2(BLOCK_XS);
|
||||||
|
localparam BLOCK_YS_CW = $clog2(BLOCK_YS);
|
||||||
|
|
||||||
|
localparam GRID_XS_CW = $clog2(GRID_XS);
|
||||||
|
localparam GRID_YS_CW = $clog2(GRID_YS);
|
||||||
|
|
||||||
|
localparam DFLAG_SIZE = GRID_XS * GRID_YS;
|
||||||
|
localparam DFLAG_CW = $clog2(DFLAG_SIZE);
|
||||||
|
|
||||||
|
localparam BLOCK_SIZE = BLOCK_XS * BLOCK_YS;
|
||||||
|
localparam BLOCK_CW = $clog2(BLOCK_SIZE);
|
||||||
|
|
||||||
|
/* --------- Drawing flags memory --------- */
|
||||||
|
logic dflag[DFLAG_SIZE];
|
||||||
|
logic dflag_wdata;
|
||||||
|
logic dflag_rdata;
|
||||||
|
logic [DFLAG_CW-1:0] dflag_waddr;
|
||||||
|
logic [DFLAG_CW-1:0] dflag_raddr;
|
||||||
|
logic [DFLAG_CW-1:0] dflag_int_addr; // for screen refresher
|
||||||
|
logic [DFLAG_CW-1:0] dflag_ext_addr; // for external master
|
||||||
|
logic dflag_wr;
|
||||||
|
logic dflag_set;
|
||||||
|
logic dflag_clr;
|
||||||
|
|
||||||
|
assign dflag_wr = dflag_set | dflag_clr;
|
||||||
|
assign dflag_waddr = dflag_clr ? dflag_int_addr : dflag_ext_addr;
|
||||||
|
assign dflag_raddr = dflag_int_addr;
|
||||||
|
assign dflag_wdata = dflag_set;
|
||||||
|
|
||||||
|
/* Infer as sysMEM Block RAM */
|
||||||
|
always_ff @ (posedge clock) begin
|
||||||
|
if (dflag_wr)
|
||||||
|
dflag[dflag_waddr] <= dflag_wdata;
|
||||||
|
|
||||||
|
dflag_rdata <= dflag[dflag_raddr];
|
||||||
|
end
|
||||||
|
|
||||||
|
/* --------- Frame buffer RAM (one-port block RAM)--------- */
|
||||||
|
logic [FBCW-1:0] fbaddr;
|
||||||
|
logic [15:0] fb_rdata;
|
||||||
|
logic [15:0] fb_wdata;
|
||||||
|
logic fbwrite;
|
||||||
|
|
||||||
|
`ifdef USE_SPRAM_PRIMITIVE
|
||||||
|
ice40_spram spram_i
|
||||||
|
(.clock(clock),
|
||||||
|
.addr(fbaddr),
|
||||||
|
.data_i(fb_wdata),
|
||||||
|
.data_o(fb_rdata),
|
||||||
|
.wr(fbwrite));
|
||||||
|
`else
|
||||||
|
logic [15:0] fbram[FBSIZE];
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
if (fbwrite) begin
|
||||||
|
fbram[fbaddr] <= fb_wdata;
|
||||||
|
fb_rdata <= 'x;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
fb_rdata <= fbram[fbaddr];
|
||||||
|
`endif
|
||||||
|
|
||||||
|
/* --------- Framebuffer arbiter --------- */
|
||||||
|
logic [FBCW-1:0] fba_int; // Frame buffer address from refresher
|
||||||
|
logic [FBCW-1:0] fba_ext; // Frame buffer address from client
|
||||||
|
|
||||||
|
logic fb_busy_int;
|
||||||
|
logic fb_busy_ext;
|
||||||
|
logic fb_clear;
|
||||||
|
|
||||||
|
assign fbaddr = fb_busy_int ? fba_int : fba_ext;
|
||||||
|
assign color_o = fb_rdata;
|
||||||
|
assign fb_wdata = fb_clear ? '0 : color_i;
|
||||||
|
|
||||||
|
enum int unsigned {
|
||||||
|
FBST_CLEAR = 0,
|
||||||
|
FBST_CLEAR_NEXT,
|
||||||
|
FBST_WAIT,
|
||||||
|
FBST_ADDR,
|
||||||
|
FBST_READ,
|
||||||
|
FBST_DONE
|
||||||
|
} fbst;
|
||||||
|
|
||||||
|
logic [FBCW-1:0] ymult;
|
||||||
|
logic [DFLAG_CW-1:0] fmult;
|
||||||
|
|
||||||
|
`ifdef USE_MAC_PRIMITIVE
|
||||||
|
wire [31:0] ymac_o;
|
||||||
|
wire [31:0] fmac_o;
|
||||||
|
|
||||||
|
ice40_mac16x16 ymac_i
|
||||||
|
(.clock, .reset,
|
||||||
|
.a(16'(y_i)),
|
||||||
|
.b(16'(XSIZE)),
|
||||||
|
.s(32'b0),
|
||||||
|
.sub(1'b0),
|
||||||
|
.y(ymac_o));
|
||||||
|
|
||||||
|
ice40_mac16x16 fmac_i
|
||||||
|
(.clock, .reset,
|
||||||
|
.a(16'(y_i) >> BLOCK_YS_CW),
|
||||||
|
.b(16'(GRID_XS)),
|
||||||
|
.s(32'b0),
|
||||||
|
.sub(1'b0),
|
||||||
|
.y(fmac_o));
|
||||||
|
|
||||||
|
assign ymult = ymac_o[FBCW-1:0];
|
||||||
|
assign fmult = fmac_o[DFLAG_CW-1:0];
|
||||||
|
`endif
|
||||||
|
|
||||||
|
always_ff @ (posedge clock, posedge reset)
|
||||||
|
if (reset) begin
|
||||||
|
fbst <= FBST_CLEAR;
|
||||||
|
ack_o <= 1'b0;
|
||||||
|
fbwrite <= 1'b0;
|
||||||
|
fb_busy_ext <= 1'b0;
|
||||||
|
dflag_set <= 1'b0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
case (fbst)
|
||||||
|
/* Clear frame buffer RAM */
|
||||||
|
FBST_CLEAR: begin
|
||||||
|
fba_ext <= '0;
|
||||||
|
fbwrite <= 1'b1;
|
||||||
|
fb_busy_ext <= 1'b1;
|
||||||
|
fb_clear <= 1'b1;
|
||||||
|
fbst <= FBST_CLEAR_NEXT;
|
||||||
|
end
|
||||||
|
|
||||||
|
FBST_CLEAR_NEXT:
|
||||||
|
if (fba_ext == (FBSIZE-1)) begin
|
||||||
|
fbwrite <= 1'b0;
|
||||||
|
fb_busy_ext <= 1'b0;
|
||||||
|
fb_clear <= 1'b0;
|
||||||
|
fbst <= FBST_WAIT;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
fba_ext <= fba_ext + 1'b1;
|
||||||
|
|
||||||
|
/* Main loop */
|
||||||
|
FBST_WAIT:
|
||||||
|
if (req_i && !fb_busy_int)
|
||||||
|
if (x_i >= XSIZE || y_i >= YSIZE) begin
|
||||||
|
ack_o <= 1'b1;
|
||||||
|
fbst <= FBST_READ;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
|
||||||
|
`ifndef USE_MAC_PRIMITIVE
|
||||||
|
ymult <= y_i * XSIZE;
|
||||||
|
fmult <= GRID_YS_CW'(y_i >> BLOCK_YS_CW) * GRID_XS;
|
||||||
|
`endif
|
||||||
|
fb_busy_ext <= 1'b1;
|
||||||
|
fbst <= FBST_ADDR;
|
||||||
|
end
|
||||||
|
|
||||||
|
FBST_ADDR:
|
||||||
|
if (fb_busy_int) begin
|
||||||
|
fbst <= FBST_WAIT;
|
||||||
|
fb_busy_ext <= 1'b0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
fba_ext <= ymult + FBCW'(x_i);
|
||||||
|
dflag_ext_addr <= fmult + DFLAG_CW'(x_i >> BLOCK_XS_CW);
|
||||||
|
|
||||||
|
if (wr_i) begin
|
||||||
|
ack_o <= 1'b1;
|
||||||
|
fbwrite <= 1'b1;
|
||||||
|
dflag_set <= 1'b1;
|
||||||
|
fbst <= FBST_DONE;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
fbst <= FBST_READ;
|
||||||
|
end
|
||||||
|
|
||||||
|
FBST_READ: begin
|
||||||
|
ack_o <= 1'b1;
|
||||||
|
fbst <= FBST_DONE;
|
||||||
|
end
|
||||||
|
|
||||||
|
FBST_DONE: begin
|
||||||
|
fbwrite <= 1'b0;
|
||||||
|
dflag_set <= 1'b0;
|
||||||
|
ack_o <= 1'b0;
|
||||||
|
fb_busy_ext <= 1'b0;
|
||||||
|
fbst <= FBST_WAIT;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
/* --------- Read initialization commands from file --------- */
|
||||||
|
localparam INIT_FILE = "lcd_init.rom";
|
||||||
|
localparam INIT_ROM_SIZE = 64;
|
||||||
|
localparam INIT_DATA_SIZE = 61;
|
||||||
|
localparam INIT_ROM_CW = $clog2(INIT_ROM_SIZE);
|
||||||
|
|
||||||
|
logic [8:0] init_rom [INIT_ROM_SIZE];
|
||||||
|
logic [INIT_ROM_CW-1:0] init_addr;
|
||||||
|
logic [8:0] init_data;
|
||||||
|
|
||||||
|
initial $readmemh(INIT_FILE, init_rom, 0, INIT_DATA_SIZE-1);
|
||||||
|
|
||||||
|
/* Block RAM as ROM */
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
init_data <= init_rom[init_addr];
|
||||||
|
|
||||||
|
/* --------- SPI master --------- */
|
||||||
|
logic [7:0] spi_data;
|
||||||
|
logic spi_push;
|
||||||
|
logic spi_done;
|
||||||
|
|
||||||
|
lcd_spi #(.DATA_WIDTH(8),
|
||||||
|
.SPI_CLK_PERIOD(SPI_CLK_PERIOD),
|
||||||
|
.PUSH_ON_DONE(1)) spim_i
|
||||||
|
(.clock, .reset,
|
||||||
|
.data_i(spi_data),
|
||||||
|
.push_i(spi_push),
|
||||||
|
.done_o(spi_done),
|
||||||
|
.spi_clk_o(lcd_spi_clk_o),
|
||||||
|
.spi_dat_o(lcd_spi_dat_o));
|
||||||
|
|
||||||
|
/* --------- Main FSM --------- */
|
||||||
|
`ifdef TESTBENCH
|
||||||
|
localparam INIT_DELAY = 250;
|
||||||
|
`else
|
||||||
|
// localparam INIT_DELAY = 7500000;
|
||||||
|
localparam INIT_DELAY = 250;
|
||||||
|
`endif
|
||||||
|
|
||||||
|
enum int unsigned {
|
||||||
|
ST_PREINIT_DELAY = 0, // 0
|
||||||
|
ST_INIT_PUSH_SPI,
|
||||||
|
ST_INIT_WAIT_SPI,
|
||||||
|
ST_INIT_WAIT_LAST,
|
||||||
|
ST_POSTINIT_DELAY,
|
||||||
|
ST_DISPLAY_ON,
|
||||||
|
ST_DISPLAY_ONW,
|
||||||
|
ST_SCRCLR_CMD,
|
||||||
|
ST_SCRCLR,
|
||||||
|
ST_SCRCLR_LAST,
|
||||||
|
ST_START_REDRAW, // 10
|
||||||
|
ST_READ_FLAG,
|
||||||
|
ST_CHECK_FLAG,
|
||||||
|
ST_CLEAR_FLAG,
|
||||||
|
ST_CADDR_CMD,
|
||||||
|
ST_CADDR_0,
|
||||||
|
ST_CADDR_1,
|
||||||
|
ST_CADDR_2,
|
||||||
|
ST_CADDR_3,
|
||||||
|
ST_PADDR_CMD,
|
||||||
|
ST_PADDR_0, // 20
|
||||||
|
ST_PADDR_1,
|
||||||
|
ST_PADDR_2,
|
||||||
|
ST_PADDR_3,
|
||||||
|
ST_WRITE_CMD,
|
||||||
|
ST_WRITE_CMDW,
|
||||||
|
ST_FB_READ,
|
||||||
|
ST_STORE_PIXEL,
|
||||||
|
ST_WRITE_PIXEL_H,
|
||||||
|
ST_WRITE_PIXEL_L,
|
||||||
|
ST_NEXT_PIXEL, // 30
|
||||||
|
ST_NEXT_BLOCK
|
||||||
|
} state, next;
|
||||||
|
|
||||||
|
always_ff @(posedge clock, posedge reset)
|
||||||
|
if (reset) state <= ST_PREINIT_DELAY;
|
||||||
|
else state <= next;
|
||||||
|
|
||||||
|
/* Pre/post init delay counter */
|
||||||
|
localparam INIT_DELAY_CW = $clog2(INIT_DELAY);
|
||||||
|
logic [INIT_DELAY_CW-1:0] delay_cntr;
|
||||||
|
logic delay_cntr_incr;
|
||||||
|
|
||||||
|
always_ff @(posedge clock)
|
||||||
|
delay_cntr <= (~reset && delay_cntr_incr) ?
|
||||||
|
delay_cntr + 1'b1 : '0;
|
||||||
|
|
||||||
|
/* Initialization ROM address */
|
||||||
|
logic init_addr_rst;
|
||||||
|
logic init_addr_incr;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
if (reset || init_addr_rst)
|
||||||
|
init_addr <= '0;
|
||||||
|
else
|
||||||
|
if (init_addr_incr)
|
||||||
|
init_addr <= init_addr + 1'b1;
|
||||||
|
|
||||||
|
/* LCD chipselect */
|
||||||
|
logic spi_disable;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
if (reset || spi_disable)
|
||||||
|
lcd_spi_csn_o <= 1'b1;
|
||||||
|
else if (spi_push)
|
||||||
|
lcd_spi_csn_o <= 1'b0;
|
||||||
|
|
||||||
|
/* LCD data/command */
|
||||||
|
logic spi_do_cmd;
|
||||||
|
logic spi_do_data;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
// if (spi_do_cmd)
|
||||||
|
// lcd_spi_dcn_o <= 1'b0;
|
||||||
|
// else if (spi_do_data)
|
||||||
|
// lcd_spi_dcn_o <= 1'b1;
|
||||||
|
if (spi_do_cmd != spi_do_data)
|
||||||
|
lcd_spi_dcn_o <= spi_do_data;
|
||||||
|
|
||||||
|
/* Redraw block coordinates */
|
||||||
|
logic [GRID_XS_CW-1:0] bx;
|
||||||
|
logic [DISPLAY_XCW-1:0] borigx;
|
||||||
|
logic [DISPLAY_YCW-1:0] borigy;
|
||||||
|
logic [DISPLAY_XCW-1:0] borigx_e;
|
||||||
|
logic [DISPLAY_YCW-1:0] borigy_e;
|
||||||
|
|
||||||
|
assign borigx_e = borigx + BLOCK_XS - 1;
|
||||||
|
assign borigy_e = borigy + BLOCK_YS - 1;
|
||||||
|
|
||||||
|
logic [FBCW-1:0] fbr_orig;
|
||||||
|
|
||||||
|
logic reset_redraw;
|
||||||
|
logic next_block;
|
||||||
|
logic is_last_blk;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
if (reset_redraw) begin
|
||||||
|
dflag_int_addr <= '0;
|
||||||
|
bx <= '0;
|
||||||
|
borigx <= XORIG;
|
||||||
|
borigy <= YORIG;
|
||||||
|
fbr_orig <= '0;
|
||||||
|
is_last_blk <= 1'b0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if (next_block) begin
|
||||||
|
dflag_int_addr <= dflag_int_addr + 1'b1;
|
||||||
|
is_last_blk <= (dflag_int_addr == DFLAG_CW'(DFLAG_SIZE-1)) ? 1'b1 : 1'b0;
|
||||||
|
|
||||||
|
if (bx == GRID_XS_CW'(GRID_XS - 1))
|
||||||
|
begin
|
||||||
|
bx <= '0;
|
||||||
|
borigx <= XORIG;
|
||||||
|
borigy <= borigy + BLOCK_YS;
|
||||||
|
fbr_orig <= fbr_orig + BLOCK_XS + ((BLOCK_YS - 1) * XSIZE);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
bx <= bx + 1'b1;
|
||||||
|
borigx <= borigx + BLOCK_XS;
|
||||||
|
fbr_orig <= fbr_orig + BLOCK_XS;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
/* Framebuffer handling */
|
||||||
|
logic [BLOCK_XS_CW-1:0] px;
|
||||||
|
logic [BLOCK_CW-1:0] pi;
|
||||||
|
logic [15:0] pixel;
|
||||||
|
|
||||||
|
logic start_write;
|
||||||
|
logic read_pixel;
|
||||||
|
logic next_pixel;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
if (read_pixel)
|
||||||
|
pixel <= fb_rdata;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
if (start_write) begin
|
||||||
|
fba_int <= fbr_orig;
|
||||||
|
px <= '0;
|
||||||
|
pi <= '0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if (next_pixel) begin
|
||||||
|
pi <= pi + 1'b1;
|
||||||
|
|
||||||
|
if (px == BLOCK_XS_CW'(BLOCK_XS-1))
|
||||||
|
begin
|
||||||
|
fba_int <= fba_int + XSIZE - BLOCK_XS + 1'b1;
|
||||||
|
px <= '0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
fba_int <= fba_int + 1'b1;
|
||||||
|
px <= px + 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
/* Column/page addresses map */
|
||||||
|
logic [15:0] caddr_b, caddr_e;
|
||||||
|
logic [15:0] paddr_b, paddr_e;
|
||||||
|
|
||||||
|
assign caddr_b = { (16-DISPLAY_XCW)'('0), borigx };
|
||||||
|
assign caddr_e = { (16-DISPLAY_XCW)'('0), borigx_e };
|
||||||
|
assign paddr_b = { (16-DISPLAY_YCW)'('0), borigy };
|
||||||
|
assign paddr_e = { (16-DISPLAY_YCW)'('0), borigy_e };
|
||||||
|
|
||||||
|
/* Clear screen pixel counter */
|
||||||
|
logic [DISPLAY_MEM_CW-1:0] scrclr_pcntr;
|
||||||
|
logic scrclr_incr;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
if (reset || init_addr_rst)
|
||||||
|
scrclr_pcntr <= '0;
|
||||||
|
else
|
||||||
|
if (scrclr_incr)
|
||||||
|
scrclr_pcntr <= scrclr_pcntr + 1'b1;
|
||||||
|
|
||||||
|
/* FSM combinational block */
|
||||||
|
always @(*) begin
|
||||||
|
next = state;
|
||||||
|
|
||||||
|
/* FSM outputs default value */
|
||||||
|
delay_cntr_incr = 1'b0;
|
||||||
|
init_addr_rst = 1'b0;
|
||||||
|
init_addr_incr = 1'b0;
|
||||||
|
scrclr_incr = 1'b0;
|
||||||
|
spi_push = 1'b0;
|
||||||
|
spi_data = '0;
|
||||||
|
spi_disable = 1'b0;
|
||||||
|
spi_do_cmd = 1'b0;
|
||||||
|
spi_do_data = 1'b0;
|
||||||
|
reset_redraw = 1'b0;
|
||||||
|
dflag_clr = 1'b0;
|
||||||
|
next_block = 1'b0;
|
||||||
|
start_write = 1'b0;
|
||||||
|
next_pixel = 1'b0;
|
||||||
|
read_pixel = 1'b0;
|
||||||
|
fb_busy_int = 1'b0;
|
||||||
|
done_o = 1'b0;
|
||||||
|
|
||||||
|
case (state)
|
||||||
|
ST_PREINIT_DELAY: begin
|
||||||
|
delay_cntr_incr = 1'b1;
|
||||||
|
init_addr_rst = 1'b1;
|
||||||
|
|
||||||
|
if (delay_cntr == INIT_DELAY)
|
||||||
|
next = ST_INIT_PUSH_SPI;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_INIT_PUSH_SPI: begin
|
||||||
|
init_addr_incr = 1'b1;
|
||||||
|
spi_data = init_data[7:0];
|
||||||
|
spi_push = 1'b1;
|
||||||
|
|
||||||
|
{spi_do_cmd, spi_do_data}
|
||||||
|
= init_data[8] ? 2'b01 : 2'b10;
|
||||||
|
|
||||||
|
if (init_addr == (INIT_DATA_SIZE-1))
|
||||||
|
next = ST_INIT_WAIT_LAST;
|
||||||
|
else
|
||||||
|
next = ST_INIT_WAIT_SPI;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_INIT_WAIT_SPI:
|
||||||
|
if (spi_done)
|
||||||
|
next = ST_INIT_PUSH_SPI;
|
||||||
|
|
||||||
|
ST_INIT_WAIT_LAST:
|
||||||
|
if (spi_done)
|
||||||
|
next = ST_POSTINIT_DELAY;
|
||||||
|
|
||||||
|
ST_POSTINIT_DELAY: begin
|
||||||
|
spi_disable = 1'b1;
|
||||||
|
delay_cntr_incr = 1'b1;
|
||||||
|
|
||||||
|
if (delay_cntr == INIT_DELAY)
|
||||||
|
next = ST_DISPLAY_ON;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_DISPLAY_ON: begin
|
||||||
|
spi_data = 8'h29;
|
||||||
|
spi_do_cmd = 1'b1;
|
||||||
|
spi_push = 1'b1;
|
||||||
|
|
||||||
|
next = ST_DISPLAY_ONW;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_DISPLAY_ONW:
|
||||||
|
if (spi_done) begin
|
||||||
|
spi_disable = 1'b1;
|
||||||
|
next = ST_SCRCLR_CMD;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_SCRCLR_CMD: begin
|
||||||
|
spi_data = 8'h2c;
|
||||||
|
spi_do_cmd = 1'b1;
|
||||||
|
spi_push = 1'b1;
|
||||||
|
next = ST_SCRCLR;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_SCRCLR:
|
||||||
|
if (spi_done) begin
|
||||||
|
spi_data = 8'h00; //8'h32;
|
||||||
|
spi_do_data = 1'b1;
|
||||||
|
spi_push = 1'b1;
|
||||||
|
scrclr_incr = 1'b1;
|
||||||
|
|
||||||
|
if (scrclr_pcntr ==
|
||||||
|
`ifdef TESTBENCH
|
||||||
|
`ifdef VERILATOR
|
||||||
|
(DISPLAY_MEM_SIZE - 1)
|
||||||
|
`else
|
||||||
|
200
|
||||||
|
`endif
|
||||||
|
`else
|
||||||
|
(DISPLAY_MEM_SIZE - 1)
|
||||||
|
`endif
|
||||||
|
)
|
||||||
|
next = ST_SCRCLR_LAST;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_SCRCLR_LAST:
|
||||||
|
if (spi_done)
|
||||||
|
next = ST_START_REDRAW;
|
||||||
|
|
||||||
|
ST_START_REDRAW:
|
||||||
|
if (redraw_i) begin
|
||||||
|
spi_disable = 1'b1;
|
||||||
|
reset_redraw = 1'b1;
|
||||||
|
next = ST_READ_FLAG;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_READ_FLAG:
|
||||||
|
if (is_last_blk) begin
|
||||||
|
done_o = 1'b1;
|
||||||
|
next = ST_START_REDRAW;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
next = ST_CHECK_FLAG;
|
||||||
|
|
||||||
|
ST_CHECK_FLAG:
|
||||||
|
if (dflag_rdata == 1'b1)
|
||||||
|
next = ST_CLEAR_FLAG;
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
next_block = 1'b1;
|
||||||
|
next = ST_READ_FLAG;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_CLEAR_FLAG: begin
|
||||||
|
dflag_clr = 1'b1;
|
||||||
|
next = ST_CADDR_CMD;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_CADDR_CMD: begin
|
||||||
|
spi_data = 8'h2a;
|
||||||
|
spi_do_cmd = 1'b1;
|
||||||
|
spi_push = 1'b1;
|
||||||
|
|
||||||
|
next = ST_CADDR_0;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_CADDR_0:
|
||||||
|
if (spi_done) begin
|
||||||
|
spi_data = caddr_b[15:8];
|
||||||
|
spi_do_data = 1'b1;
|
||||||
|
spi_push = 1'b1;
|
||||||
|
|
||||||
|
next = ST_CADDR_1;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_CADDR_1:
|
||||||
|
if (spi_done) begin
|
||||||
|
spi_data = caddr_b[7:0];
|
||||||
|
spi_push = 1'b1;
|
||||||
|
|
||||||
|
next = ST_CADDR_2;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_CADDR_2:
|
||||||
|
if (spi_done) begin
|
||||||
|
spi_data = caddr_e[15:8];
|
||||||
|
spi_push = 1'b1;
|
||||||
|
|
||||||
|
next = ST_CADDR_3;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_CADDR_3:
|
||||||
|
if (spi_done) begin
|
||||||
|
spi_data = caddr_e[7:0];
|
||||||
|
spi_push = 1'b1;
|
||||||
|
|
||||||
|
next = ST_PADDR_CMD;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_PADDR_CMD:
|
||||||
|
if (spi_done) begin
|
||||||
|
spi_data = 8'h2b;
|
||||||
|
spi_do_cmd = 1'b1;
|
||||||
|
spi_push = 1'b1;
|
||||||
|
|
||||||
|
next = ST_PADDR_0;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_PADDR_0:
|
||||||
|
if (spi_done) begin
|
||||||
|
spi_data = paddr_b[15:8];
|
||||||
|
spi_do_data = 1'b1;
|
||||||
|
spi_push = 1'b1;
|
||||||
|
|
||||||
|
next = ST_PADDR_1;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_PADDR_1:
|
||||||
|
if (spi_done) begin
|
||||||
|
spi_data = paddr_b[7:0];
|
||||||
|
spi_push = 1'b1;
|
||||||
|
|
||||||
|
next = ST_PADDR_2;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_PADDR_2:
|
||||||
|
if (spi_done) begin
|
||||||
|
spi_data = paddr_e[15:8];
|
||||||
|
spi_push = 1'b1;
|
||||||
|
|
||||||
|
next = ST_PADDR_3;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_PADDR_3:
|
||||||
|
if (spi_done) begin
|
||||||
|
spi_data = paddr_e[7:0];
|
||||||
|
spi_push = 1'b1;
|
||||||
|
|
||||||
|
next = ST_WRITE_CMD;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_WRITE_CMD:
|
||||||
|
if (spi_done) begin
|
||||||
|
spi_data = 8'h2c;
|
||||||
|
spi_do_cmd = 1'b1;
|
||||||
|
spi_push = 1'b1;
|
||||||
|
start_write = 1'b1;
|
||||||
|
next = ST_WRITE_CMDW;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_WRITE_CMDW:
|
||||||
|
if (spi_done)
|
||||||
|
next = ST_FB_READ;
|
||||||
|
|
||||||
|
ST_FB_READ:
|
||||||
|
if (!fb_busy_ext) begin
|
||||||
|
fb_busy_int = 1'b1;
|
||||||
|
next = ST_STORE_PIXEL;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_STORE_PIXEL: begin
|
||||||
|
fb_busy_int = 1'b1;
|
||||||
|
read_pixel = 1'b1;
|
||||||
|
next = ST_WRITE_PIXEL_H;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_WRITE_PIXEL_H: begin
|
||||||
|
spi_data = pixel[15:8];
|
||||||
|
spi_do_data = 1'b1;
|
||||||
|
spi_push = 1'b1;
|
||||||
|
next = ST_WRITE_PIXEL_L;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_WRITE_PIXEL_L:
|
||||||
|
if (spi_done) begin
|
||||||
|
spi_data = pixel[7:0];
|
||||||
|
spi_push = 1'b1;
|
||||||
|
next = ST_NEXT_PIXEL;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_NEXT_PIXEL:
|
||||||
|
if (spi_done) begin
|
||||||
|
next_pixel = 1'b1;
|
||||||
|
|
||||||
|
if (pi == (BLOCK_SIZE - 1))
|
||||||
|
next = ST_NEXT_BLOCK;
|
||||||
|
else
|
||||||
|
next = ST_FB_READ;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_NEXT_BLOCK: begin
|
||||||
|
spi_disable = 1'b1;
|
||||||
|
next_block = 1'b1;
|
||||||
|
next = ST_READ_FLAG;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // lcd_top
|
||||||
37
source/lfsr.sv
Normal file
37
source/lfsr.sv
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
module lfsr #(parameter POLY = 32'hA3000000)
|
||||||
|
(clock,
|
||||||
|
preset,
|
||||||
|
data_i,
|
||||||
|
prnd_o);
|
||||||
|
|
||||||
|
localparam WIDTH = $size(POLY);
|
||||||
|
|
||||||
|
input wire clock;
|
||||||
|
input wire preset;
|
||||||
|
input wire [WIDTH-1:0] data_i;
|
||||||
|
output wire prnd_o;
|
||||||
|
|
||||||
|
logic [WIDTH-1:0] sreg;
|
||||||
|
logic feedback;
|
||||||
|
|
||||||
|
initial sreg = '1;
|
||||||
|
|
||||||
|
assign feedback = sreg[0];
|
||||||
|
assign prnd_o = feedback;
|
||||||
|
|
||||||
|
integer i;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
if (preset)
|
||||||
|
sreg <= (data_i == '0) ? '1 : data_i;
|
||||||
|
else begin
|
||||||
|
sreg[WIDTH-1] <= feedback;
|
||||||
|
|
||||||
|
for (i = 0; i < (WIDTH-1); i ++)
|
||||||
|
sreg[i] <= POLY[i] ? (sreg[i+1] ^ feedback) : sreg[i+1];
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // lfsr
|
||||||
133
source/mcp3201_ma.sv
Normal file
133
source/mcp3201_ma.sv
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
`default_nettype none
|
||||||
|
`include "assert.vh"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MCP3201 controller
|
||||||
|
* Multichannel and sample rate accurate version.
|
||||||
|
*/
|
||||||
|
module mcp3201_ma #(parameter CHANNELS = 1,
|
||||||
|
parameter CLOCK_FREQ = 12000000,
|
||||||
|
parameter SCLK_FREQ = 1000000,
|
||||||
|
parameter SAMPLE_RATE = 44100)
|
||||||
|
(input wire clock,
|
||||||
|
input wire reset,
|
||||||
|
|
||||||
|
output reg spi_clk_o,
|
||||||
|
output reg spi_ssn_o,
|
||||||
|
input wire [CHANNELS-1:0] spi_miso_i,
|
||||||
|
|
||||||
|
output reg [CHANNELS*12-1:0] data_o,
|
||||||
|
output reg strb_o);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
`assert(CHANNELS > 0);
|
||||||
|
end
|
||||||
|
|
||||||
|
/* SCLK frequency not need accuracy */
|
||||||
|
localparam SCLK_PERIOD = CLOCK_FREQ/SCLK_FREQ;
|
||||||
|
localparam SCLK_CW = $clog2(SCLK_PERIOD);
|
||||||
|
|
||||||
|
logic [SCLK_CW-1:0] sclk_cnt;
|
||||||
|
logic sclk_posedge;
|
||||||
|
|
||||||
|
/* Make SPI SCLK */
|
||||||
|
always_ff @(posedge clock)
|
||||||
|
if (reset | spi_ssn_o) begin
|
||||||
|
spi_clk_o <= 1'b1;
|
||||||
|
sclk_cnt <= '0;
|
||||||
|
sclk_posedge <= 1'b0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
sclk_posedge <= 1'b0;
|
||||||
|
sclk_cnt <= sclk_cnt + 1'b1;
|
||||||
|
|
||||||
|
if (sclk_cnt == SCLK_CW'(SCLK_PERIOD/2))
|
||||||
|
spi_clk_o <= 1'b0;
|
||||||
|
else
|
||||||
|
if (sclk_cnt == SCLK_CW'(SCLK_PERIOD-1)) begin
|
||||||
|
spi_clk_o <= 1'b1;
|
||||||
|
sclk_cnt <= '0;
|
||||||
|
sclk_posedge <= 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
/* Sample rate need more accuracy */
|
||||||
|
localparam SRATE_PERIOD = $rtoi($floor($itor(CLOCK_FREQ)/$itor(SAMPLE_RATE) + 0.5));
|
||||||
|
localparam SRATE_CW = $clog2(SRATE_PERIOD);
|
||||||
|
|
||||||
|
logic [SRATE_CW-1:0] srate_cnt;
|
||||||
|
logic sample;
|
||||||
|
|
||||||
|
always_ff @(posedge clock, posedge reset)
|
||||||
|
if (reset) begin
|
||||||
|
sample <= 1'b0;
|
||||||
|
srate_cnt <= '0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if (srate_cnt == SRATE_CW'(SRATE_PERIOD-1)) begin
|
||||||
|
sample <= 1'b1;
|
||||||
|
srate_cnt <= '0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
sample <= 1'b0;
|
||||||
|
srate_cnt <= srate_cnt + 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
/* Receive data FSM */
|
||||||
|
enum int unsigned {
|
||||||
|
ST_RELAX = 0,
|
||||||
|
ST_SHIFT,
|
||||||
|
ST_STROBE
|
||||||
|
} state;
|
||||||
|
|
||||||
|
logic [3:0] bit_cnt;
|
||||||
|
logic [11:0] data_sr[CHANNELS];
|
||||||
|
integer i;
|
||||||
|
|
||||||
|
always_ff @(posedge clock, posedge reset)
|
||||||
|
if (reset) begin
|
||||||
|
state <= ST_RELAX;
|
||||||
|
bit_cnt <= '0;
|
||||||
|
spi_ssn_o <= 1'b1;
|
||||||
|
strb_o <= 1'b0;
|
||||||
|
data_o <= '0;
|
||||||
|
|
||||||
|
for (i = 0; i < CHANNELS; i ++)
|
||||||
|
data_sr[i] <= '0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
strb_o <= 1'b0;
|
||||||
|
|
||||||
|
case (state)
|
||||||
|
ST_RELAX:
|
||||||
|
if (sample) begin
|
||||||
|
bit_cnt <= '0;
|
||||||
|
spi_ssn_o <= 1'b0;
|
||||||
|
state <= ST_SHIFT;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_SHIFT:
|
||||||
|
if (sclk_posedge) begin
|
||||||
|
for (i = 0; i < CHANNELS; i ++)
|
||||||
|
data_sr[i] <= { data_sr[i][10:0], spi_miso_i[i] };
|
||||||
|
|
||||||
|
bit_cnt <= bit_cnt + 1'b1;
|
||||||
|
|
||||||
|
if (bit_cnt == 4'd14) begin
|
||||||
|
spi_ssn_o <= 1'b1;
|
||||||
|
state <= ST_STROBE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_STROBE: begin
|
||||||
|
for (i = 0; i < CHANNELS; i ++)
|
||||||
|
data_o[i*12 +: 12] <= data_sr[i];
|
||||||
|
|
||||||
|
strb_o <= 1'b1;
|
||||||
|
state <= ST_RELAX;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // mcp3201_ma
|
||||||
77
source/pll.sv
Normal file
77
source/pll.sv
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PLL configuration 12MHz->30MHz
|
||||||
|
*
|
||||||
|
* F_PLLOUT: 30.000 MHz (requested)
|
||||||
|
* F_PLLOUT: 30.000 MHz (achieved)
|
||||||
|
*
|
||||||
|
* FEEDBACK: SIMPLE
|
||||||
|
* F_PFD: 12.000 MHz
|
||||||
|
* F_VCO: 960.000 MHz
|
||||||
|
*
|
||||||
|
* DIVR: 0 (4'b0000)
|
||||||
|
* DIVF: 79 (7'b1001111)
|
||||||
|
* DIVQ: 5 (3'b101)
|
||||||
|
*
|
||||||
|
* FILTER_RANGE: 1 (3'b001)
|
||||||
|
*/
|
||||||
|
|
||||||
|
`ifdef VERILATOR
|
||||||
|
`define TESTBENCH
|
||||||
|
`endif
|
||||||
|
|
||||||
|
module pll
|
||||||
|
(input clock_in,
|
||||||
|
output clock_out,
|
||||||
|
output locked);
|
||||||
|
|
||||||
|
wire unused_0, unused_1;
|
||||||
|
|
||||||
|
`ifdef TESTBENCH
|
||||||
|
`ifdef VERILATOR
|
||||||
|
/* In Verilator just forward clock_in to clock_out */
|
||||||
|
assign clock_out = clock_in;
|
||||||
|
assign locked = 1'b1;
|
||||||
|
|
||||||
|
`else // !VERILATOR
|
||||||
|
/* In Icarus Verilog generate new clock and 'locked' signal */
|
||||||
|
logic clock_tb;
|
||||||
|
logic lock_tb;
|
||||||
|
|
||||||
|
assign clock_out = clock_tb;
|
||||||
|
assign locked = lock_tb;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
clock_tb = 1'b0;
|
||||||
|
lock_tb = 1'b0;
|
||||||
|
repeat (100) @(posedge clock_tb);
|
||||||
|
lock_tb = 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
always #(33ns/2) clock_tb <= ~clock_tb;
|
||||||
|
`endif
|
||||||
|
`else
|
||||||
|
/* In HW use PLL primitive */
|
||||||
|
SB_PLL40_PAD #(.FEEDBACK_PATH("SIMPLE"),
|
||||||
|
.DIVR(4'd0),
|
||||||
|
/* For 30 MHz: DIVF=79, DIVQ=5
|
||||||
|
* For 50 MHz: DIVF=66, DIVQ=4 */
|
||||||
|
.DIVF(7'd79),
|
||||||
|
.DIVQ(3'd5),
|
||||||
|
.FILTER_RANGE(3'd1))
|
||||||
|
uut (.PACKAGEPIN (clock_in),
|
||||||
|
.PLLOUTGLOBAL (clock_out),
|
||||||
|
.EXTFEEDBACK (1'b0),
|
||||||
|
.DYNAMICDELAY (8'b0),
|
||||||
|
.LOCK (locked),
|
||||||
|
.BYPASS (1'b0),
|
||||||
|
.RESETB (1'b1),
|
||||||
|
.LATCHINPUTVALUE(1'b0),
|
||||||
|
.PLLOUTCORE (unused_0),
|
||||||
|
.SDO (unused_1),
|
||||||
|
.SDI (1'b0),
|
||||||
|
.SCLK (1'b0));
|
||||||
|
`endif
|
||||||
|
|
||||||
|
endmodule
|
||||||
24
source/pll_lock_reset.sv
Normal file
24
source/pll_lock_reset.sv
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
`default_nettype none
|
||||||
|
`include "assert.vh"
|
||||||
|
|
||||||
|
module pll_lock_reset #(parameter RESET_LEN = 8)
|
||||||
|
(input wire pll_clock,
|
||||||
|
input wire pll_lock,
|
||||||
|
output wire reset);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
`assert(RESET_LEN > 1);
|
||||||
|
end
|
||||||
|
|
||||||
|
logic [RESET_LEN:0] rst_sr;
|
||||||
|
|
||||||
|
initial rst_sr = '0;
|
||||||
|
|
||||||
|
always_ff @(posedge pll_clock, negedge pll_lock)
|
||||||
|
if (~pll_lock) rst_sr <= '0;
|
||||||
|
else rst_sr <= { 1'b1, rst_sr[RESET_LEN:1] };
|
||||||
|
|
||||||
|
assign reset = ~rst_sr[0];
|
||||||
|
|
||||||
|
endmodule // pll_lock_reset
|
||||||
256
source/quadrant_256.rom
Normal file
256
source/quadrant_256.rom
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
00ff
|
||||||
|
02ff
|
||||||
|
03ff
|
||||||
|
05ff
|
||||||
|
06ff
|
||||||
|
08ff
|
||||||
|
09ff
|
||||||
|
0bff
|
||||||
|
0dff
|
||||||
|
0eff
|
||||||
|
10ff
|
||||||
|
11fe
|
||||||
|
13fe
|
||||||
|
14fe
|
||||||
|
16fe
|
||||||
|
17fe
|
||||||
|
19fe
|
||||||
|
1bfe
|
||||||
|
1cfd
|
||||||
|
1efd
|
||||||
|
1ffd
|
||||||
|
21fd
|
||||||
|
22fd
|
||||||
|
24fc
|
||||||
|
25fc
|
||||||
|
27fc
|
||||||
|
29fc
|
||||||
|
2afc
|
||||||
|
2cfb
|
||||||
|
2dfb
|
||||||
|
2ffb
|
||||||
|
30fa
|
||||||
|
32fa
|
||||||
|
33fa
|
||||||
|
35f9
|
||||||
|
36f9
|
||||||
|
38f9
|
||||||
|
39f8
|
||||||
|
3bf8
|
||||||
|
3cf8
|
||||||
|
3ef7
|
||||||
|
3ff7
|
||||||
|
41f7
|
||||||
|
43f6
|
||||||
|
44f6
|
||||||
|
46f5
|
||||||
|
47f5
|
||||||
|
49f4
|
||||||
|
4af4
|
||||||
|
4cf4
|
||||||
|
4df3
|
||||||
|
4ff3
|
||||||
|
50f2
|
||||||
|
51f2
|
||||||
|
53f1
|
||||||
|
54f1
|
||||||
|
56f0
|
||||||
|
57f0
|
||||||
|
59ef
|
||||||
|
5aee
|
||||||
|
5cee
|
||||||
|
5ded
|
||||||
|
5fed
|
||||||
|
60ec
|
||||||
|
62ec
|
||||||
|
63eb
|
||||||
|
64ea
|
||||||
|
66ea
|
||||||
|
67e9
|
||||||
|
69e8
|
||||||
|
6ae8
|
||||||
|
6ce7
|
||||||
|
6de7
|
||||||
|
6ee6
|
||||||
|
70e5
|
||||||
|
71e4
|
||||||
|
73e4
|
||||||
|
74e3
|
||||||
|
75e2
|
||||||
|
77e2
|
||||||
|
78e1
|
||||||
|
7ae0
|
||||||
|
7bdf
|
||||||
|
7cdf
|
||||||
|
7ede
|
||||||
|
7fdd
|
||||||
|
80dc
|
||||||
|
82dc
|
||||||
|
83db
|
||||||
|
84da
|
||||||
|
86d9
|
||||||
|
87d8
|
||||||
|
88d7
|
||||||
|
8ad7
|
||||||
|
8bd6
|
||||||
|
8cd5
|
||||||
|
8ed4
|
||||||
|
8fd3
|
||||||
|
90d2
|
||||||
|
92d1
|
||||||
|
93d0
|
||||||
|
94d0
|
||||||
|
95cf
|
||||||
|
97ce
|
||||||
|
98cd
|
||||||
|
99cc
|
||||||
|
9acb
|
||||||
|
9cca
|
||||||
|
9dc9
|
||||||
|
9ec8
|
||||||
|
9fc7
|
||||||
|
a1c6
|
||||||
|
a2c5
|
||||||
|
a3c4
|
||||||
|
a4c3
|
||||||
|
a5c2
|
||||||
|
a7c1
|
||||||
|
a8c0
|
||||||
|
a9bf
|
||||||
|
aabe
|
||||||
|
abbd
|
||||||
|
acbc
|
||||||
|
aebb
|
||||||
|
afba
|
||||||
|
b0b9
|
||||||
|
b1b8
|
||||||
|
b2b7
|
||||||
|
b3b5
|
||||||
|
b4b4
|
||||||
|
b5b3
|
||||||
|
b7b2
|
||||||
|
b8b1
|
||||||
|
b9b0
|
||||||
|
baaf
|
||||||
|
bbae
|
||||||
|
bcac
|
||||||
|
bdab
|
||||||
|
beaa
|
||||||
|
bfa9
|
||||||
|
c0a8
|
||||||
|
c1a7
|
||||||
|
c2a5
|
||||||
|
c3a4
|
||||||
|
c4a3
|
||||||
|
c5a2
|
||||||
|
c6a1
|
||||||
|
c79f
|
||||||
|
c89e
|
||||||
|
c99d
|
||||||
|
ca9c
|
||||||
|
cb9a
|
||||||
|
cc99
|
||||||
|
cd98
|
||||||
|
ce97
|
||||||
|
cf95
|
||||||
|
d094
|
||||||
|
d093
|
||||||
|
d192
|
||||||
|
d290
|
||||||
|
d38f
|
||||||
|
d48e
|
||||||
|
d58c
|
||||||
|
d68b
|
||||||
|
d78a
|
||||||
|
d788
|
||||||
|
d887
|
||||||
|
d986
|
||||||
|
da84
|
||||||
|
db83
|
||||||
|
dc82
|
||||||
|
dc80
|
||||||
|
dd7f
|
||||||
|
de7e
|
||||||
|
df7c
|
||||||
|
df7b
|
||||||
|
e07a
|
||||||
|
e178
|
||||||
|
e277
|
||||||
|
e275
|
||||||
|
e374
|
||||||
|
e473
|
||||||
|
e471
|
||||||
|
e570
|
||||||
|
e66e
|
||||||
|
e76d
|
||||||
|
e76c
|
||||||
|
e86a
|
||||||
|
e869
|
||||||
|
e967
|
||||||
|
ea66
|
||||||
|
ea64
|
||||||
|
eb63
|
||||||
|
ec62
|
||||||
|
ec60
|
||||||
|
ed5f
|
||||||
|
ed5d
|
||||||
|
ee5c
|
||||||
|
ee5a
|
||||||
|
ef59
|
||||||
|
f057
|
||||||
|
f056
|
||||||
|
f154
|
||||||
|
f153
|
||||||
|
f251
|
||||||
|
f250
|
||||||
|
f34f
|
||||||
|
f34d
|
||||||
|
f44c
|
||||||
|
f44a
|
||||||
|
f449
|
||||||
|
f547
|
||||||
|
f546
|
||||||
|
f644
|
||||||
|
f643
|
||||||
|
f741
|
||||||
|
f73f
|
||||||
|
f73e
|
||||||
|
f83c
|
||||||
|
f83b
|
||||||
|
f839
|
||||||
|
f938
|
||||||
|
f936
|
||||||
|
f935
|
||||||
|
fa33
|
||||||
|
fa32
|
||||||
|
fa30
|
||||||
|
fb2f
|
||||||
|
fb2d
|
||||||
|
fb2c
|
||||||
|
fc2a
|
||||||
|
fc29
|
||||||
|
fc27
|
||||||
|
fc25
|
||||||
|
fc24
|
||||||
|
fd22
|
||||||
|
fd21
|
||||||
|
fd1f
|
||||||
|
fd1e
|
||||||
|
fd1c
|
||||||
|
fe1b
|
||||||
|
fe19
|
||||||
|
fe17
|
||||||
|
fe16
|
||||||
|
fe14
|
||||||
|
fe13
|
||||||
|
fe11
|
||||||
|
ff10
|
||||||
|
ff0e
|
||||||
|
ff0d
|
||||||
|
ff0b
|
||||||
|
ff09
|
||||||
|
ff08
|
||||||
|
ff06
|
||||||
|
ff05
|
||||||
|
ff03
|
||||||
|
ff02
|
||||||
323
source/sugar_lissajous.sv
Normal file
323
source/sugar_lissajous.sv
Normal file
@ -0,0 +1,323 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
/* verilator lint_off UNDRIVEN */
|
||||||
|
/* verilator lint_off UNUSED */
|
||||||
|
|
||||||
|
`define VARIANT_1
|
||||||
|
//`define VARIANT_2
|
||||||
|
|
||||||
|
module sugar_lissajous
|
||||||
|
(input wire CLK12,
|
||||||
|
|
||||||
|
output wire LED_R_N,
|
||||||
|
output wire LED_G_N,
|
||||||
|
output wire LED_B_N,
|
||||||
|
|
||||||
|
// PMOD 1: two ADC MCP3201
|
||||||
|
output wire P1_1, // R SSN
|
||||||
|
input wire P1_2, // --
|
||||||
|
input wire P1_3, // R DAT
|
||||||
|
output wire P1_4, // R CLK
|
||||||
|
output wire P1_9, // L CLK
|
||||||
|
input wire P1_10, // L DAT
|
||||||
|
input wire P1_11, // --
|
||||||
|
output wire P1_12, // L SSN
|
||||||
|
|
||||||
|
// PMOD 2: LCD
|
||||||
|
input wire P2_1, //
|
||||||
|
input wire P2_2, //
|
||||||
|
output wire P2_3, // DC
|
||||||
|
input wire P2_4, //
|
||||||
|
output wire P2_9, // CLK
|
||||||
|
input wire P2_10, //
|
||||||
|
output wire P2_11, // MOSI
|
||||||
|
output wire P2_12 // CSN
|
||||||
|
);
|
||||||
|
|
||||||
|
`ifdef VARIANT_1
|
||||||
|
localparam POINTS_COUNT = 128;
|
||||||
|
localparam POINTS_FADING = 1;
|
||||||
|
localparam DECIMATION = 200;
|
||||||
|
localparam ANGLE_INCREMENT = 8;
|
||||||
|
`elsif VARIANT_2
|
||||||
|
localparam POINTS_COUNT = 32;
|
||||||
|
localparam POINTS_FADING = 0;
|
||||||
|
localparam DECIMATION = 50;
|
||||||
|
localparam ANGLE_INCREMENT = 30;
|
||||||
|
`endif
|
||||||
|
|
||||||
|
assign LED_R_N = 1'b1;
|
||||||
|
assign LED_G_N = 1'b1;
|
||||||
|
assign LED_B_N = 1'b1;
|
||||||
|
|
||||||
|
logic clock;
|
||||||
|
logic reset;
|
||||||
|
logic pll_lock;
|
||||||
|
|
||||||
|
pll pll_i
|
||||||
|
(.clock_in(CLK12),
|
||||||
|
.clock_out(clock),
|
||||||
|
.locked(pll_lock));
|
||||||
|
|
||||||
|
pll_lock_reset #(.RESET_LEN(8)) reset_i
|
||||||
|
(.pll_clock(clock),
|
||||||
|
.pll_lock(pll_lock),
|
||||||
|
.reset(reset));
|
||||||
|
|
||||||
|
localparam SPI_SCLK_FREQ = 1000000;
|
||||||
|
localparam SAMPLE_RATE = 20000;
|
||||||
|
|
||||||
|
logic [11:0] rdata;
|
||||||
|
logic [11:0] ldata;
|
||||||
|
logic strb;
|
||||||
|
|
||||||
|
logic adc_ssn, adc_clk;
|
||||||
|
logic radc_dat, ladc_dat;
|
||||||
|
|
||||||
|
assign P1_1 = adc_ssn;
|
||||||
|
assign P1_4 = adc_clk;
|
||||||
|
assign P1_12 = adc_ssn;
|
||||||
|
assign P1_9 = adc_clk;
|
||||||
|
|
||||||
|
assign radc_dat = P1_3;
|
||||||
|
assign ladc_dat = P1_10;
|
||||||
|
|
||||||
|
/* Grab audio */
|
||||||
|
mcp3201_ma #(.CHANNELS(2),
|
||||||
|
.CLOCK_FREQ(30000000),
|
||||||
|
.SCLK_FREQ(SPI_SCLK_FREQ),
|
||||||
|
.SAMPLE_RATE(SAMPLE_RATE)) adcs_i
|
||||||
|
(.clock, .reset,
|
||||||
|
.spi_clk_o(adc_clk),
|
||||||
|
.spi_ssn_o(adc_ssn),
|
||||||
|
.spi_miso_i({ radc_dat, ladc_dat }),
|
||||||
|
.data_o({ rdata, ldata }),
|
||||||
|
.strb_o(strb));
|
||||||
|
|
||||||
|
/* Filter audio stream */
|
||||||
|
logic [15:0] fir_i;
|
||||||
|
logic [15:0] fir_o;
|
||||||
|
logic fir_i_ready;
|
||||||
|
logic fir_o_valid;
|
||||||
|
|
||||||
|
logic [15:0] fir_abs;
|
||||||
|
logic fir_strb;
|
||||||
|
|
||||||
|
`ifdef TESTBENCH
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
if (strb) begin
|
||||||
|
fir_abs <= 1024/2;
|
||||||
|
fir_strb <= 1'b1;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
fir_strb <= 1'b0;
|
||||||
|
|
||||||
|
`else // !TESTBENCH
|
||||||
|
|
||||||
|
fir_filter fir_impl
|
||||||
|
(.clock, .reset,
|
||||||
|
.data_i(fir_i),
|
||||||
|
.data_o(fir_o),
|
||||||
|
.ready_i(fir_i_ready),
|
||||||
|
.valid_o(fir_o_valid));
|
||||||
|
|
||||||
|
always_ff @ (posedge clock, posedge reset)
|
||||||
|
if (reset)
|
||||||
|
fir_i_ready <= 1'b0;
|
||||||
|
else
|
||||||
|
if (~fir_i_ready) begin
|
||||||
|
fir_strb <= 1'b0;
|
||||||
|
|
||||||
|
if (strb) begin
|
||||||
|
fir_i <= (ldata >= 1024) ? 16'(ldata) - 16'd1024 : 16'd64512 - 16'(ldata);
|
||||||
|
fir_i_ready <= 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if (fir_o_valid) begin
|
||||||
|
fir_abs <= fir_o[15] ? 16'hffff - fir_o + 1'b1 : fir_o;
|
||||||
|
fir_i_ready <= 1'b0;
|
||||||
|
fir_strb <= 1'b1;
|
||||||
|
end
|
||||||
|
`endif
|
||||||
|
|
||||||
|
/* Make frame redraw tick */
|
||||||
|
logic tick_redraw;
|
||||||
|
tick_generator #(.PERIOD(600000))
|
||||||
|
tick_refresh_gen (.clock, .reset, .tick_o(tick_redraw));
|
||||||
|
|
||||||
|
logic redraw;
|
||||||
|
logic redraw_done;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
if (redraw_done)
|
||||||
|
redraw <= 1'b0;
|
||||||
|
else
|
||||||
|
if (tick_redraw)
|
||||||
|
redraw <= 1'b1;
|
||||||
|
|
||||||
|
/* LCD connection */
|
||||||
|
logic spi_csn, spi_clk, spi_sdo, dcn;
|
||||||
|
assign P2_12 = spi_csn;
|
||||||
|
assign P2_9 = spi_clk;
|
||||||
|
assign P2_11 = spi_sdo;
|
||||||
|
assign P2_3 = dcn;
|
||||||
|
|
||||||
|
logic [7:0] lcd_x;
|
||||||
|
logic [8:0] lcd_y;
|
||||||
|
logic lcd_req;
|
||||||
|
logic lcd_ack;
|
||||||
|
logic lcd_wr;
|
||||||
|
|
||||||
|
logic [15:0] color_w;
|
||||||
|
logic [15:0] color_r;
|
||||||
|
|
||||||
|
lcd_top #(.SPI_CLK_PERIOD(4)) lcd_i
|
||||||
|
(.clock, .reset,
|
||||||
|
.lcd_spi_csn_o(spi_csn),
|
||||||
|
.lcd_spi_clk_o(spi_clk),
|
||||||
|
.lcd_spi_dat_o(spi_sdo),
|
||||||
|
.lcd_spi_dcn_o(dcn),
|
||||||
|
.redraw_i(redraw),
|
||||||
|
.done_o(redraw_done),
|
||||||
|
.x_i(lcd_x),
|
||||||
|
.y_i(lcd_y),
|
||||||
|
.color_i(color_w),
|
||||||
|
.color_o(color_r),
|
||||||
|
.req_i(lcd_req),
|
||||||
|
.ack_o(lcd_ack),
|
||||||
|
.wr_i(lcd_wr));
|
||||||
|
|
||||||
|
/* Figure drawer */
|
||||||
|
logic [7:0] fig_x;
|
||||||
|
logic [8:0] fig_y;
|
||||||
|
logic [7:0] fig_h;
|
||||||
|
logic [7:0] fig_s;
|
||||||
|
logic [7:0] fig_v;
|
||||||
|
logic fig_req;
|
||||||
|
logic fig_ack;
|
||||||
|
|
||||||
|
assign lcd_wr = 1'b1;
|
||||||
|
|
||||||
|
fig_drawer fig_i
|
||||||
|
(.clock, .reset,
|
||||||
|
.x_i(fig_x),
|
||||||
|
.y_i(fig_y),
|
||||||
|
.h_i(fig_h),
|
||||||
|
.s_i(fig_s),
|
||||||
|
.v_i(fig_v),
|
||||||
|
.req_i(fig_req),
|
||||||
|
.ack_o(fig_ack),
|
||||||
|
|
||||||
|
.fb_x_o(lcd_x),
|
||||||
|
.fb_y_o(lcd_y),
|
||||||
|
.fb_color_o(color_w),
|
||||||
|
.fb_req_o(lcd_req),
|
||||||
|
.fb_ack_i(lcd_ack));
|
||||||
|
|
||||||
|
/* Awesome circle */
|
||||||
|
logic [9:0] cir_angle;
|
||||||
|
logic [7:0] cir_x;
|
||||||
|
logic [7:0] cir_y;
|
||||||
|
logic cir_req;
|
||||||
|
logic cir_ack;
|
||||||
|
|
||||||
|
circle_1024 DUT
|
||||||
|
(.clock, .reset,
|
||||||
|
.angle(cir_angle),
|
||||||
|
.r(fir_abs[11:4]),
|
||||||
|
.x0(8'd120),
|
||||||
|
.y0(8'd128),
|
||||||
|
.x(cir_x),
|
||||||
|
.y(cir_y),
|
||||||
|
.req_i(cir_req),
|
||||||
|
.ack_o(cir_ack));
|
||||||
|
|
||||||
|
/* Points ring buffer */
|
||||||
|
logic [7:0] pt_x;
|
||||||
|
logic [7:0] pt_y;
|
||||||
|
logic [7:0] pt_h;
|
||||||
|
logic pt_req;
|
||||||
|
logic pt_ack;
|
||||||
|
|
||||||
|
fig_ring #(.POINT_COUNT(POINTS_COUNT),
|
||||||
|
.FADING(POINTS_FADING)) fig_ring_i
|
||||||
|
(.clock, .reset,
|
||||||
|
.pt_x(pt_x),
|
||||||
|
.pt_y(pt_y),
|
||||||
|
.pt_h(pt_h),
|
||||||
|
.pt_req_i(pt_req),
|
||||||
|
.pt_ack_o(pt_ack),
|
||||||
|
|
||||||
|
.fig_x_o(fig_x),
|
||||||
|
.fig_y_o(fig_y),
|
||||||
|
.fig_h_o(fig_h),
|
||||||
|
.fig_s_o(fig_s),
|
||||||
|
.fig_v_o(fig_v),
|
||||||
|
.fig_req_o(fig_req),
|
||||||
|
.fig_ack_i(fig_ack));
|
||||||
|
|
||||||
|
/* Decimate audio stream */
|
||||||
|
localparam DECIMATION_CW = $clog2(DECIMATION);
|
||||||
|
|
||||||
|
logic [DECIMATION_CW-1:0] decim_cntr;
|
||||||
|
logic decim_strobe;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock, posedge reset)
|
||||||
|
if (reset)
|
||||||
|
decim_cntr <= '0;
|
||||||
|
else
|
||||||
|
if (decim_cntr == (DECIMATION-1)) begin
|
||||||
|
decim_cntr <= '0;
|
||||||
|
decim_strobe <= 1'b1;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
decim_strobe <= 1'b0;
|
||||||
|
|
||||||
|
if (fir_strb)
|
||||||
|
decim_cntr <= decim_cntr + 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
/* Draw autio sample on circle */
|
||||||
|
enum int unsigned {
|
||||||
|
ST_FIG_IDLE = 0,
|
||||||
|
ST_FIG_CIRCLE,
|
||||||
|
ST_FIG_DRAW
|
||||||
|
} state_fig;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock, posedge reset)
|
||||||
|
if (reset) begin
|
||||||
|
state_fig <= ST_FIG_IDLE;
|
||||||
|
cir_req <= 1'b0;
|
||||||
|
pt_req <= 1'b0;
|
||||||
|
cir_angle <= '0;
|
||||||
|
pt_h <= '0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
case (state_fig)
|
||||||
|
ST_FIG_IDLE:
|
||||||
|
if (decim_strobe) begin
|
||||||
|
cir_req <= 1'b1;
|
||||||
|
state_fig <= ST_FIG_CIRCLE;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_FIG_CIRCLE:
|
||||||
|
if (cir_ack) begin
|
||||||
|
cir_req <= 1'b0;
|
||||||
|
pt_x <= cir_x;
|
||||||
|
pt_y <= cir_y;
|
||||||
|
pt_req <= 1'b1;
|
||||||
|
state_fig <= ST_FIG_DRAW;
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_FIG_DRAW:
|
||||||
|
if (pt_ack) begin
|
||||||
|
pt_req <= 1'b0;
|
||||||
|
cir_angle <= cir_angle + ANGLE_INCREMENT;
|
||||||
|
pt_h <= pt_h + 1'b1;
|
||||||
|
state_fig <= ST_FIG_IDLE;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
endmodule // sugar_lissajous
|
||||||
33
source/tick_generator.sv
Normal file
33
source/tick_generator.sv
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
`default_nettype none
|
||||||
|
`include "assert.vh"
|
||||||
|
|
||||||
|
module tick_generator #(parameter PERIOD = 1000)
|
||||||
|
(input wire clock,
|
||||||
|
input wire reset,
|
||||||
|
output reg tick_o);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
`assert(PERIOD > 1);
|
||||||
|
end
|
||||||
|
|
||||||
|
localparam TICK_CW = $clog2(PERIOD);
|
||||||
|
logic [TICK_CW-1:0] cntr;
|
||||||
|
|
||||||
|
always_ff @(posedge clock, posedge reset)
|
||||||
|
if (reset) begin
|
||||||
|
cntr <= '0;
|
||||||
|
tick_o <= 1'b0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
if (cntr == (PERIOD-1)) begin
|
||||||
|
cntr <= '0;
|
||||||
|
tick_o <= 1'b1;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
cntr <= cntr + 1'b1;
|
||||||
|
tick_o <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // tick_generator
|
||||||
5
testbench/.dir-locals.el
Normal file
5
testbench/.dir-locals.el
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
;;; Directory Local Variables
|
||||||
|
;;; For more information see (info "(emacs) Directory Variables")
|
||||||
|
|
||||||
|
((verilog-mode . ((flycheck-verilator-include-path . ("." "../source"))
|
||||||
|
(verilog-library-directories . ("." "../source")))))
|
||||||
5
testbench/.gitignore
vendored
Normal file
5
testbench/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
*.out
|
||||||
|
*.bin
|
||||||
|
*.vcd
|
||||||
|
*.gtkw
|
||||||
|
filtered.txt
|
||||||
31
testbench/Makefile
Normal file
31
testbench/Makefile
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
VC = iverilog
|
||||||
|
VI = vvp
|
||||||
|
|
||||||
|
#SOURCES = ../source/lcd_320x240_spi.sv
|
||||||
|
SOURCES = $(wildcard ../source/*.sv)
|
||||||
|
SOURCES += ../../local/share/yosys/ice40/cells_sim.v
|
||||||
|
|
||||||
|
VFLAGS = -g2012 -I../source
|
||||||
|
TBS = $(wildcard tb_*.sv)
|
||||||
|
DEFINES = -D TESTBENCH
|
||||||
|
VCDDEPS = $(TBS:.sv=.vcd)
|
||||||
|
BINDEPS = $(TBS:.sv=.bin)
|
||||||
|
|
||||||
|
all: $(VCDDEPS)
|
||||||
|
|
||||||
|
.SECONDARY:
|
||||||
|
#.SILENT: $(VCDDEPS) $(BINDEPS) clean
|
||||||
|
|
||||||
|
%.vcd: %.bin
|
||||||
|
@echo "Simulate :" $(<:.bin=.sv)
|
||||||
|
$(VI) $< #> $(<:.bin=.out)
|
||||||
|
|
||||||
|
%.bin: %.sv $(SOURCES)
|
||||||
|
@echo "Compile :" $(@:.bin=.sv)
|
||||||
|
$(VC) $(VFLAGS) $(DEFINES) -D DUMPFILE=\"$(@:.bin=.vcd)\" -o $@ $< $(SOURCES)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo "Remove *.bin, *.vcd, *.out"
|
||||||
|
rm -rf *.bin
|
||||||
|
rm -rf *.out
|
||||||
|
rm -rf *.vcd
|
||||||
1
testbench/fig_circle_8x8.rom
Symbolic link
1
testbench/fig_circle_8x8.rom
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../source/fig_circle_8x8.rom
|
||||||
9
testbench/fir-magn.m
Normal file
9
testbench/fir-magn.m
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
pkg load signal
|
||||||
|
|
||||||
|
data = csvread("filtered.txt");
|
||||||
|
data = data(8:length(data));
|
||||||
|
spec = abs(fft(data ./ 32768));
|
||||||
|
len = length(data);
|
||||||
|
x = 1:len/2;
|
||||||
|
|
||||||
|
plot(x ./ len, mag2db(spec(1:len/2)));
|
||||||
1
testbench/fir_425_50hz_100hz_0db_40db.rom
Symbolic link
1
testbench/fir_425_50hz_100hz_0db_40db.rom
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../source/fir_425_50hz_100hz_0db_40db.rom
|
||||||
2
testbench/lcd-model/.clang_complete
Normal file
2
testbench/lcd-model/.clang_complete
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
-I./obj_dir
|
||||||
|
-I/usr/share/verilator/include
|
||||||
5
testbench/lcd-model/.dir-locals.el
Normal file
5
testbench/lcd-model/.dir-locals.el
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
;;; Directory Local Variables
|
||||||
|
;;; For more information see (info "(emacs) Directory Variables")
|
||||||
|
|
||||||
|
((verilog-mode . ((flycheck-verilator-include-path . ("." "../../source"))
|
||||||
|
(verilog-library-directories . ("." "../../source")))))
|
||||||
2
testbench/lcd-model/.gitignore
vendored
Normal file
2
testbench/lcd-model/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
obj_dir
|
||||||
|
*.vcd
|
||||||
31
testbench/lcd-model/Makefile
Normal file
31
testbench/lcd-model/Makefile
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
SOURCE_DIR = ../../source
|
||||||
|
|
||||||
|
SOURCES = testbench_top.cpp \
|
||||||
|
testbench_top.sv \
|
||||||
|
lcd_ili9341_4spi.sv \
|
||||||
|
$(SOURCE_DIR)/sugar_lissajous.sv \
|
||||||
|
$(SOURCE_DIR)/pll_lock_reset.sv \
|
||||||
|
$(SOURCE_DIR)/pll.sv \
|
||||||
|
$(SOURCE_DIR)/mcp3201_ma.sv \
|
||||||
|
$(SOURCE_DIR)/lfsr.sv \
|
||||||
|
$(SOURCE_DIR)/lcd_top.sv \
|
||||||
|
$(SOURCE_DIR)/lcd_spi.sv \
|
||||||
|
$(SOURCE_DIR)/ice40_spram.sv \
|
||||||
|
$(SOURCE_DIR)/ice40_mac16x16.sv
|
||||||
|
|
||||||
|
SOURCES += ../../../local/share/yosys/ice40/cells_sim.v
|
||||||
|
|
||||||
|
TOP_MODULE = testbench_top
|
||||||
|
|
||||||
|
FLAGS = -DTESTBENCH -Wno-WIDTH -cc -I$(SOURCE_DIR) --top-module $(TOP_MODULE) +1800-2017ext+sv -I$(SOURCE_DIR)
|
||||||
|
#FLAGS += --threads 8
|
||||||
|
FLAGS += --trace
|
||||||
|
|
||||||
|
all: $(SOURCES)
|
||||||
|
verilator $(FLAGS) --exe --build -o $(TOP_MODULE) $(SOURCES)
|
||||||
|
|
||||||
|
pre:
|
||||||
|
verilator $(FLAGS) -o $(TOP_MODULE) $(SOURCES)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf obj_dir
|
||||||
1
testbench/lcd-model/fig_circle_8x8.rom
Symbolic link
1
testbench/lcd-model/fig_circle_8x8.rom
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../source/fig_circle_8x8.rom
|
||||||
80
testbench/lcd-model/frontend.rkt
Executable file
80
testbench/lcd-model/frontend.rkt
Executable file
@ -0,0 +1,80 @@
|
|||||||
|
#! /usr/bin/env racket
|
||||||
|
#lang racket/gui
|
||||||
|
|
||||||
|
(require racket/gui/base)
|
||||||
|
|
||||||
|
(define display-width 240)
|
||||||
|
(define display-height 320)
|
||||||
|
(define fb-size (* display-width display-height))
|
||||||
|
|
||||||
|
(define (set-pixel! fb x y r g b)
|
||||||
|
(let ((i (* 4 (+ x (* y display-width)))))
|
||||||
|
(bytes-set! fb (+ i 0) 255)
|
||||||
|
(bytes-set! fb (+ i 1) r)
|
||||||
|
(bytes-set! fb (+ i 2) g)
|
||||||
|
(bytes-set! fb (+ i 3) b)))
|
||||||
|
|
||||||
|
(define (clear-screen fb r g b)
|
||||||
|
(for-each
|
||||||
|
(lambda (n)
|
||||||
|
(let ((n (* n 4)))
|
||||||
|
(bytes-set! fb (+ n 0) 255)
|
||||||
|
(bytes-set! fb (+ n 1) r)
|
||||||
|
(bytes-set! fb (+ n 2) g)
|
||||||
|
(bytes-set! fb (+ n 3) b)))
|
||||||
|
(range fb-size)))
|
||||||
|
|
||||||
|
;;; MAIN
|
||||||
|
(let* ((frame-buffer (make-bytes (* fb-size 4)))
|
||||||
|
(frame-bitmap (make-bitmap display-width display-height))
|
||||||
|
|
||||||
|
(frame (new frame%
|
||||||
|
(label "LCD")
|
||||||
|
(min-width display-width)
|
||||||
|
(min-height display-height)
|
||||||
|
(stretchable-width #f)
|
||||||
|
(stretchable-height #f)))
|
||||||
|
|
||||||
|
(canvas (new canvas% (parent frame)
|
||||||
|
(paint-callback
|
||||||
|
(lambda (canvas dc)
|
||||||
|
(send frame-bitmap
|
||||||
|
set-argb-pixels 0 0
|
||||||
|
display-width display-height
|
||||||
|
frame-buffer)
|
||||||
|
(send dc draw-bitmap frame-bitmap 0 0)))))
|
||||||
|
|
||||||
|
(cmdl (current-command-line-arguments))
|
||||||
|
(pipe (if (zero? (vector-length cmdl)) #f (vector-ref cmdl 0))))
|
||||||
|
|
||||||
|
|
||||||
|
(clear-screen frame-buffer 50 100 150)
|
||||||
|
(send frame show #t)
|
||||||
|
|
||||||
|
;; Read pixels data
|
||||||
|
(thread (λ ()
|
||||||
|
(let ((thunk
|
||||||
|
(lambda ()
|
||||||
|
(let loop ()
|
||||||
|
(let ((s (read-line)))
|
||||||
|
(if (eof-object? s)
|
||||||
|
(loop) ;; (send frame show #f)
|
||||||
|
(let ((l (string-split s)))
|
||||||
|
(when (= 5 (length l))
|
||||||
|
(let* ((x (string->number (list-ref l 0)))
|
||||||
|
(y (string->number (list-ref l 1)))
|
||||||
|
(r (string->number (list-ref l 2)))
|
||||||
|
(g (string->number (list-ref l 3)))
|
||||||
|
(b (string->number (list-ref l 4))))
|
||||||
|
(set-pixel! frame-buffer x y r g b)))
|
||||||
|
(loop))))))))
|
||||||
|
(if pipe
|
||||||
|
(with-input-from-file "lcd_pipe" thunk)
|
||||||
|
(thunk)))))
|
||||||
|
|
||||||
|
;; Refresh screen
|
||||||
|
(thread (lambda ()
|
||||||
|
(let loop ()
|
||||||
|
(send canvas refresh)
|
||||||
|
(sleep 0.02)
|
||||||
|
(loop)))))
|
||||||
156
testbench/lcd-model/lcd_ili9341_4spi.sv
Normal file
156
testbench/lcd-model/lcd_ili9341_4spi.sv
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
module lcd_ili9341_4spi
|
||||||
|
(input wire clock,
|
||||||
|
input wire reset,
|
||||||
|
|
||||||
|
input wire csn_i,
|
||||||
|
input wire clk_i,
|
||||||
|
input wire sdi_i,
|
||||||
|
input wire dcn_i,
|
||||||
|
|
||||||
|
output int x_o,
|
||||||
|
output int y_o,
|
||||||
|
output logic [7:0] r_o,
|
||||||
|
output logic [7:0] g_o,
|
||||||
|
output logic [7:0] b_o,
|
||||||
|
output logic strobe_o);
|
||||||
|
|
||||||
|
logic [7:0] readed;
|
||||||
|
logic [7:0] spi_sr;
|
||||||
|
int bit_cntr;
|
||||||
|
logic clk_prev;
|
||||||
|
logic rstrobe;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock) clk_prev <= clk_i;
|
||||||
|
|
||||||
|
always_ff @(posedge clock, posedge csn_i)
|
||||||
|
if (csn_i || reset) begin
|
||||||
|
bit_cntr <= 0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
if (clk_prev == 1'b0 &&
|
||||||
|
clk_i == 1'b1)
|
||||||
|
begin
|
||||||
|
spi_sr <= { spi_sr[6:0], sdi_i };
|
||||||
|
bit_cntr <= bit_cntr + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (bit_cntr == 8) begin
|
||||||
|
readed <= spi_sr;
|
||||||
|
rstrobe <= 1'b1;
|
||||||
|
bit_cntr <= 0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
rstrobe <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
enum int unsigned {
|
||||||
|
ST_IDLE = 0,
|
||||||
|
ST_CADDR,
|
||||||
|
ST_PADDR,
|
||||||
|
ST_MEM_WRITE
|
||||||
|
} state;
|
||||||
|
|
||||||
|
logic [15:0] x_beg;
|
||||||
|
logic [15:0] x_end;
|
||||||
|
logic [15:0] y_beg;
|
||||||
|
logic [15:0] y_end;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
x_beg = 0;
|
||||||
|
x_end = 239;
|
||||||
|
y_beg = 0;
|
||||||
|
y_end = 319;
|
||||||
|
end
|
||||||
|
|
||||||
|
int n;
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
logic [7:0] tmp;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock, posedge csn_i)
|
||||||
|
if (csn_i || reset) begin
|
||||||
|
state <= ST_IDLE;
|
||||||
|
n <= 0;
|
||||||
|
strobe_o <= 1'b0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
strobe_o <= 1'b0;
|
||||||
|
|
||||||
|
if (rstrobe) begin
|
||||||
|
if (~dcn_i) begin
|
||||||
|
case (readed)
|
||||||
|
8'h2a: state <= ST_CADDR;
|
||||||
|
8'h2b: state <= ST_PADDR;
|
||||||
|
8'h2c: begin
|
||||||
|
x <= int'(x_beg);
|
||||||
|
y <= int'(y_beg);
|
||||||
|
state <= ST_MEM_WRITE;
|
||||||
|
end
|
||||||
|
default: begin end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
n <= 0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
case (state)
|
||||||
|
ST_CADDR: begin
|
||||||
|
n <= n + 1;
|
||||||
|
|
||||||
|
case (n)
|
||||||
|
0: x_beg[15:8] <= readed;
|
||||||
|
1: x_beg[7:0] <= readed;
|
||||||
|
2: x_end[15:8] <= readed;
|
||||||
|
3: x_end[7:0] <= readed;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_PADDR: begin
|
||||||
|
n <= n + 1;
|
||||||
|
|
||||||
|
case (n)
|
||||||
|
0: y_beg[15:8] <= readed;
|
||||||
|
1: y_beg[7:0] <= readed;
|
||||||
|
2: y_end[15:8] <= readed;
|
||||||
|
3: y_end[7:0] <= readed;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
ST_MEM_WRITE: begin
|
||||||
|
if (n == 0) begin
|
||||||
|
n <= 1;
|
||||||
|
tmp <= readed;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
n <= 0;
|
||||||
|
|
||||||
|
// $display("%d %d %d %d %d", x, y,
|
||||||
|
// { tmp[7:3], 1'b0 },
|
||||||
|
// { tmp[2:0], readed[7:5] },
|
||||||
|
// { readed[4:0], 1'b0 });
|
||||||
|
|
||||||
|
x_o <= x;
|
||||||
|
y_o <= y;
|
||||||
|
r_o <= { 2'b00, tmp[7:3], 1'b0 };
|
||||||
|
g_o <= { 2'b00, tmp[2:0], readed[7:5] };
|
||||||
|
b_o <= { 2'b00, readed[4:0], 1'b0 };
|
||||||
|
strobe_o <= 1'b1;
|
||||||
|
|
||||||
|
x <= x + 1;
|
||||||
|
if (x == int'(x_end)) begin
|
||||||
|
x <= int'(x_beg);
|
||||||
|
|
||||||
|
y <= y + 1;
|
||||||
|
if (y == int'(y_end))
|
||||||
|
y <= int'(y_beg);
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // lcd_ili9341_4spi
|
||||||
61
testbench/lcd-model/lcd_init.rom
Normal file
61
testbench/lcd-model/lcd_init.rom
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
|
000
|
||||||
1
testbench/lcd-model/quadrant_256.rom
Symbolic link
1
testbench/lcd-model/quadrant_256.rom
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../source/quadrant_256.rom
|
||||||
107
testbench/lcd-model/testbench_top.cpp
Normal file
107
testbench/lcd-model/testbench_top.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
|
||||||
|
#include <verilated_vcd_c.h>
|
||||||
|
#include "Vtestbench_top.h"
|
||||||
|
|
||||||
|
#define DUMPFILE "testbench_top.vcd"
|
||||||
|
#define PIPE_FILE "lcd_pipe"
|
||||||
|
|
||||||
|
/* Clock period in timescale units
|
||||||
|
* In datapath.sv uses 100ps time unit */
|
||||||
|
#define CLOCK_PERIOD 2
|
||||||
|
#define TIMESCALE 20000
|
||||||
|
|
||||||
|
/* Simulation time */
|
||||||
|
uint64_t simtime = 0;
|
||||||
|
|
||||||
|
/* Clock cycle counter */
|
||||||
|
uint64_t cycle = 0;
|
||||||
|
|
||||||
|
/* Called by $time in Verilog */
|
||||||
|
double sc_time_stamp() {
|
||||||
|
return simtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
Verilated::commandArgs(argc, argv);
|
||||||
|
|
||||||
|
/* Create model instance */
|
||||||
|
Vtestbench_top *dp = new Vtestbench_top;
|
||||||
|
|
||||||
|
/* Enable trace if compiled with --trace flag */
|
||||||
|
#if (VM_TRACE == 1)
|
||||||
|
VerilatedVcdC *vcd = NULL;
|
||||||
|
const char* trace_flag = Verilated::commandArgsPlusMatch("trace");
|
||||||
|
|
||||||
|
if (trace_flag && (strcmp(trace_flag, "+trace") == 0))
|
||||||
|
{
|
||||||
|
Verilated::traceEverOn(true);
|
||||||
|
vcd = new VerilatedVcdC;
|
||||||
|
dp->trace(vcd, 99);
|
||||||
|
vcd->open(DUMPFILE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Open pipe */
|
||||||
|
FILE *o_file = fopen(PIPE_FILE, "w");
|
||||||
|
if (!o_file) {
|
||||||
|
printf("ERROR: Can't open file/pipe '%s'\n", PIPE_FILE);
|
||||||
|
delete dp;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int posedge_clock = 0;
|
||||||
|
|
||||||
|
int data_loops = 6;
|
||||||
|
uint64_t check_cycle;
|
||||||
|
|
||||||
|
/* Initial */
|
||||||
|
dp->reset = 1;
|
||||||
|
dp->clock = 0;
|
||||||
|
|
||||||
|
while (!Verilated::gotFinish())
|
||||||
|
{
|
||||||
|
posedge_clock = 0;
|
||||||
|
if ((simtime % (CLOCK_PERIOD/2)) == 0) {
|
||||||
|
dp->clock = !dp->clock;
|
||||||
|
if (dp->clock) {
|
||||||
|
posedge_clock = 1;
|
||||||
|
cycle ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* release reset at 200 simulation cycle */
|
||||||
|
if (simtime == 200) dp->reset = 0;
|
||||||
|
|
||||||
|
dp->eval();
|
||||||
|
|
||||||
|
/* ouput data */
|
||||||
|
if (posedge_clock && !dp->reset && dp->strobe)
|
||||||
|
fprintf(o_file, "%i %i %i %i %i\n",
|
||||||
|
dp->x, dp->y, dp->r << 2, dp->g << 2, dp->b << 2);
|
||||||
|
|
||||||
|
#if (VM_TRACE == 1)
|
||||||
|
if (vcd)
|
||||||
|
vcd->dump(simtime * TIMESCALE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
simtime ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dp->final();
|
||||||
|
printf("[%lu] Stop simulation\n", simtime);
|
||||||
|
|
||||||
|
#if (VM_TRACE == 1)
|
||||||
|
if (vcd) vcd->close();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fclose(o_file);
|
||||||
|
delete dp;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
41
testbench/lcd-model/testbench_top.sv
Normal file
41
testbench/lcd-model/testbench_top.sv
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
/* verilator lint_off PINMISSING */
|
||||||
|
|
||||||
|
module testbench_top
|
||||||
|
(input wire clock,
|
||||||
|
input wire reset,
|
||||||
|
|
||||||
|
output int x,
|
||||||
|
output int y,
|
||||||
|
output [7:0] r,
|
||||||
|
output [7:0] g,
|
||||||
|
output [7:0] b,
|
||||||
|
output strobe);
|
||||||
|
|
||||||
|
logic csn, mosi, clk, dcn;
|
||||||
|
|
||||||
|
sugar_lissajous DUT
|
||||||
|
(.CLK12(clock),
|
||||||
|
.P1_3(1'b0),
|
||||||
|
.P1_10(1'b1),
|
||||||
|
.P2_3(dcn),
|
||||||
|
.P2_9(clk),
|
||||||
|
.P2_11(mosi),
|
||||||
|
.P2_12(csn));
|
||||||
|
|
||||||
|
lcd_ili9341_4spi LCD
|
||||||
|
(.clock, .reset,
|
||||||
|
.csn_i(csn),
|
||||||
|
.clk_i(clk),
|
||||||
|
.sdi_i(mosi),
|
||||||
|
.dcn_i(dcn),
|
||||||
|
.x_o(x),
|
||||||
|
.y_o(y),
|
||||||
|
.r_o(r),
|
||||||
|
.g_o(g),
|
||||||
|
.b_o(b),
|
||||||
|
.strobe_o(strobe));
|
||||||
|
|
||||||
|
endmodule // testbench_top
|
||||||
1
testbench/lcd_init.rom
Symbolic link
1
testbench/lcd_init.rom
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../source/lcd_init.rom
|
||||||
1
testbench/quadrant_256.rom
Symbolic link
1
testbench/quadrant_256.rom
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../source/quadrant_256.rom
|
||||||
60
testbench/tb_circle.sv
Normal file
60
testbench/tb_circle.sv
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
|
||||||
|
module tb_circle;
|
||||||
|
logic clock = 1'b0;
|
||||||
|
logic reset = 1'b1;
|
||||||
|
|
||||||
|
/* Master clock 100MHz (10ns period) */
|
||||||
|
always #(10ns/2) clock <= ~clock;
|
||||||
|
|
||||||
|
logic [9:0] angle;
|
||||||
|
logic [7:0] r;
|
||||||
|
logic [7:0] x0;
|
||||||
|
logic [7:0] y0;
|
||||||
|
logic [7:0] x;
|
||||||
|
logic [7:0] y;
|
||||||
|
logic req, ack;
|
||||||
|
|
||||||
|
circle_1024 DUT
|
||||||
|
(.clock, .reset,
|
||||||
|
.angle,
|
||||||
|
.r,
|
||||||
|
.x0,
|
||||||
|
.y0,
|
||||||
|
.x,
|
||||||
|
.y,
|
||||||
|
.req_i(req),
|
||||||
|
.ack_o(ack));
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
reset = 1'b1;
|
||||||
|
req = 1'b0;
|
||||||
|
repeat(10) @(posedge clock) #1;
|
||||||
|
reset = 1'b0;
|
||||||
|
|
||||||
|
@(posedge clock) #1;
|
||||||
|
|
||||||
|
angle = '0;
|
||||||
|
r = 120;
|
||||||
|
x0 = 120;
|
||||||
|
y0 = 128;
|
||||||
|
|
||||||
|
for (int i = 0; i < 1024; i ++) begin
|
||||||
|
@(posedge clock) #1;
|
||||||
|
req = 1'b1;
|
||||||
|
|
||||||
|
wait (ack);
|
||||||
|
angle = angle + 1'b1;
|
||||||
|
end
|
||||||
|
req = 1'b0;
|
||||||
|
|
||||||
|
repeat(10) @(posedge clock) #1;
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("tb_circle.vcd");
|
||||||
|
$dumpvars;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // tb_circle
|
||||||
70
testbench/tb_fig_drawer.sv
Normal file
70
testbench/tb_fig_drawer.sv
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
|
||||||
|
module tb_fig_drawer;
|
||||||
|
logic clock = 1'b0;
|
||||||
|
logic reset = 1'b1;
|
||||||
|
|
||||||
|
/* Master clock 100MHz (10ns period) */
|
||||||
|
always #(10ns/2) clock <= ~clock;
|
||||||
|
|
||||||
|
logic [7:0] x;
|
||||||
|
logic [8:0] y;
|
||||||
|
logic [7:0] h, s, v;
|
||||||
|
logic req, ack;
|
||||||
|
|
||||||
|
logic [7:0] fb_x;
|
||||||
|
logic [8:0] fb_y;
|
||||||
|
logic [15:0] fb_color;
|
||||||
|
logic fb_req, fb_ack;
|
||||||
|
|
||||||
|
fig_drawer DUT
|
||||||
|
(.clock, .reset,
|
||||||
|
.x_i(x), .y_i(y),
|
||||||
|
.h_i(h), .s_i(s), .v_i(v),
|
||||||
|
.req_i(req), .ack_o(ack),
|
||||||
|
|
||||||
|
.fb_x_o(fb_x),
|
||||||
|
.fb_y_o(fb_y),
|
||||||
|
.fb_color_o(fb_color),
|
||||||
|
.fb_req_o(fb_req),
|
||||||
|
.fb_ack_i(fb_ack));
|
||||||
|
|
||||||
|
int fb_lat_n;
|
||||||
|
always_ff @ (posedge clock) begin
|
||||||
|
fb_ack <= 1'b0;
|
||||||
|
|
||||||
|
if (fb_req)
|
||||||
|
if (fb_lat_n == 2) begin
|
||||||
|
fb_ack <= 1'b1;
|
||||||
|
fb_lat_n <= 0;
|
||||||
|
end
|
||||||
|
else fb_lat_n <= fb_lat_n + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
if (ack)
|
||||||
|
req <= 1'b0;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
reset <= 1'b1;
|
||||||
|
repeat(10) @(posedge clock);
|
||||||
|
reset <= 1'b0;
|
||||||
|
|
||||||
|
@(posedge clock);
|
||||||
|
x <= 'd20;
|
||||||
|
y <= 'd50;
|
||||||
|
h <= 50;
|
||||||
|
s <= 100;
|
||||||
|
v <= 150;
|
||||||
|
req <= 1'b1;
|
||||||
|
|
||||||
|
repeat(1000) @(posedge clock);
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("tb_fig_drawer.vcd");
|
||||||
|
$dumpvars;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // tb_fig_drawer
|
||||||
69
testbench/tb_fig_ring.sv
Normal file
69
testbench/tb_fig_ring.sv
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
|
||||||
|
module tb_fig_ring;
|
||||||
|
logic clock = 1'b0;
|
||||||
|
logic reset = 1'b1;
|
||||||
|
|
||||||
|
/* Master clock 100MHz (10ns period) */
|
||||||
|
always #(10ns/2) clock <= ~clock;
|
||||||
|
|
||||||
|
logic pt_ack_o;
|
||||||
|
logic [7:0] fig_x_o;
|
||||||
|
logic [8:0] fig_y_o;
|
||||||
|
logic [7:0] fig_h_o;
|
||||||
|
logic [7:0] fig_s_o;
|
||||||
|
logic [7:0] fig_v_o;
|
||||||
|
logic fig_req_o;
|
||||||
|
logic [7:0] pt_x;
|
||||||
|
logic [7:0] pt_y;
|
||||||
|
logic [7:0] pt_h;
|
||||||
|
logic pt_req_i;
|
||||||
|
logic fig_ack_i;
|
||||||
|
|
||||||
|
fig_ring DUT (/*AUTOINST*/
|
||||||
|
// Outputs
|
||||||
|
.pt_ack_o (pt_ack_o),
|
||||||
|
.fig_x_o (fig_x_o[7:0]),
|
||||||
|
.fig_y_o (fig_y_o[8:0]),
|
||||||
|
.fig_h_o (fig_h_o[7:0]),
|
||||||
|
.fig_s_o (fig_s_o[7:0]),
|
||||||
|
.fig_v_o (fig_v_o[7:0]),
|
||||||
|
.fig_req_o (fig_req_o),
|
||||||
|
// Inputs
|
||||||
|
.clock (clock),
|
||||||
|
.reset (reset),
|
||||||
|
.pt_x (pt_x[7:0]),
|
||||||
|
.pt_y (pt_y[7:0]),
|
||||||
|
.pt_h (pt_h[7:0]),
|
||||||
|
.pt_req_i (pt_req_i),
|
||||||
|
.fig_ack_i (fig_ack_i));
|
||||||
|
|
||||||
|
assign fig_ack_i = 1'b1;
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
if (pt_ack_o)
|
||||||
|
pt_req_i <= 1'b0;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
reset = 1'b1;
|
||||||
|
pt_req_i = 1'b0;
|
||||||
|
|
||||||
|
repeat(10) @(posedge clock) #1;
|
||||||
|
reset = 1'b0;
|
||||||
|
|
||||||
|
@(posedge clock) #1;
|
||||||
|
pt_x = 0;
|
||||||
|
pt_y = 0;
|
||||||
|
pt_h = 100;
|
||||||
|
pt_req_i = 1'b1;
|
||||||
|
|
||||||
|
repeat(1000) @(posedge clock) #1;
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("tb_fig_ring.vcd");
|
||||||
|
$dumpvars;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // tb_fig_ring
|
||||||
66
testbench/tb_fir_filter.sv
Normal file
66
testbench/tb_fir_filter.sv
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
|
||||||
|
module tb_fir_filter;
|
||||||
|
logic clock = 1'b0;
|
||||||
|
logic reset = 1'b1;
|
||||||
|
|
||||||
|
/* Master clock 100MHz (10ns period) */
|
||||||
|
always #(10ns/2) clock <= ~clock;
|
||||||
|
|
||||||
|
logic signed [15:0] data_i;
|
||||||
|
logic signed [15:0] data_o;
|
||||||
|
logic input_ready, output_valid;
|
||||||
|
|
||||||
|
localparam FILTER_LEN = 425;
|
||||||
|
|
||||||
|
fir_filter #(.LEN(FILTER_LEN),
|
||||||
|
.COEFFS_ROM_FILE("fir_425_50hz_100hz_0db_40db.rom")) DUT
|
||||||
|
(.clock, .reset,
|
||||||
|
.data_i, .data_o,
|
||||||
|
.ready_i(input_ready),
|
||||||
|
.valid_o(output_valid));
|
||||||
|
|
||||||
|
event done;
|
||||||
|
integer file_o;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
file_o = $fopen("filtered.txt", "w");
|
||||||
|
@(done);
|
||||||
|
$fclose(file_o);
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
reset = 1'b1;
|
||||||
|
input_ready = 1'b0;
|
||||||
|
|
||||||
|
repeat(10) @(posedge clock) #1;
|
||||||
|
reset = 1'b0;
|
||||||
|
|
||||||
|
@(posedge clock) #1;
|
||||||
|
data_i = 16'd32767;
|
||||||
|
input_ready = 1'b1;
|
||||||
|
|
||||||
|
@(posedge clock) #1;
|
||||||
|
wait (output_valid)
|
||||||
|
$fdisplay(file_o, "%d", data_o);
|
||||||
|
data_i = '0;
|
||||||
|
|
||||||
|
for (int i = 1; i < FILTER_LEN; i ++) begin
|
||||||
|
@(posedge clock) #1;
|
||||||
|
wait (output_valid)
|
||||||
|
$fdisplay(file_o, "%d", data_o);
|
||||||
|
end
|
||||||
|
|
||||||
|
->done;
|
||||||
|
|
||||||
|
repeat(10) @(posedge clock) #1;
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("tb_fir_filter.vcd");
|
||||||
|
$dumpvars;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // tb_fir_filter
|
||||||
49
testbench/tb_hsl2rgb.sv
Normal file
49
testbench/tb_hsl2rgb.sv
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
|
||||||
|
module tb_hsl2rgb;
|
||||||
|
logic clock = 1'b0;
|
||||||
|
logic reset = 1'b1;
|
||||||
|
|
||||||
|
/* Master clock 100MHz (10ns period) */
|
||||||
|
always #(10ns/2) clock <= ~clock;
|
||||||
|
|
||||||
|
logic [7:0] h, s, l;
|
||||||
|
logic [7:0] r, g, b;
|
||||||
|
logic valid, ready;
|
||||||
|
|
||||||
|
hsl2rgb DUT
|
||||||
|
(.clock, .reset,
|
||||||
|
.h, .s, .l,
|
||||||
|
.ready_i(ready),
|
||||||
|
.r, .g, .b,
|
||||||
|
.valid_o(valid));
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
if (valid)
|
||||||
|
$display("%d %d %d", r, g, b);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
reset = 1'b1;
|
||||||
|
ready = 1'b0;
|
||||||
|
repeat(10) @(posedge clock) #1;
|
||||||
|
reset = 1'b0;
|
||||||
|
|
||||||
|
@(posedge clock) #1;
|
||||||
|
h = 8'd128;
|
||||||
|
s = 8'd255;
|
||||||
|
l = 8'd130;
|
||||||
|
ready = 1'b1;
|
||||||
|
|
||||||
|
@(posedge clock) #1;
|
||||||
|
ready = 1'b0;
|
||||||
|
|
||||||
|
repeat(20) @(posedge clock);
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("tb_hsl2rgb.vcd");
|
||||||
|
$dumpvars;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // tb_hsl2rgb
|
||||||
78
testbench/tb_hsv2rgb.sv
Normal file
78
testbench/tb_hsv2rgb.sv
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
|
||||||
|
module tb_hsv2rgb;
|
||||||
|
logic clock = 1'b0;
|
||||||
|
logic reset = 1'b1;
|
||||||
|
|
||||||
|
/* Master clock 100MHz (10ns period) */
|
||||||
|
always #(10ns/2) clock <= ~clock;
|
||||||
|
|
||||||
|
logic [7:0] h, s, v;
|
||||||
|
logic [7:0] r, g, b;
|
||||||
|
logic valid, ready;
|
||||||
|
|
||||||
|
hsv2rgb DUT
|
||||||
|
(.clock, .reset,
|
||||||
|
.h, .s, .v,
|
||||||
|
.ready_i(ready),
|
||||||
|
.r, .g, .b,
|
||||||
|
.valid_o(valid));
|
||||||
|
|
||||||
|
always_ff @ (posedge clock)
|
||||||
|
if (valid)
|
||||||
|
$display("%d %d %d", r, g, b);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
reset = 1'b1;
|
||||||
|
ready = 1'b0;
|
||||||
|
repeat(10) @(posedge clock) #1;
|
||||||
|
reset = 1'b0;
|
||||||
|
|
||||||
|
@(posedge clock) #1;
|
||||||
|
h = 8'd50;
|
||||||
|
s = 8'd100;
|
||||||
|
v = 8'd150;
|
||||||
|
ready = 1'b1;
|
||||||
|
|
||||||
|
@(posedge clock) #1;
|
||||||
|
h = 8'dx;
|
||||||
|
s = 8'dx;
|
||||||
|
v = 8'dx;
|
||||||
|
ready = 1'b0;
|
||||||
|
|
||||||
|
@(posedge clock) #1;
|
||||||
|
@(posedge clock) #1;
|
||||||
|
@(posedge clock) #1;
|
||||||
|
|
||||||
|
@(posedge clock) #1;
|
||||||
|
h = 8'd50;
|
||||||
|
s = 8'd100;
|
||||||
|
v = 8'd150;
|
||||||
|
ready = 1'b1;
|
||||||
|
|
||||||
|
@(posedge clock) #1;
|
||||||
|
h = 8'd111;
|
||||||
|
s = 8'd222;
|
||||||
|
v = 8'd33;
|
||||||
|
ready = 1'b1;
|
||||||
|
|
||||||
|
@(posedge clock) #1;
|
||||||
|
h = 8'd200;
|
||||||
|
s = 8'd150;
|
||||||
|
v = 8'd50;
|
||||||
|
ready = 1'b1;
|
||||||
|
|
||||||
|
@(posedge clock) #1;
|
||||||
|
ready = 1'b0;
|
||||||
|
|
||||||
|
|
||||||
|
repeat(10) @(posedge clock);
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("tb_hsv2rgb.vcd");
|
||||||
|
$dumpvars;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // tb_hsv2rgb
|
||||||
63
testbench/tb_lcd_spi.sv
Normal file
63
testbench/tb_lcd_spi.sv
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
`timescale 1ns/100ps
|
||||||
|
|
||||||
|
module tb_lcd_spi;
|
||||||
|
logic clock = 1'b0;
|
||||||
|
logic reset = 1'b1;
|
||||||
|
|
||||||
|
/* Master clock 50MHz (20ns period) */
|
||||||
|
always #(20ns/2) clock <= ~clock;
|
||||||
|
|
||||||
|
logic [7:0] data;
|
||||||
|
logic push, done;
|
||||||
|
logic sclk, sdo;
|
||||||
|
|
||||||
|
lcd_spi #(.DATA_WIDTH(8),
|
||||||
|
.SPI_CLK_PERIOD(16)) DUT
|
||||||
|
(.clock, .reset,
|
||||||
|
.data_i(data),
|
||||||
|
.push_i(push),
|
||||||
|
.done_o(done),
|
||||||
|
.spi_clk_o(sclk),
|
||||||
|
.spi_dat_o(sdo));
|
||||||
|
|
||||||
|
int state;
|
||||||
|
|
||||||
|
always_ff @(posedge clock)
|
||||||
|
if (reset) begin
|
||||||
|
push <= 1'b0;
|
||||||
|
state <= 0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
case (state)
|
||||||
|
0: begin
|
||||||
|
data <= $random;
|
||||||
|
push <= 1'b1;
|
||||||
|
state <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
1: begin
|
||||||
|
if (done) begin
|
||||||
|
//data <= $random;
|
||||||
|
push <= 1'b0;
|
||||||
|
state <= 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
reset = 1'b1;
|
||||||
|
repeat(10) @(posedge clock) #1;
|
||||||
|
reset = 1'b0;
|
||||||
|
|
||||||
|
repeat(1000) @(posedge clock);
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("tb_lcd_spi.vcd");
|
||||||
|
$dumpvars;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // tb_lcd_spi
|
||||||
Loading…
x
Reference in New Issue
Block a user