mirror of
git://projects.qi-hardware.com/nn-usb-fpga.git
synced 2025-04-21 12:27:27 +03:00
Updating examples to Board changes, adding irq driver demo
This commit is contained in:
23
lm32/logic/sakc/cores/vgafb/doc/Makefile
Normal file
23
lm32/logic/sakc/cores/vgafb/doc/Makefile
Normal file
@@ -0,0 +1,23 @@
|
||||
TEX=vgafb.tex
|
||||
|
||||
DVI=$(TEX:.tex=.dvi)
|
||||
PS=$(TEX:.tex=.ps)
|
||||
PDF=$(TEX:.tex=.pdf)
|
||||
AUX=$(TEX:.tex=.aux)
|
||||
LOG=$(TEX:.tex=.log)
|
||||
|
||||
all: $(PDF)
|
||||
|
||||
%.dvi: %.tex
|
||||
latex $<
|
||||
|
||||
%.ps: %.dvi
|
||||
dvips $<
|
||||
|
||||
%.pdf: %.ps
|
||||
ps2pdf $<
|
||||
|
||||
clean:
|
||||
rm -f $(DVI) $(PS) $(PDF) $(AUX) $(LOG)
|
||||
|
||||
.PHONY: clean
|
||||
74
lm32/logic/sakc/cores/vgafb/doc/vgafb.tex
Normal file
74
lm32/logic/sakc/cores/vgafb/doc/vgafb.tex
Normal file
@@ -0,0 +1,74 @@
|
||||
\documentclass[a4paper,11pt]{article}
|
||||
\usepackage{fullpage}
|
||||
\usepackage[latin1]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[normalem]{ulem}
|
||||
\usepackage[english]{babel}
|
||||
\usepackage{listings,babel}
|
||||
\lstset{breaklines=true,basicstyle=\ttfamily}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{moreverb}
|
||||
\usepackage{url}
|
||||
\usepackage{amsmath}
|
||||
|
||||
\title{VGA framebuffer}
|
||||
\author{S\'ebastien Bourdeauducq}
|
||||
\date{December 2009}
|
||||
\begin{document}
|
||||
\setlength{\parindent}{0pt}
|
||||
\setlength{\parskip}{5pt}
|
||||
\maketitle{}
|
||||
\section{Specifications}
|
||||
The VGA framebuffer core enables a system-on-chip to support a VGA video output with the picture read from a memory framebuffer.
|
||||
The core directly drives a 3-channel 8-bit digital to analog converter and the horizontal and vertical synchronization signals.
|
||||
The framebuffer is read with a 4x64 FastMemoryLink (FML) master; and a CSR interface is implemented for configuring the video output.
|
||||
|
||||
\section{Registers}
|
||||
\subsection{Control register, offset 0x00}
|
||||
This register enables or disables the video output by setting or clearing the reset bit 0. At reset, the default value is 0x1.
|
||||
|
||||
\subsection{Horizontal video parameters, offsets 0x04, 0x08, 0x0c and 0x10}
|
||||
Those registers set respectively:
|
||||
\begin{itemize}
|
||||
\item the horizontal size of the active video area (the horizontal resolution)
|
||||
\item the position of the beginning of the horizontal sync pulse in the scan line, in pixel clocks
|
||||
\item the position of the end of the horizontal sync pulse in the scan line, in pixel clocks
|
||||
\item the total length of the horizontal scan line minus one, in pixels
|
||||
\end{itemize}
|
||||
The default values are for the standard VGA resolution of 640x480 at 60Hz with a 25MHz pixel clock.
|
||||
|
||||
\subsection{Vertical video parameters, offsets 0x14, 0x18, 0x1c and 0x20}
|
||||
Those registers set respectively:
|
||||
\begin{itemize}
|
||||
\item the vertical size of the active video area (the vertical resolution)
|
||||
\item the position of the beginning of the vertical sync pulse. The unit is the horizontal scan line.
|
||||
\item the position of the end of the vertical sync pulse. Same unit as above.
|
||||
\item the total count of horizontal scan lines minus one. Same unit as above.
|
||||
\end{itemize}
|
||||
The default values are for the standard VGA resolution of 640x480 at 60Hz with a 25MHz pixel clock.
|
||||
|
||||
\subsection{DMA control registers, offsets 0x24, 0x28 and 0x2c}
|
||||
The register 0x24 defines the base address of the framebuffer. That framebuffer is basic progressive scan buffer using the RGB565 pixel format.
|
||||
|
||||
When register 0x24 is written, the framebuffer address is not updated immediately. Instead, the VGA core waits for the end of the vertical active video area and only starts fetching data from the new framebuffer at the beginning of the next frame. This enables the use of multiple framebuffers without any tearing or flickering artifacts. The address from which the core is currently reading data is available in register 0x28.
|
||||
When registers 0x24 and 0x28 have different values, a framebuffer address change is pending. When they have the same values, the frame being displayed is the latest that was asked for.
|
||||
|
||||
The framebuffer must be aligned to the start of a FML burst ($\frac{4 \cdot 64}{8}$ bytes).
|
||||
|
||||
Register 0x2c defines the number of FML bursts required to fill a complete screen. This is typically set to:
|
||||
\[
|
||||
\frac{\text{horizontal resolution} \cdot \text{vertical resolution} \cdot 16}{4 \cdot 64}
|
||||
\]
|
||||
|
||||
The screen resolution must be set so that this number is integer. This is the case with common VGA resolutions.
|
||||
|
||||
\section{Connections}
|
||||
The pixel clock is not generated internally and must be fed to the core using the \verb!vga_clk! port. No relationship is expected with the system clock (the two domains are entirely independent). That pixel clock should also be fed to the synchronous DAC.
|
||||
|
||||
The other ports should be self-explanatory.
|
||||
|
||||
\section*{Copyright notice}
|
||||
Copyright \copyright 2007-2009 S\'ebastien Bourdeauducq. \\
|
||||
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the LICENSE.FDL file at the root of the Milkymist source distribution.
|
||||
|
||||
\end{document}
|
||||
229
lm32/logic/sakc/cores/vgafb/rtl/vgafb.v
Normal file
229
lm32/logic/sakc/cores/vgafb/rtl/vgafb.v
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Milkymist VJ SoC
|
||||
* Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module vgafb #(
|
||||
parameter csr_addr = 4'h0,
|
||||
parameter fml_depth = 26
|
||||
) (
|
||||
input sys_clk,
|
||||
input sys_rst,
|
||||
|
||||
/* Configuration interface */
|
||||
input [13:0] csr_a,
|
||||
input csr_we,
|
||||
input [31:0] csr_di,
|
||||
output [31:0] csr_do,
|
||||
|
||||
/* Framebuffer FML 4x64 interface */
|
||||
output [fml_depth-1:0] fml_adr,
|
||||
output fml_stb,
|
||||
input fml_ack,
|
||||
input [63:0] fml_di,
|
||||
|
||||
/* VGA pixel clock */
|
||||
input vga_clk,
|
||||
|
||||
/* VGA signal pads */
|
||||
output vga_psave_n,
|
||||
output reg vga_hsync_n,
|
||||
output reg vga_vsync_n,
|
||||
output vga_sync_n,
|
||||
output vga_blank_n,
|
||||
output reg [7:0] vga_r,
|
||||
output reg [7:0] vga_g,
|
||||
output reg [7:0] vga_b,
|
||||
output [1:0] vga_clk_sel
|
||||
);
|
||||
|
||||
/*
|
||||
* Control interface
|
||||
*/
|
||||
wire vga_rst;
|
||||
|
||||
wire [10:0] hres;
|
||||
wire [10:0] hsync_start;
|
||||
wire [10:0] hsync_end;
|
||||
wire [10:0] hscan;
|
||||
|
||||
wire [10:0] vres;
|
||||
wire [10:0] vsync_start;
|
||||
wire [10:0] vsync_end;
|
||||
wire [10:0] vscan;
|
||||
|
||||
wire [fml_depth-1:0] baseaddress;
|
||||
wire baseaddress_ack;
|
||||
|
||||
wire [17:0] nbursts;
|
||||
|
||||
vgafb_ctlif #(
|
||||
.csr_addr(csr_addr),
|
||||
.fml_depth(fml_depth)
|
||||
) ctlif (
|
||||
.sys_clk(sys_clk),
|
||||
.sys_rst(sys_rst),
|
||||
|
||||
.csr_a(csr_a),
|
||||
.csr_we(csr_we),
|
||||
.csr_di(csr_di),
|
||||
.csr_do(csr_do),
|
||||
|
||||
.vga_rst(vga_rst),
|
||||
|
||||
.hres(hres),
|
||||
.hsync_start(hsync_start),
|
||||
.hsync_end(hsync_end),
|
||||
.hscan(hscan),
|
||||
|
||||
.vres(vres),
|
||||
.vsync_start(vsync_start),
|
||||
.vsync_end(vsync_end),
|
||||
.vscan(vscan),
|
||||
|
||||
.baseaddress(baseaddress),
|
||||
.baseaddress_ack(baseaddress_ack),
|
||||
|
||||
.nbursts(nbursts),
|
||||
|
||||
.vga_clk_sel(vga_clk_sel)
|
||||
);
|
||||
|
||||
/*
|
||||
* Generate signal data
|
||||
*/
|
||||
reg hsync_n;
|
||||
reg vsync_n;
|
||||
wire pixel_valid;
|
||||
wire [15:0] pixel_fb;
|
||||
wire pixel_ack;
|
||||
wire [15:0] pixel;
|
||||
|
||||
wire fifo_full;
|
||||
|
||||
reg hactive;
|
||||
reg vactive;
|
||||
wire active = hactive & vactive;
|
||||
assign pixel = active ? pixel_fb : 16'h0000;
|
||||
|
||||
wire generate_en;
|
||||
|
||||
reg [10:0] hcounter;
|
||||
reg [10:0] vcounter;
|
||||
|
||||
always @(posedge sys_clk) begin
|
||||
if(vga_rst) begin
|
||||
hcounter <= 10'd0;
|
||||
vcounter <= 10'd0;
|
||||
hactive <= 1'b0;
|
||||
hsync_n <= 1'b1;
|
||||
vactive <= 1'b0;
|
||||
vsync_n <= 1'b1;
|
||||
end else begin
|
||||
if(generate_en) begin
|
||||
hcounter <= hcounter + 10'd1;
|
||||
|
||||
if(hcounter == 10'd0) hactive <= 1'b1;
|
||||
if(hcounter == hres) hactive <= 1'b0;
|
||||
if(hcounter == hsync_start) hsync_n <= 1'b0;
|
||||
if(hcounter == hsync_end) hsync_n <= 1'b1;
|
||||
if(hcounter == hscan) begin
|
||||
hcounter <= 10'd0;
|
||||
if(vcounter == vscan)
|
||||
vcounter <= 10'd0;
|
||||
else
|
||||
vcounter <= vcounter + 10'd1;
|
||||
end
|
||||
|
||||
if(vcounter == 10'd0) vactive <= 1'b1;
|
||||
if(vcounter == vres) vactive <= 1'b0;
|
||||
if(vcounter == vsync_start) vsync_n <= 1'b0;
|
||||
if(vcounter == vsync_end) vsync_n <= 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign generate_en = ~fifo_full & (~active | pixel_valid);
|
||||
assign pixel_ack = ~fifo_full & active & pixel_valid;
|
||||
|
||||
vgafb_pixelfeed #(
|
||||
.fml_depth(fml_depth)
|
||||
) pixelfeed (
|
||||
.sys_clk(sys_clk),
|
||||
.sys_rst(sys_rst),
|
||||
.vga_rst(vga_rst),
|
||||
|
||||
.nbursts(nbursts),
|
||||
.baseaddress(baseaddress),
|
||||
.baseaddress_ack(baseaddress_ack),
|
||||
|
||||
.fml_adr(fml_adr),
|
||||
.fml_stb(fml_stb),
|
||||
.fml_ack(fml_ack),
|
||||
.fml_di(fml_di),
|
||||
|
||||
.pixel_valid(pixel_valid),
|
||||
.pixel(pixel_fb),
|
||||
.pixel_ack(pixel_ack)
|
||||
);
|
||||
|
||||
/*
|
||||
* System clock to VGA clock domain crossing is
|
||||
* acheived by an asynchronous FIFO.
|
||||
*
|
||||
* Bits 0-15 are RGB565 pixel data
|
||||
* Bit 16 is negated Horizontal Sync
|
||||
* Bit 17 is negated Verical Sync
|
||||
*/
|
||||
wire [17:0] fifo_do;
|
||||
|
||||
vgafb_asfifo #(
|
||||
.DATA_WIDTH(18),
|
||||
.ADDRESS_WIDTH(6)
|
||||
) fifo (
|
||||
.Data_out(fifo_do),
|
||||
.Empty_out(),
|
||||
.ReadEn_in(1'b1),
|
||||
.RClk(vga_clk),
|
||||
|
||||
.Data_in({vsync_n, hsync_n, pixel}),
|
||||
.Full_out(fifo_full),
|
||||
.WriteEn_in(generate_en),
|
||||
.WClk(sys_clk),
|
||||
|
||||
.Clear_in(vga_rst)
|
||||
);
|
||||
|
||||
/*
|
||||
* Drive the VGA pads.
|
||||
* RGB565 -> RGB888 color space conversion is also performed here
|
||||
* by bit shifting and replicating the most significant bits of
|
||||
* the input into the least significant bits of the output left
|
||||
* undefined by the shifting.
|
||||
*/
|
||||
|
||||
assign vga_sync_n = 1'b0; /* Sync-on-Green is not implemented */
|
||||
assign vga_psave_n = 1'b1;
|
||||
assign vga_blank_n = 1'b1;
|
||||
|
||||
always @(posedge vga_clk) begin
|
||||
vga_vsync_n <= fifo_do[17];
|
||||
vga_hsync_n <= fifo_do[16];
|
||||
vga_r <= {fifo_do[15:11], fifo_do[15:13]};
|
||||
vga_g <= {fifo_do[10:5], fifo_do[10:9]};
|
||||
vga_b <= {fifo_do[4:0], fifo_do[4:2]};
|
||||
end
|
||||
|
||||
endmodule
|
||||
116
lm32/logic/sakc/cores/vgafb/rtl/vgafb_asfifo.v
Normal file
116
lm32/logic/sakc/cores/vgafb/rtl/vgafb_asfifo.v
Normal file
@@ -0,0 +1,116 @@
|
||||
//==========================================
|
||||
// Function : Asynchronous FIFO (w/ 2 asynchronous clocks).
|
||||
// Coder : Alex Claros F.
|
||||
// Date : 15/May/2005.
|
||||
// Notes : This implementation is based on the article
|
||||
// 'Asynchronous FIFO in Virtex-II FPGAs'
|
||||
// writen by Peter Alfke. This TechXclusive
|
||||
// article can be downloaded from the
|
||||
// Xilinx website. It has some minor modifications.
|
||||
//=========================================
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module vgafb_asfifo
|
||||
#(parameter DATA_WIDTH = 8,
|
||||
ADDRESS_WIDTH = 4,
|
||||
FIFO_DEPTH = (1 << ADDRESS_WIDTH))
|
||||
//Reading port
|
||||
(output wire [DATA_WIDTH-1:0] Data_out,
|
||||
output reg Empty_out,
|
||||
input wire ReadEn_in,
|
||||
input wire RClk,
|
||||
//Writing port.
|
||||
input wire [DATA_WIDTH-1:0] Data_in,
|
||||
output reg Full_out,
|
||||
input wire WriteEn_in,
|
||||
input wire WClk,
|
||||
|
||||
input wire Clear_in);
|
||||
|
||||
/////Internal connections & variables//////
|
||||
reg [DATA_WIDTH-1:0] Mem [FIFO_DEPTH-1:0];
|
||||
wire [ADDRESS_WIDTH-1:0] pNextWordToWrite, pNextWordToRead;
|
||||
wire EqualAddresses;
|
||||
wire NextWriteAddressEn, NextReadAddressEn;
|
||||
wire Set_Status, Rst_Status;
|
||||
reg Status;
|
||||
wire PresetFull, PresetEmpty;
|
||||
|
||||
//////////////Code///////////////
|
||||
//Data ports logic:
|
||||
//(Uses a dual-port RAM).
|
||||
//'Data_out' logic:
|
||||
assign Data_out = Mem[pNextWordToRead];
|
||||
// always @ (posedge RClk)
|
||||
// if (!PresetEmpty)
|
||||
// Data_out <= Mem[pNextWordToRead];
|
||||
// if (ReadEn_in & !Empty_out)
|
||||
|
||||
//'Data_in' logic:
|
||||
always @ (posedge WClk)
|
||||
if (WriteEn_in & !Full_out)
|
||||
Mem[pNextWordToWrite] <= Data_in;
|
||||
|
||||
//Fifo addresses support logic:
|
||||
//'Next Addresses' enable logic:
|
||||
assign NextWriteAddressEn = WriteEn_in & ~Full_out;
|
||||
assign NextReadAddressEn = ReadEn_in & ~Empty_out;
|
||||
|
||||
//Addreses (Gray counters) logic:
|
||||
vgafb_graycounter #(
|
||||
.COUNTER_WIDTH( ADDRESS_WIDTH )
|
||||
) GrayCounter_pWr (
|
||||
.GrayCount_out(pNextWordToWrite),
|
||||
.Enable_in(NextWriteAddressEn),
|
||||
.Clear_in(Clear_in),
|
||||
|
||||
.Clk(WClk)
|
||||
);
|
||||
|
||||
vgafb_graycounter #(
|
||||
.COUNTER_WIDTH( ADDRESS_WIDTH )
|
||||
) GrayCounter_pRd (
|
||||
.GrayCount_out(pNextWordToRead),
|
||||
.Enable_in(NextReadAddressEn),
|
||||
.Clear_in(Clear_in),
|
||||
.Clk(RClk)
|
||||
);
|
||||
|
||||
|
||||
//'EqualAddresses' logic:
|
||||
assign EqualAddresses = (pNextWordToWrite == pNextWordToRead);
|
||||
|
||||
//'Quadrant selectors' logic:
|
||||
assign Set_Status = (pNextWordToWrite[ADDRESS_WIDTH-2] ~^ pNextWordToRead[ADDRESS_WIDTH-1]) &
|
||||
(pNextWordToWrite[ADDRESS_WIDTH-1] ^ pNextWordToRead[ADDRESS_WIDTH-2]);
|
||||
|
||||
assign Rst_Status = (pNextWordToWrite[ADDRESS_WIDTH-2] ^ pNextWordToRead[ADDRESS_WIDTH-1]) &
|
||||
(pNextWordToWrite[ADDRESS_WIDTH-1] ~^ pNextWordToRead[ADDRESS_WIDTH-2]);
|
||||
|
||||
//'Status' latch logic:
|
||||
always @ (Set_Status, Rst_Status, Clear_in) //D Latch w/ Asynchronous Clear & Preset.
|
||||
if (Rst_Status | Clear_in)
|
||||
Status = 0; //Going 'Empty'.
|
||||
else if (Set_Status)
|
||||
Status = 1; //Going 'Full'.
|
||||
|
||||
//'Full_out' logic for the writing port:
|
||||
assign PresetFull = Status & EqualAddresses; //'Full' Fifo.
|
||||
|
||||
always @ (posedge WClk, posedge PresetFull) //D Flip-Flop w/ Asynchronous Preset.
|
||||
if (PresetFull)
|
||||
Full_out <= 1;
|
||||
else
|
||||
Full_out <= 0;
|
||||
|
||||
//'Empty_out' logic for the reading port:
|
||||
assign PresetEmpty = ~Status & EqualAddresses; //'Empty' Fifo.
|
||||
|
||||
always @ (posedge RClk, posedge PresetEmpty) //D Flip-Flop w/ Asynchronous Preset.
|
||||
if (PresetEmpty)
|
||||
Empty_out <= 1;
|
||||
else
|
||||
Empty_out <= 0;
|
||||
|
||||
endmodule
|
||||
93
lm32/logic/sakc/cores/vgafb/rtl/vgafb_asfifo_xilinx.v
Normal file
93
lm32/logic/sakc/cores/vgafb/rtl/vgafb_asfifo_xilinx.v
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Milkymist VJ SoC
|
||||
* Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* FIXME: this module does not work. Find out why. */
|
||||
|
||||
module vgafb_asfifo #(
|
||||
/* NB: those are fixed in this implementation */
|
||||
parameter DATA_WIDTH = 18,
|
||||
parameter ADDRESS_WIDTH = 11
|
||||
) (
|
||||
/* Reading port */
|
||||
output [17:0] Data_out,
|
||||
output Empty_out,
|
||||
input ReadEn_in,
|
||||
input RClk,
|
||||
|
||||
/* Writing port */
|
||||
input [17:0] Data_in,
|
||||
output Full_out,
|
||||
input WriteEn_in,
|
||||
input WClk,
|
||||
|
||||
input Clear_in
|
||||
);
|
||||
|
||||
wire full;
|
||||
wire empty;
|
||||
|
||||
FIFO16 #(
|
||||
.DATA_WIDTH(9),
|
||||
.FIRST_WORD_FALL_THROUGH("TRUE")
|
||||
) fifo_lo (
|
||||
.ALMOSTEMPTY(),
|
||||
.ALMOSTFULL(),
|
||||
.DO(Data_out[7:0]),
|
||||
.DOP(Data_out[8]),
|
||||
.EMPTY(empty),
|
||||
.FULL(full),
|
||||
.RDCOUNT(),
|
||||
.RDERR(),
|
||||
.WRCOUNT(),
|
||||
.WRERR(),
|
||||
.DI(Data_in[7:0]),
|
||||
.DIP(Data_in[8]),
|
||||
.RDCLK(RClk),
|
||||
.RDEN(ReadEn_in & ~empty & ~Clear_in),
|
||||
.RST(Clear_in),
|
||||
.WRCLK(WClk),
|
||||
.WREN(WriteEn_in & ~full & ~Clear_in)
|
||||
);
|
||||
|
||||
assign Empty_out = empty;
|
||||
assign Full_out = full;
|
||||
|
||||
FIFO16 #(
|
||||
.DATA_WIDTH(9),
|
||||
.FIRST_WORD_FALL_THROUGH("TRUE")
|
||||
) fifo_hi (
|
||||
.ALMOSTEMPTY(),
|
||||
.ALMOSTFULL(),
|
||||
.DO(Data_out[16:9]),
|
||||
.DOP(Data_out[17]),
|
||||
.EMPTY(),
|
||||
.FULL(),
|
||||
.RDCOUNT(),
|
||||
.RDERR(),
|
||||
.WRCOUNT(),
|
||||
.WRERR(),
|
||||
.DI(Data_in[16:9]),
|
||||
.DIP(Data_in[17]),
|
||||
.RDCLK(RClk),
|
||||
.RDEN(ReadEn_in & ~empty & ~Clear_in),
|
||||
.RST(Clear_in),
|
||||
.WRCLK(WClk),
|
||||
.WREN(WriteEn_in & ~full & ~Clear_in)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
121
lm32/logic/sakc/cores/vgafb/rtl/vgafb_ctlif.v
Normal file
121
lm32/logic/sakc/cores/vgafb/rtl/vgafb_ctlif.v
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Milkymist VJ SoC
|
||||
* Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module vgafb_ctlif #(
|
||||
parameter csr_addr = 4'h0,
|
||||
parameter fml_depth = 26
|
||||
) (
|
||||
input sys_clk,
|
||||
input sys_rst,
|
||||
|
||||
input [13:0] csr_a,
|
||||
input csr_we,
|
||||
input [31:0] csr_di,
|
||||
output reg [31:0] csr_do,
|
||||
|
||||
output reg vga_rst,
|
||||
|
||||
output reg [10:0] hres,
|
||||
output reg [10:0] hsync_start,
|
||||
output reg [10:0] hsync_end,
|
||||
output reg [10:0] hscan,
|
||||
|
||||
output reg [10:0] vres,
|
||||
output reg [10:0] vsync_start,
|
||||
output reg [10:0] vsync_end,
|
||||
output reg [10:0] vscan,
|
||||
|
||||
output reg [fml_depth-1:0] baseaddress,
|
||||
input baseaddress_ack,
|
||||
|
||||
output reg [17:0] nbursts,
|
||||
|
||||
output reg [1:0] vga_clk_sel
|
||||
);
|
||||
|
||||
reg [fml_depth-1:0] baseaddress_act;
|
||||
|
||||
always @(posedge sys_clk) begin
|
||||
if(sys_rst)
|
||||
baseaddress_act <= {fml_depth{1'b0}};
|
||||
else if(baseaddress_ack)
|
||||
baseaddress_act <= baseaddress;
|
||||
end
|
||||
|
||||
wire csr_selected = csr_a[13:10] == csr_addr;
|
||||
|
||||
always @(posedge sys_clk) begin
|
||||
if(sys_rst) begin
|
||||
csr_do <= 32'd0;
|
||||
|
||||
vga_rst <= 1'b1;
|
||||
|
||||
hres <= 10'd640;
|
||||
hsync_start <= 10'd656;
|
||||
hsync_end <= 10'd752;
|
||||
hscan <= 10'd799;
|
||||
|
||||
vres <= 10'd480;
|
||||
vsync_start <= 10'd491;
|
||||
vsync_end <= 10'd493;
|
||||
vscan <= 10'd523;
|
||||
|
||||
baseaddress <= {fml_depth{1'b0}};
|
||||
|
||||
nbursts <= 18'd19200;
|
||||
vga_clk_sel <= 2'd00;
|
||||
end else begin
|
||||
csr_do <= 32'd0;
|
||||
if(csr_selected) begin
|
||||
if(csr_we) begin
|
||||
case(csr_a[3:0])
|
||||
4'd0: vga_rst <= csr_di[0];
|
||||
4'd1: hres <= csr_di[10:0];
|
||||
4'd2: hsync_start <= csr_di[10:0];
|
||||
4'd3: hsync_end <= csr_di[10:0];
|
||||
4'd4: hscan <= csr_di[10:0];
|
||||
4'd5: vres <= csr_di[10:0];
|
||||
4'd6: vsync_start <= csr_di[10:0];
|
||||
4'd7: vsync_end <= csr_di[10:0];
|
||||
4'd8: vscan <= csr_di[10:0];
|
||||
4'd9: baseaddress <= csr_di[fml_depth-1:0];
|
||||
// 10: baseaddress_act is read-only for Wishbone
|
||||
4'd11: nbursts <= csr_di[17:0];
|
||||
4'd12: vga_clk_sel <= csr_di[1:0];
|
||||
endcase
|
||||
end
|
||||
|
||||
case(csr_a[3:0])
|
||||
4'd0: csr_do <= vga_rst;
|
||||
4'd1: csr_do <= hres;
|
||||
4'd2: csr_do <= hsync_start;
|
||||
4'd3: csr_do <= hsync_end;
|
||||
4'd4: csr_do <= hscan;
|
||||
4'd5: csr_do <= vres;
|
||||
4'd6: csr_do <= vsync_start;
|
||||
4'd7: csr_do <= vsync_end;
|
||||
4'd8: csr_do <= vscan;
|
||||
4'd9: csr_do <= baseaddress;
|
||||
4'd10: csr_do <= baseaddress_act;
|
||||
4'd11: csr_do <= nbursts;
|
||||
4'd12: csr_do <= vga_clk_sel;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
75
lm32/logic/sakc/cores/vgafb/rtl/vgafb_fifo64to16.v
Normal file
75
lm32/logic/sakc/cores/vgafb/rtl/vgafb_fifo64to16.v
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Milkymist VJ SoC
|
||||
* Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module vgafb_fifo64to16(
|
||||
input sys_clk,
|
||||
input vga_rst,
|
||||
|
||||
input stb,
|
||||
input [63:0] di,
|
||||
|
||||
output do_valid,
|
||||
output reg [15:0] do,
|
||||
input next /* should only be asserted when do_valid = 1 */
|
||||
);
|
||||
|
||||
/*
|
||||
* FIFO can hold 4 64-bit words
|
||||
* that is 16 16-bit words.
|
||||
*/
|
||||
|
||||
reg [63:0] storage[0:3];
|
||||
reg [1:0] produce; /* in 64-bit words */
|
||||
reg [3:0] consume; /* in 16-bit words */
|
||||
/*
|
||||
* 16-bit words stored in the FIFO, 0-16 (17 possible values)
|
||||
*/
|
||||
reg [4:0] level;
|
||||
|
||||
wire [63:0] do64;
|
||||
assign do64 = storage[consume[3:2]];
|
||||
|
||||
always @(*) begin
|
||||
case(consume[1:0])
|
||||
2'd0: do <= do64[63:48];
|
||||
2'd1: do <= do64[47:32];
|
||||
2'd2: do <= do64[31:16];
|
||||
2'd3: do <= do64[15:0];
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge sys_clk) begin
|
||||
if(vga_rst) begin
|
||||
produce = 2'd0;
|
||||
consume = 4'd0;
|
||||
level = 5'd0;
|
||||
end else begin
|
||||
if(stb) begin
|
||||
storage[produce] = di;
|
||||
produce = produce + 2'd1;
|
||||
level = level + 5'd4;
|
||||
end
|
||||
if(next) begin /* next should only be asserted when do_valid = 1 */
|
||||
consume = consume + 4'd1;
|
||||
level = level - 5'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign do_valid = ~(level == 5'd0);
|
||||
|
||||
endmodule
|
||||
35
lm32/logic/sakc/cores/vgafb/rtl/vgafb_graycounter.v
Normal file
35
lm32/logic/sakc/cores/vgafb/rtl/vgafb_graycounter.v
Normal file
@@ -0,0 +1,35 @@
|
||||
//==========================================
|
||||
// Function : Code Gray counter.
|
||||
// Coder : Alex Claros F.
|
||||
// Date : 15/May/2005.
|
||||
//=======================================
|
||||
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module vgafb_graycounter
|
||||
#(parameter COUNTER_WIDTH = 2)
|
||||
|
||||
(output reg [COUNTER_WIDTH-1:0] GrayCount_out, //'Gray' code count output.
|
||||
|
||||
input wire Enable_in, //Count enable.
|
||||
input wire Clear_in, //Count reset.
|
||||
|
||||
input wire Clk);
|
||||
|
||||
/////////Internal connections & variables///////
|
||||
reg [COUNTER_WIDTH-1:0] BinaryCount;
|
||||
|
||||
/////////Code///////////////////////
|
||||
|
||||
always @ (posedge Clk)
|
||||
if (Clear_in) begin
|
||||
BinaryCount <= {COUNTER_WIDTH{1'b 0}} + 1; //Gray count begins @ '1' with
|
||||
GrayCount_out <= {COUNTER_WIDTH{1'b 0}}; // first 'Enable_in'.
|
||||
end
|
||||
else if (Enable_in) begin
|
||||
BinaryCount <= BinaryCount + 1;
|
||||
GrayCount_out <= {BinaryCount[COUNTER_WIDTH-1],
|
||||
BinaryCount[COUNTER_WIDTH-2:0] ^ BinaryCount[COUNTER_WIDTH-1:1]};
|
||||
end
|
||||
|
||||
endmodule
|
||||
182
lm32/logic/sakc/cores/vgafb/rtl/vgafb_pixelfeed.v
Normal file
182
lm32/logic/sakc/cores/vgafb/rtl/vgafb_pixelfeed.v
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Milkymist VJ SoC
|
||||
* Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module vgafb_pixelfeed #(
|
||||
parameter fml_depth = 26
|
||||
) (
|
||||
input sys_clk,
|
||||
/* We must take into account both resets :
|
||||
* VGA reset should not interrupt a pending FML request
|
||||
* but system reset should.
|
||||
*/
|
||||
input sys_rst,
|
||||
input vga_rst,
|
||||
|
||||
input [17:0] nbursts,
|
||||
input [fml_depth-1:0] baseaddress,
|
||||
output baseaddress_ack,
|
||||
|
||||
output reg [fml_depth-1:0] fml_adr,
|
||||
output reg fml_stb,
|
||||
input fml_ack,
|
||||
input [63:0] fml_di,
|
||||
|
||||
output pixel_valid,
|
||||
output [15:0] pixel,
|
||||
input pixel_ack
|
||||
);
|
||||
|
||||
/* FIFO that stores the 64-bit bursts and slices it in 16-bit words */
|
||||
|
||||
reg fifo_stb;
|
||||
wire fifo_valid;
|
||||
|
||||
vgafb_fifo64to16 fifo64to16(
|
||||
.sys_clk(sys_clk),
|
||||
.vga_rst(vga_rst),
|
||||
|
||||
.stb(fifo_stb),
|
||||
.di(fml_di),
|
||||
|
||||
.do_valid(fifo_valid),
|
||||
.do(pixel),
|
||||
.next(pixel_ack)
|
||||
);
|
||||
|
||||
assign pixel_valid = fifo_valid;
|
||||
|
||||
/* BURST COUNTER */
|
||||
reg sof;
|
||||
wire counter_en;
|
||||
|
||||
reg [17:0] bcounter;
|
||||
|
||||
always @(posedge sys_clk) begin
|
||||
if(vga_rst) begin
|
||||
bcounter <= 18'd1;
|
||||
sof <= 1'b1;
|
||||
end else begin
|
||||
if(counter_en) begin
|
||||
if(bcounter == nbursts) begin
|
||||
bcounter <= 18'd1;
|
||||
sof <= 1'b1;
|
||||
end else begin
|
||||
bcounter <= bcounter + 18'd1;
|
||||
sof <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
/* FML ADDRESS GENERATOR */
|
||||
wire next_address;
|
||||
|
||||
assign baseaddress_ack = sof & next_address;
|
||||
|
||||
always @(posedge sys_clk) begin
|
||||
if(sys_rst) begin
|
||||
fml_adr <= {fml_depth{1'b0}};
|
||||
end else begin
|
||||
if(next_address) begin
|
||||
if(sof)
|
||||
fml_adr <= baseaddress;
|
||||
else
|
||||
fml_adr <= fml_adr + {{fml_depth-6{1'b0}}, 6'd32};
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
/* CONTROLLER */
|
||||
reg [2:0] state;
|
||||
reg [2:0] next_state;
|
||||
|
||||
parameter IDLE = 3'd0;
|
||||
parameter WAIT = 3'd1;
|
||||
parameter FETCH2 = 3'd2;
|
||||
parameter FETCH3 = 3'd3;
|
||||
parameter FETCH4 = 3'd4;
|
||||
|
||||
always @(posedge sys_clk) begin
|
||||
if(sys_rst)
|
||||
state <= IDLE;
|
||||
else
|
||||
state <= next_state;
|
||||
end
|
||||
|
||||
/*
|
||||
* Do not put spurious data into the FIFO if the VGA reset
|
||||
* is asserted and released during the FML access. Getting
|
||||
* the FIFO out of sync would result in distorted pictures
|
||||
* we really want to avoid.
|
||||
*/
|
||||
|
||||
reg ignore;
|
||||
reg ignore_clear;
|
||||
|
||||
always @(posedge sys_clk) begin
|
||||
if(vga_rst)
|
||||
ignore <= 1'b1;
|
||||
else if(ignore_clear)
|
||||
ignore <= 1'b0;
|
||||
end
|
||||
|
||||
reg next_burst;
|
||||
|
||||
assign counter_en = next_burst;
|
||||
assign next_address = next_burst;
|
||||
|
||||
always @(*) begin
|
||||
next_state = state;
|
||||
|
||||
fifo_stb = 1'b0;
|
||||
next_burst = 1'b0;
|
||||
|
||||
fml_stb = 1'b0;
|
||||
ignore_clear = 1'b0;
|
||||
|
||||
case(state)
|
||||
IDLE: begin
|
||||
if(~fifo_valid & ~vga_rst) begin
|
||||
/* We're in need of pixels ! */
|
||||
next_burst = 1'b1;
|
||||
ignore_clear = 1'b1;
|
||||
next_state = WAIT;
|
||||
end
|
||||
end
|
||||
WAIT: begin
|
||||
fml_stb = 1'b1;
|
||||
if(fml_ack) begin
|
||||
if(~ignore) fifo_stb = 1'b1;
|
||||
next_state = FETCH2;
|
||||
end
|
||||
end
|
||||
FETCH2: begin
|
||||
if(~ignore) fifo_stb = 1'b1;
|
||||
next_state = FETCH3;
|
||||
end
|
||||
FETCH3: begin
|
||||
if(~ignore) fifo_stb = 1'b1;
|
||||
next_state = FETCH4;
|
||||
end
|
||||
FETCH4: begin
|
||||
if(~ignore) fifo_stb = 1'b1;
|
||||
next_state = IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
11
lm32/logic/sakc/cores/vgafb/test/Makefile
Normal file
11
lm32/logic/sakc/cores/vgafb/test/Makefile
Normal file
@@ -0,0 +1,11 @@
|
||||
SOURCES_PIXELFEED=tb_pixelfeed.v ../rtl/vgafb_pixelfeed.v ../rtl/vgafb_fifo64to16.v
|
||||
|
||||
all: pixelfeed
|
||||
|
||||
pixelfeed: $(SOURCES_PIXELFEED)
|
||||
cver $(SOURCES_PIXELFEED)
|
||||
|
||||
clean:
|
||||
rm -f verilog.log
|
||||
|
||||
.PHONY: clean pixelfeed
|
||||
61
lm32/logic/sakc/cores/vgafb/test/tb_pixelfeed.v
Normal file
61
lm32/logic/sakc/cores/vgafb/test/tb_pixelfeed.v
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Milkymist VJ SoC
|
||||
* Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module tb_pixelfeed();
|
||||
|
||||
reg sys_clk;
|
||||
initial sys_clk = 1'b0;
|
||||
always #5 sys_clk = ~sys_clk;
|
||||
|
||||
reg sys_rst;
|
||||
reg vga_rst;
|
||||
|
||||
wire pixel_valid;
|
||||
wire fml_stb;
|
||||
wire [25:0] fml_adr;
|
||||
|
||||
initial begin
|
||||
sys_rst = 1'b1;
|
||||
vga_rst = 1'b1;
|
||||
#20 sys_rst = 1'b0;
|
||||
#20 vga_rst = 1'b0;
|
||||
end
|
||||
|
||||
vgafb_pixelfeed dut(
|
||||
.sys_clk(sys_clk),
|
||||
.sys_rst(sys_rst),
|
||||
.vga_rst(vga_rst),
|
||||
|
||||
.nbursts(18'd100),
|
||||
.baseaddress(26'd1024),
|
||||
.baseaddress_ack(),
|
||||
|
||||
.fml_adr(fml_adr),
|
||||
.fml_stb(fml_stb),
|
||||
.fml_ack(fml_stb),
|
||||
.fml_di(64'hcafebabedeadbeef),
|
||||
|
||||
.pixel_valid(pixel_valid),
|
||||
.pixel(),
|
||||
.pixel_ack(pixel_valid)
|
||||
);
|
||||
|
||||
always @(posedge sys_clk) $display("%x", fml_adr);
|
||||
|
||||
initial #600 $finish;
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user