1
0
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:
Carlos Camargo
2010-06-11 08:06:13 -05:00
parent c8b70e5307
commit 5041c0eb60
41 changed files with 2263 additions and 145 deletions

View 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

View 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

View 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

View 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

View 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

View 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

View 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