mirror of
https://github.com/aolofsson/oh.git
synced 2025-01-30 02:32:53 +08:00
Merge branch 'master' of github.com:parallella/oh
Conflicts: docs/tapeout_checklist.md
This commit is contained in:
commit
893db9508a
17
README.md
17
README.md
@ -123,10 +123,12 @@ TBD
|
||||
* Use common names: nreset, clk, din, dout, en, rd, wr, addr, etc
|
||||
* Make names descriptive, avoid non-common abbreviations
|
||||
* Make names as short as possible, but not shorter
|
||||
* Use short named generate blocks "g0, g1, etc"
|
||||
* Inside generate blocks use short "i<name>" for instance
|
||||
* Use _ in constants over 4 bits (eg: 8'h1100_1100)
|
||||
* One module per file
|
||||
* Use ".vh" suffix for header files,
|
||||
* yse ".v" for verilog source files
|
||||
* Use ".v" for verilog source files
|
||||
* Use `include files for constants
|
||||
* Use `ifndef _CONSTANTS_V to include file only once
|
||||
* No timescales in design files (only in testbench)
|
||||
@ -138,6 +140,7 @@ TBD
|
||||
* Avoid redundant resets
|
||||
* Avoid heavily nested if, else statements
|
||||
* Don't use defparams, place #(.DW(DW)) in module instantation
|
||||
* With parameters, NEVER us this instantiation: "mux3 #(32) U2 (...)"
|
||||
* Always use connection by name (not by order) in module instantiatoin
|
||||
* Parametrize as much as possible but not more
|
||||
* Place a useful comment every 5-20 lines
|
||||
@ -149,6 +152,7 @@ TBD
|
||||
* Don't use proprietary EDA tool pragmas (use parameters)
|
||||
* Only use synthesizable constructs
|
||||
* Use $signed() for arithmetic operations on signed types
|
||||
.
|
||||
* Allowed keywords: assign, always, input, output, wire, reg, module, endmodule, if/else, case, casez, ~,|,&,^,==, >>, <<, >, <,?,posedge, negedge, generate, for(...), begin, end, $signed,
|
||||
|
||||
|
||||
@ -174,16 +178,9 @@ TBD
|
||||
* Show how to synthesize/build..
|
||||
* Show how to use..
|
||||
|
||||
## Design Checklist
|
||||
## Tapeout Checklist
|
||||
|
||||
* Is the block datasheet complete and accurate?
|
||||
* Is there a user guide?
|
||||
* Is there a script/make file for building/testing the design?
|
||||
* Is there a self testing testbench?
|
||||
* Is there an auotomated synthesis script?
|
||||
* Is the driver written?
|
||||
* Is there a demo example?
|
||||
* Is the the block Silicon and FPGA validated?
|
||||
* [HERE](docs/tapeout_checklist.md)
|
||||
|
||||
## Recommended Reading
|
||||
|
||||
|
@ -35,6 +35,8 @@ A list of some basic equations and constants I have found useful in my life as a
|
||||
| Line capacitance / mm (max density) | (highly variable!) |
|
||||
| Line resistance / mm (fat layer) | (copper, highly variable!) |
|
||||
|
||||
|
||||
|
||||
## Interconnects
|
||||
|
||||
| Rule | Value |
|
||||
|
@ -8,17 +8,23 @@
|
||||
| Specification | Answer |
|
||||
|--------------------------------------------|--------------------------------|
|
||||
| Is there a written specification? | |
|
||||
| Is the datasheet complete and accurate? | |
|
||||
| Is there a user guide? | |
|
||||
| What is the chip max power target? | |
|
||||
| What is the chip standby power target? | |
|
||||
| What is the chip yield target? | |
|
||||
| What is the chip cost target? | |
|
||||
| What is the max die size? | |
|
||||
| What is the maximum die size? | |
|
||||
| How many signal IOs? | |
|
||||
| What is the highest frequency IO? | |
|
||||
|
||||
| Design | Answer |
|
||||
|--------------------------------------------|--------------------------------|
|
||||
| In Verilog 2005 used? | |
|
||||
| Are all features implemented? | |
|
||||
| Are all issues closed? | |
|
||||
| Has design been through peer review? | |
|
||||
| Has a linter been run? | |
|
||||
| Is there zero use of 'casex'? | |
|
||||
| Were Latches used? (If so list) | |
|
||||
@ -39,7 +45,7 @@
|
||||
| Any floating inputs in design? | |
|
||||
| All power-gated signals isolated? | |
|
||||
| All voltage domain crossings levelshifted? | |
|
||||
|
||||
| Is Verilog 2005 used? | |
|
||||
|
||||
| Verification | Answer |
|
||||
|--------------------------------------------|--------------------------------|
|
||||
@ -49,10 +55,15 @@
|
||||
| >24hrs of random vectors? | |
|
||||
| Randomized clock frequencies? | |
|
||||
| Were all open issues closed? | |
|
||||
|
||||
| Were all features tested? | |
|
||||
| Simulator support for all features? | |
|
||||
| Was design emulated in an FPGA? | |
|
||||
| Was design validated with application SW? | |
|
||||
| Was formal equivalence run between HDL/GL? | |
|
||||
| Is the firmware written? | |
|
||||
| Is there a demo? | |
|
||||
|
||||
|
||||
| Timing | Answer |
|
||||
|--------------------------------------------|--------------------------------|
|
||||
@ -74,6 +85,8 @@
|
||||
| Clock | Answer |
|
||||
|--------------------------------------------|--------------------------------|
|
||||
| Percentage regs clock gated? | |
|
||||
| Integrated clock gating cells used? | |
|
||||
| Setup/hold verified on clock gating cells? | |
|
||||
| Clock tree insertion delay? | |
|
||||
| Clock tree local skew? | |
|
||||
| Clock tree global skew? | |
|
||||
@ -83,7 +96,6 @@
|
||||
| Use of oh_fifo_cdc on all CDCs? | |
|
||||
| Were custom CDCs used? (if so list) | |
|
||||
|
||||
|
||||
| Reset | Answer |
|
||||
|--------------------------------------------|--------------------------------|
|
||||
| Is reset active low used? | |
|
||||
@ -133,6 +145,12 @@
|
||||
|
||||
| Layout | Answer |
|
||||
|--------------------------------------------|--------------------------------|
|
||||
| Synthesis/PNR | Answer |
|
||||
|--------------------------------------------|--------------------------------|
|
||||
| Is the flow completely automated? | |
|
||||
| Was the correct/latest version of HDL used?| |
|
||||
| Are all EDA warnings/errors acceptable? | |
|
||||
| The number of warnings has bee minimized? | |
|
||||
| Was the correct/latest gate level used? | |
|
||||
| Are all EDA warnings/errors understood? | |
|
||||
| Are ECO/spare cells used? | |
|
||||
@ -150,6 +168,7 @@
|
||||
| Is the chip logo included | |
|
||||
| Have gds layer map been manually reviewed? | |
|
||||
| Has tapeout GDS been manually reviewed? | |
|
||||
| XOR check between foundry/design GDSIIs | |
|
||||
|
||||
| DFM | Answer |
|
||||
|--------------------------------------------|--------------------------------|
|
||||
@ -158,6 +177,7 @@
|
||||
| What is the percentage of double vias? | |
|
||||
| Is yield optimizing wire spreading used? | |
|
||||
| Does design include fault tolerance? | |
|
||||
| Does design meet metal density rules? | |
|
||||
|
||||
| Test | Answer |
|
||||
|--------------------------------------------|--------------------------------|
|
||||
@ -187,6 +207,10 @@
|
||||
| Design's lowest operating voltage? | |
|
||||
| What is the longest signal on the chip? | |
|
||||
| Is design sensitive to duty cycle shift? | |
|
||||
| What is the max duty-cycle distortion? | |
|
||||
| Does design meet EMI constraints? | |
|
||||
| ERC runset checks run on GDSII? | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -21,6 +21,7 @@ $OH_HOME/scripts/link.sh
|
||||
###############################
|
||||
iverilog -g2005\
|
||||
-DTARGET_SIM=1\
|
||||
-DCFG_ASIC=0\
|
||||
$DUT\
|
||||
$OH_HOME/symlinks/dv/dv_top.v\
|
||||
-y .\
|
||||
|
@ -1,50 +1,42 @@
|
||||
/* verilator lint_off STMTDLY */
|
||||
module dv_driver (/*AUTOARG*/
|
||||
// Outputs
|
||||
stim_access, stim_packet, stim_wait, stim_done,
|
||||
// Inputs
|
||||
clkin, clkout, nreset, start, coreid, dut_access, dut_packet,
|
||||
dut_wait
|
||||
module dv_driver #( parameter N = 1, // "N" packets wide
|
||||
parameter AW = 32, // address width
|
||||
parameter PW = 104, // packet width (derived)
|
||||
parameter IDW = 12, // id width
|
||||
parameter NAME = "none", // north, south etc
|
||||
parameter STIMS = 1, // number of stimulus
|
||||
parameter MAW = 16 // 64KB memory address width
|
||||
)
|
||||
(
|
||||
//control signals
|
||||
input clkin,
|
||||
input clkout,
|
||||
input nreset,
|
||||
input start, //starts test
|
||||
input [IDW-1:0] coreid, //everything has a coreid!
|
||||
//inputs for monitoring
|
||||
input [N-1:0] dut_access,
|
||||
input [N*PW-1:0] dut_packet,
|
||||
input [N-1:0] dut_wait,
|
||||
//stimulus to drive
|
||||
output [N-1:0] stim_access,
|
||||
output [N*PW-1:0] stim_packet,
|
||||
output [N-1:0] stim_wait,
|
||||
output stim_done
|
||||
);
|
||||
|
||||
//Parameters
|
||||
parameter N = 1; // "N" packets wide
|
||||
parameter AW = 32; // address width
|
||||
parameter IDW = 12; // id width
|
||||
parameter NAME = "none"; // north, south etc
|
||||
parameter STIMS = 1; // number of stimulus
|
||||
parameter MAW = 16; // 64KB memory address width
|
||||
localparam PW = 2*AW+40; // packet width (derived)
|
||||
|
||||
//Control signals
|
||||
input clkin;
|
||||
input clkout;
|
||||
input nreset;
|
||||
input start; //starts test
|
||||
input [IDW-1:0] coreid; //everything has a coreid!
|
||||
|
||||
//Inputs for monitoring
|
||||
input [N-1:0] dut_access;
|
||||
input [N*PW-1:0] dut_packet;
|
||||
input [N-1:0] dut_wait;
|
||||
|
||||
//Stimulus to drive
|
||||
output [N-1:0] stim_access;
|
||||
output [N*PW-1:0] stim_packet;
|
||||
output [N-1:0] stim_wait;
|
||||
output stim_done;
|
||||
|
||||
|
||||
//#############
|
||||
//LOCAL WIRES
|
||||
//#############
|
||||
reg [IDW-1:0] offset;
|
||||
wire [N*32-1:0] stim_count;
|
||||
wire [N-1:0] stim_vec_done;
|
||||
wire [N*IDW-1:0] coreid_array;
|
||||
reg [IDW-1:0] offset;
|
||||
|
||||
wire [N*PW-1:0] mem_packet_out;
|
||||
wire [N-1:0] mem_access_out;
|
||||
wire [N-1:0] mem_wait_out;
|
||||
|
||||
/*AUTOWIRE*/
|
||||
|
||||
//###########################################
|
||||
//STIMULUS
|
||||
//###########################################
|
||||
@ -126,6 +118,7 @@ module dv_driver (/*AUTOARG*/
|
||||
for(j=0;j<N;j=j+1) begin : mem
|
||||
ememory #(.NAME(NAME),
|
||||
.IDW(IDW),
|
||||
.PW(PW),
|
||||
.AW(AW)
|
||||
)
|
||||
ememory(// Outputs
|
||||
|
@ -53,6 +53,8 @@ module dv_top();
|
||||
.clk1 (clk1),
|
||||
.clk2 (clk2),
|
||||
.start (start),
|
||||
.vdd (vdd),
|
||||
.vss (vss),
|
||||
// Inputs
|
||||
.dut_active (dut_active),
|
||||
.stim_done (stim_done));
|
||||
|
@ -32,6 +32,8 @@ module oh_clockdiv
|
||||
reg clkout1_reg;
|
||||
reg clkout1_shift;
|
||||
reg [2:0] period;
|
||||
wire
|
||||
period_match;
|
||||
|
||||
//###########################################
|
||||
//# CHANGE DETECT (count 8 periods)
|
||||
|
@ -5,34 +5,40 @@
|
||||
//# License: MIT (see LICENSE file in OH! repository) #
|
||||
//#############################################################################
|
||||
|
||||
module oh_clockgate #(parameter DW = 1, // width of data
|
||||
parameter ASIC = 0 // use ASIC lib
|
||||
module oh_clockgate # (parameter ASIC = 0, // use ASIC lib
|
||||
parameter PROJ = "E5" // project name (used for IP selection)
|
||||
)
|
||||
(
|
||||
input nrst, // active low sync reset (synced to input clk)
|
||||
input clk, // clock input
|
||||
input se, // scan enable
|
||||
input [DW-1:0] en, // enable (from positive edge FF)
|
||||
output [DW-1:0] eclk// enabled clock output
|
||||
input te, // test enable enable
|
||||
input en, // enable (from positive edge FF)
|
||||
output eclk // enabled clock output
|
||||
);
|
||||
|
||||
generate
|
||||
if(ASIC)
|
||||
begin : asic
|
||||
asic_icg #(.PROJ(PROJ))
|
||||
asic_icg (.en(en),
|
||||
.te(te),
|
||||
.clk(clk),
|
||||
.eclk(eclk));
|
||||
end
|
||||
else
|
||||
begin : generic
|
||||
wire en_sh;
|
||||
wire en_sl;
|
||||
//Stable low/valid rising edge enable
|
||||
assign en_sl = en | te;
|
||||
|
||||
wire [DW-1:0] en_sh;
|
||||
wire [DW-1:0] en_sl;
|
||||
|
||||
//Turn on clock if in scan mode or if enabled
|
||||
assign en_sl[DW-1:0] = en[DW-1:0] |
|
||||
{(DW){se}} |
|
||||
{(DW){~nrst}};
|
||||
|
||||
//making signal stable
|
||||
oh_lat0 #(.DW(1)) lat0 (.out (en_sh[DW-1:0]),
|
||||
.in (en_sl[DW-1:0]),
|
||||
.clk (clk)
|
||||
);
|
||||
|
||||
assign eclk[DW-1:0] = {(DW){clk}} & en_sh[DW-1:0];
|
||||
//Stable high enable signal
|
||||
oh_lat0 lat0 (.out (en_sh),
|
||||
.in (en_sl),
|
||||
.clk (clk));
|
||||
|
||||
assign eclk = clk & en_sh;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule // oh_clockgate
|
||||
|
||||
|
32
src/common/hdl/oh_clockmux.v
Normal file
32
src/common/hdl/oh_clockmux.v
Normal file
@ -0,0 +1,32 @@
|
||||
//#############################################################################
|
||||
//# Function: One hot 4:1 mux for clocks #
|
||||
//#############################################################################
|
||||
//# Author: Andreas Olofsson #
|
||||
//# License: MIT (see LICENSE file in OH! repository) #
|
||||
//#############################################################################
|
||||
|
||||
module oh_clockmux #(parameter PROJ = "E5", // project name
|
||||
parameter ASIC = 0, // use ASIC lib
|
||||
parameter N = 1) // number of clock inputs
|
||||
(
|
||||
input [N-1:0] en, // one hot enable, valid rising edge wrt to its clock
|
||||
input [N-1:0] clkin,// free running input clocks
|
||||
output clkout
|
||||
);
|
||||
|
||||
wire [N-1:0] eclk;
|
||||
|
||||
//One clock gate per clock
|
||||
oh_clockgate #(.PROJ(PROJ),
|
||||
.ASIC(ASIC))
|
||||
i_clockgate [N-1:0] (.eclk (eclk[N-1:0]),
|
||||
.clk (clkin[N-1:0]),
|
||||
.te (1'b0), //do something about this>
|
||||
.en (en[N-1:0]));
|
||||
|
||||
//Or gated clocks together
|
||||
assign clkout = |(eclk[N-1:0]);
|
||||
|
||||
endmodule // oh_clockmux
|
||||
|
||||
|
@ -17,7 +17,7 @@ module oh_csa32 #(parameter DW = 1, // data width
|
||||
|
||||
generate
|
||||
if(ASIC)
|
||||
begin
|
||||
begin : asic
|
||||
asic_csa32 i_csa32[DW-1:0] (.s(s[DW-1:0]),
|
||||
.c(c[DW-1:0]),
|
||||
.in2(in2[DW-1:0]),
|
||||
@ -25,7 +25,7 @@ module oh_csa32 #(parameter DW = 1, // data width
|
||||
.in0(in0[DW-1:0]));
|
||||
end
|
||||
else
|
||||
begin
|
||||
begin : generic
|
||||
assign s[DW-1:0] = in0[DW-1:0] ^ in1[DW-1:0] ^ in2[DW-1:0];
|
||||
assign c[DW-1:0] = (in0[DW-1:0] & in1[DW-1:0]) |
|
||||
(in1[DW-1:0] & in2[DW-1:0]) |
|
||||
|
@ -5,52 +5,36 @@
|
||||
//# License: MIT (see LICENSE file in OH! repository) #
|
||||
//#############################################################################
|
||||
|
||||
module oh_dsync #(parameter DW = 1, // width of data
|
||||
parameter PS = 3, // mnumber of sync stages
|
||||
parameter ASIC = 0 // use asic library
|
||||
module oh_dsync #(parameter PS = 2, // number of sync stages
|
||||
parameter DELAY = 0, // random delay
|
||||
parameter ASIC = `CFG_ASIC // use asic library
|
||||
)
|
||||
(
|
||||
input clk, // clock
|
||||
input nreset, // clock
|
||||
input [DW-1:0] din, // input data
|
||||
output [DW-1:0] dout // synchronized data
|
||||
input din, // input data
|
||||
output dout // synchronized data
|
||||
);
|
||||
|
||||
generate
|
||||
if(ASIC)
|
||||
begin
|
||||
asic_dsync #(.DW(DW))
|
||||
asic_dsync(.clk(clk),
|
||||
begin : g0
|
||||
asic_dsync asic_dsync (.clk(clk),
|
||||
.nreset(nreset),
|
||||
.din(din[DW-1:0]),
|
||||
.dout(dout[DW-1:0]));
|
||||
.din(din),
|
||||
.dout(dout));
|
||||
end
|
||||
else
|
||||
begin
|
||||
reg [DW-1:0] sync_pipe[PS:0]; //extra cycle for DV
|
||||
genvar i;
|
||||
for(i=0;i<(PS+1);i=i+1)
|
||||
if(i==0)
|
||||
begin : g0
|
||||
reg [PS:0] sync_pipe;
|
||||
always @ (posedge clk or negedge nreset)
|
||||
if(!nreset)
|
||||
sync_pipe[0][DW-1:0] <= 'b0;
|
||||
sync_pipe[PS:0] <= 1'b0;
|
||||
else
|
||||
sync_pipe[0][DW-1:0] <= din[DW-1:0];
|
||||
else
|
||||
always @ (posedge clk or negedge nreset)
|
||||
if(!nreset)
|
||||
sync_pipe[i][DW-1:0] <= 'b0;
|
||||
else
|
||||
sync_pipe[i][DW-1:0] <= sync_pipe[i-1][DW-1:0];
|
||||
`ifdef TARGET_SIM
|
||||
// randomize sync delay based on value in per bit delay register
|
||||
// delay to be forced from testbench
|
||||
reg [DW-1:0] delay = 0;
|
||||
assign dout[DW-1:0] = (delay[DW-1:0] & sync_pipe[PS][DW-1:0]) | //extra cycle
|
||||
(~delay[DW-1:0] & sync_pipe[PS-1][DW-1:0]); //default
|
||||
`else
|
||||
assign dout[DW-1:0] = sync_pipe[PS-1][DW-1:0];
|
||||
`endif
|
||||
sync_pipe[PS:0] <= {sync_pipe[PS-1:0],din};
|
||||
// drive randomize delay from testbench
|
||||
assign dout = (DELAY & sync_pipe[PS]) | //extra cycle
|
||||
(~DELAY & sync_pipe[PS-1]); //default
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
@ -48,9 +48,28 @@ module oh_fifo_async # (parameter DW = 104, //FIFO width
|
||||
.din (din[DW-1:0]),
|
||||
.rd_en (rd_en));
|
||||
end
|
||||
else if(TARGET=="ASIC") begin : asic
|
||||
oh_fifo_generic #(.DEPTH(DEPTH),
|
||||
.DW(DW))
|
||||
fifo_generic (
|
||||
// Outputs
|
||||
.full (full),
|
||||
.prog_full (prog_full),
|
||||
.dout (dout[DW-1:0]),
|
||||
.empty (empty),
|
||||
.rd_count (rd_count[AW-1:0]),
|
||||
.wr_count (wr_count[AW-1:0]),
|
||||
// Inputs
|
||||
.nreset (nreset),
|
||||
.wr_clk (wr_clk),
|
||||
.rd_clk (rd_clk),
|
||||
.wr_en (wr_en),
|
||||
.din (din[DW-1:0]),
|
||||
.rd_en (rd_en));
|
||||
end
|
||||
else if (TARGET=="XILINX") begin : xilinx
|
||||
if((DW==104) & (DEPTH==32))
|
||||
begin
|
||||
begin : g104x32
|
||||
fifo_async_104x32
|
||||
fifo (
|
||||
// Outputs
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
module oh_fifo_cdc # (parameter DW = 104, //FIFO width
|
||||
parameter DEPTH = 32, //FIFO depth (entries)
|
||||
parameter TARGET = "GENERIC" //XILINX,ALTERA,GENERIC,ASIC
|
||||
parameter TARGET = "GENERIC" //XILINX,ALTERA,GENERIC
|
||||
)
|
||||
(
|
||||
input nreset, // shared domain async active low reset
|
||||
@ -16,7 +16,7 @@ module oh_fifo_cdc # (parameter DW = 104, //FIFO width
|
||||
input [DW-1:0] packet_in, // write packet
|
||||
output wait_out, // write pushback
|
||||
input clk_out, //read clock
|
||||
output access_out, //read access
|
||||
output reg access_out, //read access
|
||||
output [DW-1:0] packet_out, //read packet
|
||||
input wait_in, // read pushback
|
||||
output prog_full, // fifo is half full
|
||||
@ -24,8 +24,8 @@ module oh_fifo_cdc # (parameter DW = 104, //FIFO width
|
||||
output empty // fifo is empty
|
||||
);
|
||||
|
||||
// local variables
|
||||
reg access_out;
|
||||
wire wr_en;
|
||||
wire rd_en;
|
||||
|
||||
// FIFO control logic
|
||||
assign wr_en = access_in;
|
||||
|
@ -28,6 +28,8 @@ module oh_fifo_generic #(parameter DW = 104, // FIFO width
|
||||
output [AW-1:0] wr_count // NOT IMPLEMENTED
|
||||
);
|
||||
|
||||
localparam ASIC = `CFG_ASIC;
|
||||
|
||||
//regs
|
||||
reg [AW:0] wr_addr; // extra bit for wraparound comparison
|
||||
reg [AW:0] wr_addr_ahead; // extra bit for wraparound comparison
|
||||
@ -38,7 +40,8 @@ module oh_fifo_generic #(parameter DW = 104, // FIFO width
|
||||
wire [AW:0] wr_addr_gray_sync;
|
||||
wire [AW:0] rd_addr_sync;
|
||||
wire [AW:0] wr_addr_sync;
|
||||
|
||||
wire wr_nreset;
|
||||
wire rd_nreset;
|
||||
|
||||
//###########################
|
||||
//# Full/empty indicators
|
||||
@ -64,11 +67,13 @@ module oh_fifo_generic #(parameter DW = 104, // FIFO width
|
||||
//# Reset synchronizers
|
||||
//###########################
|
||||
|
||||
oh_rsync wr_rsync (.nrst_out (wr_nreset),
|
||||
oh_rsync #(.ASIC(ASIC))
|
||||
wr_rsync (.nrst_out (wr_nreset),
|
||||
.clk (wr_clk),
|
||||
.nrst_in (nreset));
|
||||
|
||||
oh_rsync rd_rsync (.nrst_out (rd_nreset),
|
||||
oh_rsync #(.ASIC(ASIC))
|
||||
rd_rsync (.nrst_out (rd_nreset),
|
||||
.clk (rd_clk),
|
||||
.nrst_in (nreset));
|
||||
|
||||
@ -99,8 +104,7 @@ module oh_fifo_generic #(parameter DW = 104, // FIFO width
|
||||
.in (wr_addr[AW:0]));
|
||||
|
||||
// synchronize to read clock
|
||||
oh_dsync #(.DW(AW+1))
|
||||
wr_sync(.dout (wr_addr_gray_sync[AW:0]),
|
||||
oh_dsync wr_sync[AW:0] (.dout (wr_addr_gray_sync[AW:0]),
|
||||
.clk (rd_clk),
|
||||
.nreset(rd_nreset),
|
||||
.din (wr_addr_gray[AW:0]));
|
||||
@ -125,8 +129,7 @@ module oh_fifo_generic #(parameter DW = 104, // FIFO width
|
||||
.in (rd_addr[AW:0]));
|
||||
|
||||
//synchronize to wr clock
|
||||
oh_dsync #(.DW(AW+1))
|
||||
rd_sync(.dout (rd_addr_gray_sync[AW:0]),
|
||||
oh_dsync rd_sync[AW:0] (.dout (rd_addr_gray_sync[AW:0]),
|
||||
.clk (wr_clk),
|
||||
.nreset (wr_nreset),
|
||||
.din (rd_addr_gray[AW:0]));
|
||||
|
@ -20,12 +20,13 @@ module oh_fifo_sync #(parameter DW = 104, //FIFO width
|
||||
output full, // fifo full
|
||||
output prog_full, // fifo is almost full
|
||||
output empty, // fifo is empty
|
||||
output [AW-1:0] rd_count // valid entries in fifo
|
||||
output reg [AW-1:0] rd_count // valid entries in fifo
|
||||
);
|
||||
|
||||
reg [AW-1:0] wr_addr;
|
||||
reg [AW-1:0] rd_addr;
|
||||
reg [AW-1:0] rd_count;
|
||||
wire fifo_read;
|
||||
wire fifo_write;
|
||||
|
||||
assign empty = (rd_count[AW-1:0] == 0);
|
||||
assign prog_full = (rd_count[AW-1:0] >= PROG_FULL);
|
||||
|
@ -11,15 +11,13 @@ module oh_iddr #(parameter DW = 1 // width of data inputs
|
||||
input clk, // clock
|
||||
input ce, // clock enable, set to high to clock in data
|
||||
input [DW-1:0] din, // data input sampled on both edges of clock
|
||||
output [DW-1:0] q1, // iddr rising edge sampled data
|
||||
output [DW-1:0] q2 // iddr falling edge sampled data
|
||||
output reg [DW-1:0] q1, // iddr rising edge sampled data
|
||||
output reg [DW-1:0] q2 // iddr falling edge sampled data
|
||||
);
|
||||
|
||||
//regs("sl"=stable low, "sh"=stable high)
|
||||
reg [DW-1:0] q1_sl;
|
||||
reg [DW-1:0] q2_sh;
|
||||
reg [DW-1:0] q1;
|
||||
reg [DW-1:0] q2;
|
||||
|
||||
// rising edge sample
|
||||
always @ (posedge clk)
|
||||
|
@ -8,10 +8,9 @@
|
||||
module oh_lat0 #(parameter DW = 1) // data width
|
||||
( input clk, // clk, latch when clk=0
|
||||
input [DW-1:0] in, // input data
|
||||
output [DW-1:0] out // output data (stable/latched when clk=1)
|
||||
output reg [DW-1:0] out // output data (stable/latched when clk=1)
|
||||
);
|
||||
|
||||
reg [DW-1:0] out;
|
||||
always @ (clk or in)
|
||||
if (!clk)
|
||||
out[DW-1:0] <= in[DW-1:0];
|
||||
|
@ -1,21 +1,33 @@
|
||||
//#############################################################################
|
||||
//# Function: Latch data when clk=1 #
|
||||
//# Function: Achive high latch #
|
||||
//#############################################################################
|
||||
//# Author: Andreas Olofsson #
|
||||
//# License: MIT (see LICENSE file in OH! repository) #
|
||||
//#############################################################################
|
||||
|
||||
module oh_lat1 #(parameter DW = 1) // data width
|
||||
module oh_lat1 #(parameter DW = 1, //data width
|
||||
parameter ASIC = 0 // use ASIC lib
|
||||
)
|
||||
( input clk, // clk, latch when clk=1
|
||||
input [DW-1:0] in, // input data
|
||||
output [DW-1:0] out // output data (stable/latched when clk=0)
|
||||
);
|
||||
|
||||
reg [DW-1:0] out;
|
||||
generate
|
||||
if(ASIC)
|
||||
begin : g0
|
||||
asic_lat1 i_lat [DW-1:0] (.clk(clk),
|
||||
.in(in[DW-1:0]),
|
||||
.out(out[DW-1:0]));
|
||||
end
|
||||
else
|
||||
begin : g0
|
||||
reg [DW-1:0] out_reg;
|
||||
always @ (clk or in)
|
||||
if (clk)
|
||||
out[DW-1:0] <= in[DW-1:0];
|
||||
out_reg[DW-1:0] <= in[DW-1:0];
|
||||
assign out[DW-1:0] = out_reg[DW-1:0];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule // oh_lat1
|
||||
|
||||
|
||||
|
@ -39,10 +39,10 @@ module oh_memory_dp # (parameter DW = 104, //memory width
|
||||
|
||||
generate
|
||||
if(ASIC)
|
||||
begin
|
||||
begin : asic
|
||||
oh_memory_ram #(.DW(DW),
|
||||
.DEPTH(DEPTH))
|
||||
i_sram (//read port
|
||||
memory_dp (//read port
|
||||
.rd_dout (rd_dout[DW-1:0]),
|
||||
.rd_clk (rd_clk),
|
||||
.rd_en (rd_en),
|
||||
@ -55,10 +55,10 @@ module oh_memory_dp # (parameter DW = 104, //memory width
|
||||
.wr_din (wr_din[DW-1:0]));
|
||||
end // if (ASIC)
|
||||
else
|
||||
begin
|
||||
begin : generic
|
||||
oh_memory_ram #(.DW(DW),
|
||||
.DEPTH(DEPTH))
|
||||
oh_memory_ram (//read port
|
||||
memory_dp (//read port
|
||||
.rd_dout (rd_dout[DW-1:0]),
|
||||
.rd_clk (rd_clk),
|
||||
.rd_en (rd_en),
|
||||
@ -72,8 +72,6 @@ module oh_memory_dp # (parameter DW = 104, //memory width
|
||||
end // else: !if(ASIC)
|
||||
endgenerate
|
||||
|
||||
|
||||
|
||||
endmodule // oh_memory_dp
|
||||
|
||||
|
||||
|
@ -6,13 +6,14 @@
|
||||
//#############################################################################
|
||||
|
||||
module oh_memory_ram # (parameter DW = 104, //memory width
|
||||
parameter DEPTH = 32 //memory depth
|
||||
parameter DEPTH = 32, //memory depth
|
||||
parameter AW = $clog2(DEPTH) // address width
|
||||
)
|
||||
(// read-port
|
||||
input rd_clk,// rd clock
|
||||
input rd_en, // memory access
|
||||
input [AW-1:0] rd_addr, // address
|
||||
output [DW-1:0] rd_dout, // data output
|
||||
output reg [DW-1:0] rd_dout, // data output
|
||||
// write-port
|
||||
input wr_clk,// wr clock
|
||||
input wr_en, // memory access
|
||||
@ -21,10 +22,7 @@ module oh_memory_ram # (parameter DW = 104, //memory width
|
||||
input [DW-1:0] wr_din // data input
|
||||
);
|
||||
|
||||
parameter AW = $clog2(DEPTH); // address bus width
|
||||
|
||||
reg [DW-1:0] ram [DEPTH-1:0];
|
||||
reg [DW-1:0] rd_dout;
|
||||
integer i;
|
||||
|
||||
//registered read port
|
||||
|
@ -1,5 +1,5 @@
|
||||
//#############################################################################
|
||||
//# Function: Sinle Port Memory #
|
||||
//# Function: Single Port Memory #
|
||||
//#############################################################################
|
||||
//# Author: Andreas Olofsson #
|
||||
//# License: MIT (see LICENSE file in OH! repository) #
|
||||
@ -9,7 +9,8 @@ module oh_memory_sp # (parameter DW = 104, // memory width
|
||||
parameter DEPTH = 32, // memory depth
|
||||
parameter PROJ = "", // project name
|
||||
parameter ASIC = 0, // use ASIC lib
|
||||
parameter MCW = 8 // repair/config vector width
|
||||
parameter MCW = 8, // repair/config width
|
||||
parameter AW = $clog2(DEPTH) // address bus width
|
||||
)
|
||||
(// memory interface (single port)
|
||||
input clk, // clock
|
||||
@ -34,16 +35,16 @@ module oh_memory_sp # (parameter DW = 104, // memory width
|
||||
input [DW-1:0] bist_din // data input
|
||||
);
|
||||
|
||||
parameter AW = $clog2(DEPTH); // address bus width
|
||||
|
||||
|
||||
generate
|
||||
if(ASIC)
|
||||
begin
|
||||
begin : g0
|
||||
asic_sram_sp #(.DW(DW),
|
||||
.DEPTH(DEPTH),
|
||||
.PROJ(PROJ),
|
||||
.MCW(MCW))
|
||||
i_sram (// Outputs
|
||||
sram_sp (// Outputs
|
||||
.dout (dout[DW-1:0]),
|
||||
// Inputs
|
||||
.clk (clk),
|
||||
@ -65,10 +66,10 @@ module oh_memory_sp # (parameter DW = 104, // memory width
|
||||
.bist_din (bist_din[DW-1:0]));
|
||||
end
|
||||
else
|
||||
begin
|
||||
begin : g0
|
||||
oh_memory_ram #(.DW(DW),
|
||||
.DEPTH(DEPTH))
|
||||
oh_memory_ram (//read port
|
||||
sram_sp (//read port
|
||||
.rd_dout (dout[DW-1:0]),
|
||||
.rd_clk (clk),
|
||||
.rd_addr (addr[AW-1:0]),
|
||||
|
@ -6,7 +6,8 @@
|
||||
//#############################################################################
|
||||
|
||||
module oh_par2ser #(parameter PW = 64, // parallel packet width
|
||||
parameter SW = 1 // serial packet width
|
||||
parameter SW = 1, // serial packet width
|
||||
parameter CW = $clog2(PW/SW) // serialization factor
|
||||
)
|
||||
(
|
||||
input clk, // sampling clock
|
||||
@ -23,11 +24,11 @@ module oh_par2ser #(parameter PW = 64, // parallel packet width
|
||||
output wait_out // wait output (wait in | serial wait)
|
||||
);
|
||||
|
||||
// parameters
|
||||
parameter CW = $clog2(PW/SW); // serialization factor (for counter)
|
||||
|
||||
// local wires
|
||||
reg [PW-1:0] shiftreg;
|
||||
reg [CW-1:0] count;
|
||||
wire start_transfer;
|
||||
wire busy;
|
||||
|
||||
// start serialization
|
||||
assign start_transfer = load & ~wait_in & ~busy;
|
||||
|
@ -28,7 +28,7 @@ module oh_pulse2pulse (
|
||||
toggle_reg <= toggle;
|
||||
|
||||
//metastability synchronizer
|
||||
oh_dsync #(1) sync(.dout (toggle_sync),
|
||||
oh_dsync sync(.dout (toggle_sync),
|
||||
.din (toggle),
|
||||
.nreset (nrstout),
|
||||
.clk (clkout));
|
||||
|
@ -18,7 +18,7 @@ module oh_pwr_gate #(parameter ASIC = 0 // use ASIC lib
|
||||
`else
|
||||
generate
|
||||
if(ASIC)
|
||||
begin
|
||||
begin : asic
|
||||
asic_pwr_header i_header (.npower(npower),
|
||||
.vdd(vdd),
|
||||
.vddg(vddg));
|
||||
|
@ -23,14 +23,13 @@ module oh_pwr_isolate #(parameter DW = 1, // width of data inputs
|
||||
`else
|
||||
generate
|
||||
if(ASIC)
|
||||
begin
|
||||
asic_iso i_iso [DW-1:0] (.vdd(vdd),
|
||||
.vss(vss),
|
||||
begin : asic
|
||||
asic_iso i_iso [DW-1:0] (.niso(niso),
|
||||
.in(in[DW-1:0]),
|
||||
.out(out[DW-1:0]));
|
||||
end
|
||||
else
|
||||
begin
|
||||
begin : generic
|
||||
assign out[DW-1:0] = {(DW){niso}} & in[DW-1:0];
|
||||
end
|
||||
endgenerate
|
||||
|
@ -5,22 +5,32 @@
|
||||
//# License: MIT (see LICENSE file in OH! repository) #
|
||||
//#############################################################################
|
||||
|
||||
module oh_rsync #(parameter PS =2) // number of sync stages
|
||||
module oh_rsync #(parameter PS = 2, // number of sync stages
|
||||
parameter ASIC = `CFG_ASIC // use asic library
|
||||
)
|
||||
(
|
||||
input clk,
|
||||
input nrst_in,
|
||||
output nrst_out
|
||||
);
|
||||
|
||||
generate
|
||||
if(ASIC)
|
||||
begin : g0
|
||||
asic_rsync asic_rsync (.clk(clk),
|
||||
.nrst_in(nrst_in),
|
||||
.nrst_out(nrst_out));
|
||||
end
|
||||
else
|
||||
begin :g0
|
||||
reg [PS-1:0] sync_pipe;
|
||||
|
||||
always @ (posedge clk or negedge nrst_in)
|
||||
if(!nrst_in)
|
||||
sync_pipe[PS-1:0] <= 1'b0;
|
||||
else
|
||||
sync_pipe[PS-1:0] <= {sync_pipe[PS-2:0],1'b1};
|
||||
|
||||
assign nrst_out = sync_pipe[PS-1];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule // oh_rsync
|
||||
|
||||
|
@ -6,19 +6,17 @@
|
||||
//#############################################################################
|
||||
|
||||
module oh_ser2par #(parameter PW = 64, // parallel packet width
|
||||
parameter SW = 1 // serial packet width
|
||||
parameter SW = 1, // serial packet width
|
||||
parameter CW = $clog2(PW/SW) // serialization factor (for counter)
|
||||
)
|
||||
(
|
||||
input clk, // sampling clock
|
||||
input [SW-1:0] din, // serial data
|
||||
output [PW-1:0] dout, // parallel data
|
||||
output reg [PW-1:0] dout, // parallel data
|
||||
input lsbfirst, // lsb first order
|
||||
input shift // shift the shifter
|
||||
);
|
||||
|
||||
parameter CW = $clog2(PW/SW); // serialization factor (for counter)
|
||||
|
||||
reg [PW-1:0] dout;
|
||||
reg [CW-1:0] count;
|
||||
wire [PW-1:0] shiftdata;
|
||||
|
||||
|
@ -5,11 +5,14 @@
|
||||
//# License: MIT (see LICENSE file in OH! repository) #
|
||||
//#############################################################################
|
||||
|
||||
module oh_standby #( parameter PD = 5) //cycles to stay awake after "wakeup"
|
||||
module oh_standby #( parameter PD = 5, // cycles to stay awake after "wakeup"
|
||||
parameter ASIC = 1, // use ASIC lib
|
||||
parameter N = 5, // number of wake up signals
|
||||
parameter PROJ = "") // project name
|
||||
(
|
||||
input clkin, //clock input
|
||||
input nreset, //sync reset
|
||||
input wakeup, //wake up now!
|
||||
input nreset,//async active low reset
|
||||
input [N-1:0] wakeup, //wake up event vector
|
||||
input idle, //core is in idle
|
||||
output clkout //clock output
|
||||
);
|
||||
@ -17,28 +20,36 @@ module oh_standby #( parameter PD = 5) //cycles to stay awake after "wakeup"
|
||||
//Wire declarations
|
||||
reg [PD-1:0] wakeup_pipe;
|
||||
reg idle_reg;
|
||||
wire state_change;
|
||||
wire clk_en;
|
||||
wire [N-1:0] wakeup_pulse;
|
||||
wire wakeup_now;
|
||||
|
||||
// detect an idle state change (wake up on any)
|
||||
always @ (posedge clk )
|
||||
idle_reg <= idle;
|
||||
assign state_change = (idle ^ idle_reg);
|
||||
// Wake up on any external event change
|
||||
oh_edge2pulse #(.DW(N))
|
||||
oh_edge2pulse (.out (wakeup_pulse[N-1:0]),
|
||||
.clk (clkin),
|
||||
.nreset (nreset),
|
||||
.in (wakeup[N-1:0]));
|
||||
|
||||
always @ (posedge clk)
|
||||
wakeup_pipe[PD-1:0] <= {wakeup_pipe[PD-2:0],(state_change | wakeup)};
|
||||
assign wakeup_now = |(wakeup_pulse[N-1:0]);
|
||||
|
||||
//block enable signal
|
||||
assign clk_en = ~nreset | //always on during reset
|
||||
wakeup | //immediate wakeup
|
||||
state_change | //incoming transition
|
||||
// Stay away for PD cycles
|
||||
always @ (posedge clkin)
|
||||
wakeup_pipe[PD-1:0] <= {wakeup_pipe[PD-2:0], wakeup_now};
|
||||
|
||||
// Clock enable
|
||||
assign clk_en = wakeup_now | //immediate wakeup
|
||||
(|wakeup_pipe[PD-1:0]) | //anything in pipe
|
||||
~idle; //core not in idle
|
||||
|
||||
//clock gater (technology specific)
|
||||
oh_clockgate clockgate (.eclk(clkout),
|
||||
.clk(clk),
|
||||
// Clock gating cell
|
||||
oh_clockgate #(.PROJ(PROJ),
|
||||
.ASIC(ASIC))
|
||||
oh_clockgate (.eclk(clkout),
|
||||
.clk(clkin),
|
||||
.en(clk_en),
|
||||
.nrst(nreset),
|
||||
.se(1'b0));
|
||||
.te(1'b0));
|
||||
|
||||
endmodule // oh_standby
|
||||
|
||||
|
26
src/common/hdl/oh_tristate.v
Normal file
26
src/common/hdl/oh_tristate.v
Normal file
@ -0,0 +1,26 @@
|
||||
//#############################################################################
|
||||
//# Function: Bidirectional port with output-enable #
|
||||
//#############################################################################
|
||||
//# Author: Ola Jeppsson #
|
||||
//# SPDX-License-Identifier: MIT #
|
||||
//#############################################################################
|
||||
|
||||
module oh_tristate #(parameter N = 1) // width of port
|
||||
(
|
||||
inout [N-1:0] io, // bidirectional port
|
||||
input [N-1:0] oe, // output enable (1 = output, 0 = input)
|
||||
output [N-1:0] in, // port as input
|
||||
input [N-1:0] out // port as output
|
||||
);
|
||||
|
||||
assign in[N-1:0] = io[N-1:0];
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i < N; i = i + 1)
|
||||
begin : gen_oh_tristate
|
||||
assign io[i] = oe[i] ? out[i] : 1'bZ;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule // oh_tristate
|
@ -4,57 +4,38 @@
|
||||
//# Author: Andreas Olofsson #
|
||||
//# License: MIT (see below) #
|
||||
//#############################################################################
|
||||
module edma (/*AUTOARG*/
|
||||
// Outputs
|
||||
irq, wait_out, access_out, packet_out, reg_wait_out,
|
||||
reg_access_out, reg_packet_out,
|
||||
// Inputs
|
||||
vdd, vss, clk, nreset, access_in, packet_in, wait_in,
|
||||
reg_access_in, reg_packet_in, reg_wait_in
|
||||
module edma #( parameter AW = 32, // address width
|
||||
parameter PW = 104 // packet width
|
||||
)
|
||||
(
|
||||
// power
|
||||
input vdd, // supply
|
||||
input vss, // common ground
|
||||
// reset, clk, config
|
||||
input clk, // main core clock
|
||||
input nreset, // async active low reset
|
||||
output irq, // interrupt output
|
||||
// datapath interface
|
||||
input access_in, // streaming input access
|
||||
input [PW-1:0] packet_in, // streaming input data
|
||||
output wait_out, // pushback
|
||||
output access_out, // output access (master/slave)
|
||||
output [PW-1:0] packet_out, // output packet (with address)
|
||||
input wait_in, // pushback
|
||||
// config/fetch interface
|
||||
input reg_access_in, // config register access
|
||||
input [PW-1:0] reg_packet_in, // config register packet
|
||||
output reg_wait_out, // pushback by register read
|
||||
output reg_access_out,// config readback
|
||||
output [PW-1:0] reg_packet_out,// config reacback packet
|
||||
input reg_wait_in // pushback for readback
|
||||
);
|
||||
|
||||
//#####################################################################
|
||||
//# INTERFACE
|
||||
//#####################################################################
|
||||
|
||||
//parameters
|
||||
parameter AW = 32; // address width
|
||||
localparam PW = 2*AW+40; // emesh packet width
|
||||
|
||||
// power
|
||||
input vdd; // supply
|
||||
input vss; // common ground
|
||||
|
||||
// reset, clk, config
|
||||
input clk; // main core clock
|
||||
input nreset; // async active low reset
|
||||
output irq; // interrupt output
|
||||
|
||||
// datapath interface
|
||||
input access_in; // streaming input access
|
||||
input [PW-1:0] packet_in; // streaming input data
|
||||
output wait_out; // pushback
|
||||
|
||||
output access_out; // output access (master/slave)
|
||||
output [PW-1:0] packet_out; // output packet (with address)
|
||||
input wait_in; // pushback
|
||||
|
||||
// config/fetch interface
|
||||
input reg_access_in; // config register access
|
||||
input [PW-1:0] reg_packet_in; // config register packet
|
||||
output reg_wait_out; // pushback by register read
|
||||
|
||||
output reg_access_out;// config readback
|
||||
output [PW-1:0] reg_packet_out;// config reacback packet
|
||||
input reg_wait_in; // pushback for readback
|
||||
|
||||
//#####################################################################
|
||||
//# BODY
|
||||
//#####################################################################
|
||||
|
||||
//###############
|
||||
//# LOCAL WIRES
|
||||
//###############
|
||||
/*AUTOOUTPUT*/
|
||||
/*AUTOINPUT*/
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
wire chainmode; // From edma_regs of edma_regs.v
|
||||
@ -84,7 +65,8 @@ module edma (/*AUTOARG*/
|
||||
//# DATAPATH
|
||||
//##########################
|
||||
|
||||
edma_dp #(.AW(AW))
|
||||
edma_dp #(.AW(AW),
|
||||
.PW(PW))
|
||||
edma_dp(/*AUTOINST*/
|
||||
// Outputs
|
||||
.count (count[31:0]),
|
||||
@ -112,7 +94,8 @@ module edma (/*AUTOARG*/
|
||||
//# CONFIG REGISTERS
|
||||
//##########################
|
||||
|
||||
edma_regs #(.AW(AW))
|
||||
edma_regs #(.AW(AW),
|
||||
.PW(PW))
|
||||
edma_regs (/*AUTOINST*/
|
||||
// Outputs
|
||||
.reg_wait_out (reg_wait_out),
|
||||
@ -149,7 +132,8 @@ module edma (/*AUTOARG*/
|
||||
//# STATE MACHINE
|
||||
//##########################
|
||||
|
||||
edma_ctrl #(.AW(AW))
|
||||
edma_ctrl #(.AW(AW),
|
||||
.PW(PW))
|
||||
edma_ctrl (/*AUTOINST*/
|
||||
// Outputs
|
||||
.fetch_access (fetch_access),
|
||||
|
@ -16,7 +16,7 @@ module edma_ctrl (/*AUTOARG*/
|
||||
);
|
||||
|
||||
parameter AW = 32; // address width
|
||||
localparam PW = 2*AW+40; // fetch packet width
|
||||
parameter PW = 2*AW+40; // fetch packet width
|
||||
parameter ID = 4'b0000; // group id for DMA regs [10:8]
|
||||
|
||||
// clk, reset, config
|
||||
@ -54,6 +54,9 @@ module edma_ctrl (/*AUTOARG*/
|
||||
wire [15:0] fetch_addr;
|
||||
wire [AW-1:0] srcaddr_out;
|
||||
wire [4:0] reg_addr;
|
||||
wire dma_error;
|
||||
wire incount_zero;
|
||||
wire outcount_zero;
|
||||
|
||||
//###########################################
|
||||
//# STATE MACHINE
|
||||
@ -167,7 +170,8 @@ module edma_ctrl (/*AUTOARG*/
|
||||
2'b0}; //1-0
|
||||
|
||||
// constructing fetch packet
|
||||
emesh2packet #(.AW(AW))
|
||||
emesh2packet #(.AW(AW),
|
||||
.PW(PW))
|
||||
e2p (//outputs
|
||||
.packet_out (fetch_packet[PW-1:0]),
|
||||
//inputs
|
||||
|
@ -14,7 +14,7 @@ module edma_dp (/*AUTOARG*/
|
||||
);
|
||||
|
||||
parameter AW = 8; // divider counter width
|
||||
localparam PW = 2*AW+40; // emesh packet width
|
||||
parameter PW = 2*AW+40; // emesh packet width
|
||||
|
||||
// clk, reset, config
|
||||
input clk; // main clock
|
||||
@ -99,7 +99,8 @@ module edma_dp (/*AUTOARG*/
|
||||
//################################
|
||||
|
||||
// parsing input packet
|
||||
packet2emesh #(.AW(AW))
|
||||
packet2emesh #(.AW(AW),
|
||||
.PW(PW))
|
||||
p2e (/*AUTOINST*/
|
||||
// Outputs
|
||||
.write_in (write_in),
|
||||
@ -121,7 +122,8 @@ module edma_dp (/*AUTOARG*/
|
||||
assign srcaddr_out[AW-1:0] = master_active ? {(AW){1'b0}} : srcaddr_in[31:0];
|
||||
|
||||
// constructing output packet
|
||||
emesh2packet #(.AW(AW))
|
||||
emesh2packet #(.AW(AW),
|
||||
.PW(PW))
|
||||
e2p (.packet_out (packet[PW-1:0]),
|
||||
/*AUTOINST*/
|
||||
// Inputs
|
||||
|
@ -19,7 +19,7 @@ module edma_regs (/*AUTOARG*/
|
||||
|
||||
// parameters
|
||||
parameter AW = 8; // address width
|
||||
localparam PW = 2*AW+40; // emesh packet width
|
||||
parameter PW = 2*AW+40; // emesh packet width
|
||||
parameter DEF_CFG = 0; // default config after reset
|
||||
|
||||
// clk, reset
|
||||
@ -79,12 +79,16 @@ module edma_regs (/*AUTOARG*/
|
||||
reg [31:0] status_reg;
|
||||
|
||||
// wires
|
||||
wire [4:0] ctrlmode_out;
|
||||
wire [AW-1:0] data_out;
|
||||
wire [1:0] datamode_out;
|
||||
wire [AW-1:0] dstaddr_out;
|
||||
wire [AW-1:0] srcaddr_out;
|
||||
wire write_out;
|
||||
wire reg_write;
|
||||
wire config_write;
|
||||
wire stride_write;
|
||||
wire count_write;
|
||||
wire srcaddr0_write;
|
||||
wire srcaddr1_write;
|
||||
wire dstaddr0_write;
|
||||
wire dstaddr1_write;
|
||||
wire status_write;
|
||||
wire irqmode;
|
||||
|
||||
/*AUTOINPUT*/
|
||||
/*AUTOWIRE*/
|
||||
@ -101,7 +105,8 @@ module edma_regs (/*AUTOARG*/
|
||||
//# DECODE
|
||||
//################################
|
||||
|
||||
packet2emesh #(.AW(AW))
|
||||
packet2emesh #(.AW(AW),
|
||||
.PW(PW))
|
||||
p2e (.packet_in (reg_packet_in[PW-1:0]),
|
||||
/*AUTOINST*/
|
||||
// Outputs
|
||||
|
@ -143,8 +143,7 @@ module etx_cfg (/*AUTOARG*/
|
||||
//###########################
|
||||
|
||||
//Synchronize to make easy regular
|
||||
oh_dsync #(.DW(16))
|
||||
dsync (.dout (tx_status_sync[15:0]),
|
||||
oh_dsync isync[15:0] (.dout (tx_status_sync[15:0]),
|
||||
.clk (clk),
|
||||
.nreset (1'b1),
|
||||
.din (tx_status[15:0]));
|
||||
|
@ -1,37 +1,34 @@
|
||||
|
||||
module ememory(/*AUTOARG*/
|
||||
// Outputs
|
||||
wait_out, access_out, packet_out,
|
||||
// Inputs
|
||||
clk, nreset, coreid, access_in, packet_in, wait_in
|
||||
module ememory # (parameter AW = 32, // address width
|
||||
parameter PW = 104, // packet width
|
||||
parameter IDW = 12, // ID width
|
||||
parameter DEPTH = 65536, // memory depth
|
||||
parameter NAME = "emem", // instance name
|
||||
parameter WAIT = 0, // enable random wait
|
||||
parameter MON = 0 // enable monitor monitor
|
||||
)
|
||||
|
||||
(// clk,reset
|
||||
input clk,
|
||||
input nreset,
|
||||
input [IDW-1:0] coreid,
|
||||
// incoming read/write
|
||||
input access_in,
|
||||
input [PW-1:0] packet_in,
|
||||
output wait_out, //pushback
|
||||
// back to mesh (readback data)
|
||||
output reg access_out,
|
||||
output [PW-1:0] packet_out,
|
||||
input wait_in //pushback
|
||||
);
|
||||
|
||||
parameter AW = 32;
|
||||
parameter IDW = 12;
|
||||
parameter DEPTH = 65536;
|
||||
parameter MAW = $clog2(DEPTH);
|
||||
parameter NAME = "emem";
|
||||
parameter WAIT = 0; //turns on random wait circuit
|
||||
parameter MON = 0; //turns on monitor
|
||||
|
||||
//derived parameters
|
||||
localparam DW = AW; //always the same
|
||||
localparam PW = 2*AW+40;//packet width
|
||||
parameter MAW = $clog2(DEPTH);
|
||||
|
||||
//Basic Interface
|
||||
input clk;
|
||||
input nreset;
|
||||
input [IDW-1:0] coreid;
|
||||
|
||||
//incoming read/write
|
||||
input access_in;
|
||||
input [PW-1:0] packet_in;
|
||||
output wait_out; //pushback
|
||||
|
||||
//back to mesh (readback data)
|
||||
output access_out;
|
||||
output [PW-1:0] packet_out;
|
||||
input wait_in; //pushback
|
||||
//###############
|
||||
//# LOCAL WIRES
|
||||
//##############
|
||||
|
||||
wire [MAW-1:0] addr;
|
||||
wire [63:0] din;
|
||||
@ -39,39 +36,40 @@ module ememory(/*AUTOARG*/
|
||||
wire en;
|
||||
wire mem_rd;
|
||||
reg [7:0] wen;
|
||||
|
||||
//State
|
||||
reg access_out;
|
||||
reg write_out;
|
||||
reg [1:0] datamode_out;
|
||||
reg [4:0] ctrlmode_out;
|
||||
reg [AW-1:0] dstaddr_out;
|
||||
|
||||
wire [AW-1:0] srcaddr_out;
|
||||
wire [AW-1:0] data_out;
|
||||
reg [2:0] align_addr;
|
||||
|
||||
wire write_in;
|
||||
wire [1:0] datamode_in;
|
||||
wire [4:0] ctrlmode_in;
|
||||
wire [AW-1:0] dstaddr_in;
|
||||
wire [DW-1:0] data_in;
|
||||
wire [AW-1:0] srcaddr_in;
|
||||
wire [DW-1:0] din_aligned;
|
||||
wire [63:0] dout_aligned;
|
||||
wire wait_random; //TODO: make random
|
||||
wire wait_all;
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
wire [4:0] ctrlmode_in; // From p2e of packet2emesh.v
|
||||
wire [AW-1:0] data_in; // From p2e of packet2emesh.v
|
||||
wire [1:0] datamode_in; // From p2e of packet2emesh.v
|
||||
wire [AW-1:0] dstaddr_in; // From p2e of packet2emesh.v
|
||||
wire [AW-1:0] srcaddr_in; // From p2e of packet2emesh.v
|
||||
wire write_in; // From p2e of packet2emesh.v
|
||||
// End of automatics
|
||||
|
||||
packet2emesh #(.AW(AW))
|
||||
p2e (
|
||||
packet2emesh #(.AW(AW),
|
||||
.PW(PW))
|
||||
p2e (/*AUTOINST*/
|
||||
// Outputs
|
||||
.write_in (write_in),
|
||||
.datamode_in (datamode_in[1:0]),
|
||||
.ctrlmode_in (ctrlmode_in[4:0]),
|
||||
.dstaddr_in (dstaddr_in[AW-1:0]),
|
||||
.data_in (data_in[DW-1:0]),
|
||||
.srcaddr_in (srcaddr_in[AW-1:0]),
|
||||
.packet_in (packet_in[PW-1:0])
|
||||
);
|
||||
.data_in (data_in[AW-1:0]),
|
||||
// Inputs
|
||||
.packet_in (packet_in[PW-1:0]));
|
||||
|
||||
|
||||
//Access-in
|
||||
assign en = access_in & ~wait_all & ~wait_all;
|
||||
@ -178,7 +176,8 @@ module ememory(/*AUTOARG*/
|
||||
assign data_out[31:0] = dout_aligned[31:0];
|
||||
|
||||
//Concatenate
|
||||
emesh2packet #(.AW(AW))
|
||||
emesh2packet #(.AW(AW),
|
||||
.PW(PW))
|
||||
e2p (
|
||||
/*AUTOINST*/
|
||||
// Outputs
|
||||
|
@ -1,71 +1,67 @@
|
||||
/*
|
||||
* ---- 32-BIT ADDRESS ----
|
||||
* [1] write bit
|
||||
* [2:1] datamode
|
||||
* [6:3] ctrlmode
|
||||
* [7] RESERVED
|
||||
* [39:8] f0 = dstaddr(lo)
|
||||
* [71:40] f1 = data (lo)
|
||||
* [103:72] f2 = srcaddr(lo) / data (hi)
|
||||
*
|
||||
* ---- 64-BIT ADDRESS ----
|
||||
* [0] write bit
|
||||
* [2:1] datamode
|
||||
* [7:3] ctrlmode
|
||||
* [39:8] f0 = dstaddr(lo)
|
||||
* [71:40] f1 = D0
|
||||
* [103:72] f2 = D1 | srcaddr(lo)
|
||||
* [135:104] f3 = D2 | srcaddr(hi)
|
||||
* [167:136] f4 = D3 | dstaddr(hi)
|
||||
*
|
||||
*/
|
||||
module emesh2packet(/*AUTOARG*/
|
||||
// Outputs
|
||||
packet_out,
|
||||
// Inputs
|
||||
write_out, datamode_out, ctrlmode_out, dstaddr_out, data_out,
|
||||
srcaddr_out
|
||||
);
|
||||
parameter AW = 32;
|
||||
parameter PW = 2*AW+40;
|
||||
|
||||
//#############################################################################
|
||||
//# Function: Maps Emesh Signals to Packet #
|
||||
//#############################################################################
|
||||
//# Author: Andreas Olofsson #
|
||||
//# License: MIT (see LICENSE file in OH! repository) #
|
||||
//#############################################################################
|
||||
module emesh2packet #(parameter AW = 32, // address width
|
||||
parameter PW = 104) // packet width
|
||||
(
|
||||
//Emesh signal bundle
|
||||
input write_out;
|
||||
input [1:0] datamode_out;
|
||||
input [4:0] ctrlmode_out;
|
||||
input [AW-1:0] dstaddr_out;
|
||||
input [AW-1:0] data_out;
|
||||
input [AW-1:0] srcaddr_out;
|
||||
|
||||
input write_out,
|
||||
input [1:0] datamode_out,
|
||||
input [4:0] ctrlmode_out,
|
||||
input [AW-1:0] dstaddr_out,
|
||||
input [AW-1:0] data_out,
|
||||
input [AW-1:0] srcaddr_out,
|
||||
//Output packet
|
||||
output [PW-1:0] packet_out;
|
||||
output [PW-1:0] packet_out
|
||||
);
|
||||
|
||||
// ---- FORMAT -----
|
||||
//
|
||||
// [0] =write bit
|
||||
// [2:1]=datamode
|
||||
// [7:3]=ctrlmode
|
||||
// [39:8]=dstaddr(lo)
|
||||
//
|
||||
// ---- 32-BIT ADDRESS ----
|
||||
// [71:40] data (lo) | xxxx
|
||||
// [103:72] srcaddr(lo) | data (hi)
|
||||
//
|
||||
// ---- 64-BIT ADDRESS ----
|
||||
// [71:40] D0 | srcaddr(hi)
|
||||
// [103:72] D1 | srcaddr(lo)
|
||||
// [135:104] dstaddr(hi)
|
||||
|
||||
assign packet_out[0] = write_out;
|
||||
assign packet_out[2:1] = datamode_out[1:0];
|
||||
assign packet_out[7:3] = ctrlmode_out[4:0];
|
||||
|
||||
generate
|
||||
if(AW==64)
|
||||
begin : packet64
|
||||
if(PW==136)
|
||||
begin : p136
|
||||
assign packet_out[39:8] = dstaddr_out[31:0];
|
||||
assign packet_out[71:40] = data_out[31:0];
|
||||
assign packet_out[103:72] = srcaddr_out[31:0];
|
||||
assign packet_out[135:104] = srcaddr_out[63:32];
|
||||
assign packet_out[167:136] = dstaddr_out[63:32];
|
||||
assign packet_out[71:40] = data_out[31:0]; // | srcaddr_out[63:32]
|
||||
assign packet_out[103:72] = srcaddr_out[31:0]; // (data_out[63:32])
|
||||
assign packet_out[135:104] = dstaddr_out[63:32];
|
||||
end
|
||||
else if(AW==32)
|
||||
begin : packet32
|
||||
else if(PW==104)
|
||||
begin : p104
|
||||
assign packet_out[39:8] = dstaddr_out[31:0];
|
||||
assign packet_out[71:40] = data_out[31:0];
|
||||
assign packet_out[103:72] = srcaddr_out[31:0];
|
||||
end
|
||||
else if(AW==16)
|
||||
begin : packet16
|
||||
else if(PW==72)
|
||||
begin : p72
|
||||
assign packet_out[39:8] = dstaddr_out[31:0];
|
||||
assign packet_out[71:40] = data_out[31:0];
|
||||
end
|
||||
else if(PW==40)
|
||||
begin : p40
|
||||
assign packet_out[23:8] = dstaddr_out[15:0];
|
||||
assign packet_out[39:24] = data_out[15:0];
|
||||
assign packet_out[55:40] = srcaddr_out[15:0];
|
||||
end
|
||||
|
||||
endgenerate
|
||||
|
||||
endmodule // emesh2packet
|
||||
|
@ -5,7 +5,7 @@ module emesh_readback (/*AUTOARG*/
|
||||
nreset, clk, access_in, packet_in, read_data, wait_in
|
||||
);
|
||||
parameter AW = 32; // address width
|
||||
localparam PW = 2*AW+40; // packet width
|
||||
parameter PW = 104; // packet width
|
||||
|
||||
//clk, reset
|
||||
input nreset; // asynchronous active low reset
|
||||
@ -45,7 +45,8 @@ module emesh_readback (/*AUTOARG*/
|
||||
//# Parse packet
|
||||
//#######################################
|
||||
|
||||
packet2emesh #(.AW(AW))
|
||||
packet2emesh #(.AW(AW),
|
||||
.PW(PW))
|
||||
p2e (/*AUTOINST*/
|
||||
// Outputs
|
||||
.write_in (write_in),
|
||||
@ -87,7 +88,8 @@ module emesh_readback (/*AUTOARG*/
|
||||
//# Convert to Packet
|
||||
//#######################################
|
||||
|
||||
emesh2packet #(.AW(AW))
|
||||
emesh2packet #(.AW(AW),
|
||||
.PW(PW))
|
||||
e2p (.write_out (1'b1),
|
||||
/*AUTOINST*/
|
||||
// Outputs
|
||||
|
@ -1,49 +1,42 @@
|
||||
/*
|
||||
* ---- 32-BIT ADDRESS ----
|
||||
* [1] write bit
|
||||
* [2:1] datamode
|
||||
* [6:3] ctrlmode
|
||||
* [7] RESERVED
|
||||
* [39:8] f0 = dstaddr(lo)
|
||||
* [71:40] f1 = data (lo)
|
||||
* [103:72] f2 = srcaddr(lo) / data (hi)
|
||||
*
|
||||
* ---- 64-BIT ADDRESS ----
|
||||
* [0] write bit
|
||||
* [2:1] datamode
|
||||
* [7:3] ctrlmode
|
||||
* [39:8] f0 = dstaddr(lo)
|
||||
* [71:40] f1 = D0
|
||||
* [103:72] f2 = D1 | srcaddr(lo)
|
||||
* [135:104] f3 = D2 | srcaddr(hi)
|
||||
* [167:136] f4 = D3 | dstaddr(hi)
|
||||
*
|
||||
*/
|
||||
module packet2emesh(/*AUTOARG*/
|
||||
// Outputs
|
||||
write_in, datamode_in, ctrlmode_in, dstaddr_in, srcaddr_in,
|
||||
data_in,
|
||||
// Inputs
|
||||
packet_in
|
||||
//#############################################################################
|
||||
//# Function: Maps Packet to Emesh Signals #
|
||||
//#############################################################################
|
||||
//# Author: Andreas Olofsson #
|
||||
//# License: MIT (see LICENSE file in OH! repository) #
|
||||
//#############################################################################
|
||||
module packet2emesh #(parameter AW = 32, // address width
|
||||
parameter PW = 104) // packet width
|
||||
(
|
||||
//Input packet
|
||||
input [PW-1:0] packet_in,
|
||||
//Emesh signal bundle
|
||||
output write_in, // write signal
|
||||
output [1:0] datamode_in,// datasize
|
||||
output [4:0] ctrlmode_in,// ctrlmode
|
||||
output [AW-1:0] dstaddr_in, // read/write address
|
||||
output [AW-1:0] srcaddr_in, // return address for reads
|
||||
output [AW-1:0] data_in // data
|
||||
);
|
||||
|
||||
parameter AW = 32;
|
||||
parameter PW = (2*AW+40);
|
||||
|
||||
//Input packet
|
||||
input [PW-1:0] packet_in;
|
||||
|
||||
//Emesh signal bundle
|
||||
output write_in;
|
||||
output [1:0] datamode_in;
|
||||
output [4:0] ctrlmode_in;
|
||||
output [AW-1:0] dstaddr_in;
|
||||
output [AW-1:0] srcaddr_in;
|
||||
output [AW-1:0] data_in;
|
||||
// ---- FORMAT -----
|
||||
//
|
||||
// [0] =write bit
|
||||
// [2:1]=datamode
|
||||
// [7:3]=ctrlmode
|
||||
// [39:8]=dstaddr(lo)
|
||||
//
|
||||
// ---- 32-BIT ADDRESS ----
|
||||
// [71:40] data (lo) | xxxx
|
||||
// [103:72] srcaddr(lo) | data (hi)
|
||||
//
|
||||
// ---- 64-BIT ADDRESS ----
|
||||
// [71:40] D0 | srcaddr(hi)
|
||||
// [103:72] D1 | srcaddr(lo)
|
||||
// [135:104] dstaddr(hi)
|
||||
|
||||
generate
|
||||
if(AW==32)
|
||||
begin : packet32
|
||||
if(PW==104)
|
||||
begin : p104
|
||||
assign write_in = packet_in[0];
|
||||
assign datamode_in[1:0] = packet_in[2:1];
|
||||
assign ctrlmode_in[4:0] = {1'b0,packet_in[6:3]};
|
||||
@ -51,15 +44,31 @@ module packet2emesh(/*AUTOARG*/
|
||||
assign srcaddr_in[31:0] = packet_in[103:72];
|
||||
assign data_in[31:0] = packet_in[71:40];
|
||||
end
|
||||
else if(AW==64)
|
||||
begin : packet64
|
||||
else if(PW==136)
|
||||
begin : p136
|
||||
assign write_in = packet_in[0];
|
||||
assign datamode_in[1:0] = packet_in[2:1];
|
||||
assign ctrlmode_in[4:0] = packet_in[7:3];
|
||||
assign dstaddr_in[63:0] = {packet_in[167:135],packet_in[39:8]};
|
||||
assign srcaddr_in[63:0] = packet_in[135:72];
|
||||
assign dstaddr_in[63:0] = {packet_in[135:104],packet_in[39:8]};
|
||||
assign srcaddr_in[63:0] = {packet_in[71:40],packet_in[135:72]};
|
||||
assign data_in[63:0] = packet_in[103:40];
|
||||
end
|
||||
else if(PW==72)
|
||||
begin : p72
|
||||
assign write_in = packet_in[0];
|
||||
assign datamode_in[1:0] = packet_in[2:1];
|
||||
assign ctrlmode_in[4:0] = packet_in[7:3];
|
||||
assign dstaddr_in[31:0] = packet_in[39:8];
|
||||
assign data_in[31:0] = packet_in[71:40];
|
||||
end
|
||||
else if(PW==40)
|
||||
begin : p40
|
||||
assign write_in = packet_in[0];
|
||||
assign datamode_in[1:0] = packet_in[2:1];
|
||||
assign ctrlmode_in[4:0] = packet_in[7:3];
|
||||
assign dstaddr_in[15:0] = packet_in[23:8];
|
||||
assign data_in[15:0] = packet_in[39:24];
|
||||
end
|
||||
else
|
||||
begin : unknown
|
||||
`ifdef TARGET_SIM
|
||||
|
@ -164,14 +164,11 @@ module etrace (/*AUTOARG*/
|
||||
//# SYNC CFG SIGNALS TO SAMPLE CLK
|
||||
//#################################
|
||||
|
||||
dsync #(.DW(1))
|
||||
|
||||
dsync(// Outputs
|
||||
dsync dsync(// Outputs
|
||||
.dout (trace_enable),
|
||||
// Inputs
|
||||
.clk (trace_clk),
|
||||
.din (mi_trace_enable)
|
||||
);
|
||||
.din (mi_trace_enable));
|
||||
|
||||
//###########################
|
||||
//# TIME KEEPER
|
||||
|
@ -19,7 +19,7 @@ GPIO: General Purpose Software Programmable IO
|
||||
| GPIO_OUTSET | 0x4 | WR | n/a | Output = output "or" value |
|
||||
| GPIO_OUTXOR | 0x5 | WR | n/a | Output = output ^ value |
|
||||
| GPIO_IMASK | 0x6 | WR | H | Interrupt mask (1=mask) |
|
||||
| GPIO_ITYPE | 0x7 | WR | n/a | IRQ type (1=edge,0=level) |
|
||||
| GPIO_ITYPE | 0x7 | WR | n/a | IRQ type (0=edge,1=level) |
|
||||
| GPIO_IPOL | 0x8 | WR | H | IRQ polarity (1=rising edge/high)|
|
||||
| GPIO_ILAT | 0x9 | RD | L | IRQ Status (1=latched irq) |
|
||||
| GPIO_ILATCLR | 0xA | WR | n/a | Clears ILAT(1=clear) |
|
||||
|
@ -0,0 +1,35 @@
|
||||
OH GPIO controller bindings
|
||||
|
||||
Required properties:
|
||||
- compatible: "oh,gpio"
|
||||
- reg: Address and length of the register set for the device
|
||||
- interrupt-parent: phandle of the parent interrupt controller.
|
||||
- interrupts : Should be the port interrupt shared by all 32 pins.
|
||||
- gpio-controller : Marks the device node as a GPIO controller.
|
||||
- #gpio-cells : Should be two.
|
||||
- first cell is the pin number
|
||||
- second cell is used to specify optional parameters (unused)
|
||||
- interrupt-controller: Mark the device node as an interrupt controller.
|
||||
- #interrupt-cells : Should be 2.
|
||||
The first cell is the GPIO number.
|
||||
The second cell is used to specify flags:
|
||||
bits[3:0] trigger type and level flags:
|
||||
1 = rising edge triggered.
|
||||
2 = falling edge triggered.
|
||||
4 = active high level-sensitive.
|
||||
8 = active low level-sensitive.
|
||||
- ngpios: number of GPIOs this controller has
|
||||
|
||||
Example:
|
||||
|
||||
gpio0: gpio0 {
|
||||
compatible = "oh,gpio";
|
||||
reg = <0xe000a000 0x1000>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <57>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
ngpios = <24>;
|
||||
};
|
1
src/gpio/driver/linux/Kbuild
Normal file
1
src/gpio/driver/linux/Kbuild
Normal file
@ -0,0 +1 @@
|
||||
obj-m := gpio-oh.o
|
14
src/gpio/driver/linux/Makefile
Normal file
14
src/gpio/driver/linux/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
# kbuild part of makefile
|
||||
obj-y := gpio-oh.o
|
||||
else
|
||||
# normal makefile
|
||||
KDIR ?= /lib/modules/`uname -r`/build
|
||||
|
||||
default:
|
||||
$(MAKE) -C $(KDIR) M=$$PWD
|
||||
|
||||
clean:
|
||||
rm -fr gpio-oh.mod.c *.o *.ko .*.cmd modules.order Module.symvers .tmp_versions
|
||||
|
||||
endif
|
28
src/gpio/driver/linux/README.md
Normal file
28
src/gpio/driver/linux/README.md
Normal file
@ -0,0 +1,28 @@
|
||||
# OH GPIO Linux Kernel driver
|
||||
|
||||
## Compilation
|
||||
|
||||
### Against system kernel sources
|
||||
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
### Custom source path
|
||||
|
||||
```
|
||||
make KDIR=path/to/src/linux
|
||||
```
|
||||
|
||||
### Cross compiling (example w/ custom build-dir)
|
||||
|
||||
```
|
||||
make -C path/to/built/linux-builddir \
|
||||
M=`pwd` \
|
||||
ARCH=arm \
|
||||
CROSS_COMPILE=arm-linux-gnueabihf- \
|
||||
LOADADDR=0x8000
|
||||
```
|
||||
|
||||
For more flags etc, see:
|
||||
https://www.kernel.org/doc/Documentation/kbuild/modules.txt
|
503
src/gpio/driver/linux/gpio-oh.c
Normal file
503
src/gpio/driver/linux/gpio-oh.c
Normal file
@ -0,0 +1,503 @@
|
||||
/*
|
||||
* Open Hardware GPIO device driver
|
||||
*
|
||||
* Copyright (C) 2016 Parallella Foundation
|
||||
* Written by Ola Jeppsson <ola@adapteva.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in the
|
||||
* file called COPYING.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#define DRIVERNAME "oh-gpio"
|
||||
|
||||
#define OH_GPIO_MAX_NR_GPIOS 64
|
||||
|
||||
#define OH_GPIO_DIR 0x00 /* set direction of pin */
|
||||
#define OH_GPIO_IN 0x08 /* input data (read only) */
|
||||
#define OH_GPIO_OUT 0x10 /* output data (write only) */
|
||||
#define OH_GPIO_OUTCLR 0x18 /* alias, clears specific bits in GPIO_OUT */
|
||||
#define OH_GPIO_OUTSET 0x20 /* alias, sets specific bits in GPIO_OUT */
|
||||
#define OH_GPIO_OUTXOR 0x28 /* alias, toggles specific bits in GPIO_OUT */
|
||||
#define OH_GPIO_IMASK 0x30 /* interrupt mask */
|
||||
#define OH_GPIO_ITYPE 0x38 /* interrupt type (edge=0/level=1) */
|
||||
#define OH_GPIO_IPOL 0x40 /* interrupt polarity (hi/rising / low/falling) */
|
||||
#define OH_GPIO_ILAT 0x48 /* latched interrupts (read only) */
|
||||
#define OH_GPIO_ILATCLR 0x50 /* clear an interrupt */
|
||||
|
||||
struct oh_gpio {
|
||||
void __iomem *base_addr;
|
||||
struct gpio_chip chip;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
static struct oh_gpio *to_oh_gpio(struct gpio_chip *gpio)
|
||||
{
|
||||
return container_of(gpio, struct oh_gpio, chip);
|
||||
}
|
||||
|
||||
#ifdef writeq
|
||||
#define oh_gpio_writeq writeq
|
||||
#else
|
||||
static inline void oh_gpio_writeq(u64 value, void __iomem *addr)
|
||||
{
|
||||
writel((u32) (value & 0xffffffff), addr);
|
||||
writel((u32) (value >> 32), (u8 __iomem *) addr + 4);
|
||||
}
|
||||
#endif
|
||||
#ifdef readq
|
||||
#define oh_gpio_readq readq
|
||||
#else
|
||||
static inline u64 oh_gpio_readq(void __iomem *addr)
|
||||
{
|
||||
u64 lo, hi;
|
||||
|
||||
lo = readl(addr);
|
||||
hi = readl((u8 __iomem *) addr + 4);
|
||||
|
||||
return (hi << 32 | lo);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void oh_gpio_reg_write(u64 value, struct oh_gpio *gpio,
|
||||
unsigned long offset)
|
||||
{
|
||||
if (gpio->chip.ngpio > 32)
|
||||
oh_gpio_writeq(value, (u8 __iomem *) gpio->base_addr + offset);
|
||||
else
|
||||
writel((u32) value, (u8 __iomem *) gpio->base_addr + offset);
|
||||
}
|
||||
|
||||
static inline u64 oh_gpio_reg_read(struct oh_gpio *gpio, unsigned long offset)
|
||||
{
|
||||
if (gpio->chip.ngpio > 32)
|
||||
return oh_gpio_readq((u8 __iomem *) gpio->base_addr + offset);
|
||||
else
|
||||
return (u64) readl((u8 __iomem *) gpio->base_addr + offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* oh_gpio_get_value - Get value of the specified pin
|
||||
* @chip: gpio chip device
|
||||
* @pin: gpio pin number
|
||||
*
|
||||
* Return: 0 if the pin is low, 1 if pin is high.
|
||||
*/
|
||||
static int oh_gpio_get_value(struct gpio_chip *chip, unsigned pin)
|
||||
{
|
||||
u64 data;
|
||||
unsigned long flags;
|
||||
struct oh_gpio *gpio = to_oh_gpio(chip);
|
||||
|
||||
spin_lock_irqsave(&gpio->lock, flags);
|
||||
data = oh_gpio_reg_read(gpio, OH_GPIO_IN);
|
||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||
|
||||
return (data >> pin) & 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* oh_gpio_set_value - Assign output value for pin
|
||||
* @chip: gpio chip device
|
||||
* @pin: gpio pin number
|
||||
* @value: value used to modify the state of the specified pin
|
||||
*/
|
||||
static void oh_gpio_set_value(struct gpio_chip *chip, unsigned pin, int value)
|
||||
{
|
||||
u64 mask;
|
||||
unsigned long flags;
|
||||
struct oh_gpio *gpio = to_oh_gpio(chip);
|
||||
|
||||
mask = BIT_ULL(pin);
|
||||
|
||||
spin_lock_irqsave(&gpio->lock, flags);
|
||||
if (value)
|
||||
oh_gpio_reg_write(mask, gpio, OH_GPIO_OUTSET);
|
||||
else
|
||||
oh_gpio_reg_write(mask, gpio, OH_GPIO_OUTCLR);
|
||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* oh_gpio_get_direction - Get direction of pin
|
||||
* @chip: gpio chip device
|
||||
* @pin: gpio pin number
|
||||
*
|
||||
* Return: direction of pin, 0=out, 1=in
|
||||
*/
|
||||
static int oh_gpio_get_direction(struct gpio_chip *chip, unsigned pin)
|
||||
{
|
||||
u64 dir;
|
||||
unsigned long flags;
|
||||
struct oh_gpio *gpio = to_oh_gpio(chip);
|
||||
|
||||
spin_lock_irqsave(&gpio->lock, flags);
|
||||
dir = oh_gpio_reg_read(gpio, OH_GPIO_DIR);
|
||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||
|
||||
return !((dir >> pin) & 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* oh_gpio_direction_in - Set the direction of the specified GPIO pin as input
|
||||
* @chip: gpio chip device
|
||||
* @pin: gpio pin number
|
||||
*
|
||||
* Return: 0 always
|
||||
*/
|
||||
static int oh_gpio_direction_in(struct gpio_chip *chip, unsigned pin)
|
||||
{
|
||||
u64 mask, dir;
|
||||
unsigned long flags;
|
||||
struct oh_gpio *gpio = to_oh_gpio(chip);
|
||||
|
||||
mask = BIT_ULL(pin);
|
||||
|
||||
spin_lock_irqsave(&gpio->lock, flags);
|
||||
dir = oh_gpio_reg_read(gpio, OH_GPIO_DIR);
|
||||
dir &= ~mask;
|
||||
oh_gpio_reg_write(dir, gpio, OH_GPIO_DIR);
|
||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* oh_gpio_direction_out - Set the direction of the specified GPIO pin as output
|
||||
* @chip: gpio chip device
|
||||
* @pin: gpio pin number
|
||||
* @value: value to be written to pin
|
||||
*
|
||||
* This function sets the direction of specified GPIO pin as output, and uses
|
||||
* oh_gpio_set to set the specified pin value.
|
||||
*
|
||||
* Return: 0 always
|
||||
*/
|
||||
static int oh_gpio_direction_out(struct gpio_chip *chip, unsigned pin,
|
||||
int value)
|
||||
{
|
||||
u64 mask, dir;
|
||||
unsigned long flags;
|
||||
struct oh_gpio *gpio = to_oh_gpio(chip);
|
||||
|
||||
mask = BIT_ULL(pin);
|
||||
|
||||
spin_lock_irqsave(&gpio->lock, flags);
|
||||
dir = oh_gpio_reg_read(gpio, OH_GPIO_DIR);
|
||||
dir |= mask;
|
||||
oh_gpio_reg_write(dir, gpio, OH_GPIO_DIR);
|
||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||
|
||||
oh_gpio_set_value(chip, pin, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* oh_gpio_irq_mask - Disable interrupts for a gpio pin
|
||||
* @irq_data: per irq and chip data passed down to chip functions
|
||||
*
|
||||
*/
|
||||
static void oh_gpio_irq_mask(struct irq_data *irq_data)
|
||||
{
|
||||
u64 imask;
|
||||
unsigned long flags;
|
||||
unsigned pin;
|
||||
struct oh_gpio *gpio = to_oh_gpio(irq_data_get_irq_chip_data(irq_data));
|
||||
|
||||
pin = irq_data->hwirq;
|
||||
|
||||
spin_lock_irqsave(&gpio->lock, flags);
|
||||
imask = oh_gpio_reg_read(gpio, OH_GPIO_IMASK);
|
||||
imask |= BIT_ULL(pin);
|
||||
oh_gpio_reg_write(imask, gpio, OH_GPIO_IMASK);
|
||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* oh_gpio_irq_unmask - Enable interrupts for a gpio pin
|
||||
* @irq_data: irq data containing irq number of gpio pin for the interrupt
|
||||
* to enable
|
||||
*/
|
||||
static void oh_gpio_irq_unmask(struct irq_data *irq_data)
|
||||
{
|
||||
u64 imask;
|
||||
unsigned long flags;
|
||||
unsigned pin;
|
||||
struct oh_gpio *gpio = to_oh_gpio(irq_data_get_irq_chip_data(irq_data));
|
||||
|
||||
pin = irq_data->hwirq;
|
||||
|
||||
spin_lock_irqsave(&gpio->lock, flags);
|
||||
imask = oh_gpio_reg_read(gpio, OH_GPIO_IMASK);
|
||||
imask &= ~BIT_ULL(pin);
|
||||
oh_gpio_reg_write(imask, gpio, OH_GPIO_IMASK);
|
||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* oh_gpio_irq_ack - Clear interrupt latch of a gpio pin
|
||||
* @irq_data: irq data containing irq number of gpio pin for the interrupt
|
||||
* to clear
|
||||
*/
|
||||
static void oh_gpio_irq_ack(struct irq_data *irq_data)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned pin;
|
||||
struct oh_gpio *gpio = to_oh_gpio(irq_data_get_irq_chip_data(irq_data));
|
||||
|
||||
pin = irq_data->hwirq;
|
||||
|
||||
spin_lock_irqsave(&gpio->lock, flags);
|
||||
oh_gpio_reg_write(BIT_ULL(pin), gpio, OH_GPIO_ILATCLR);
|
||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* oh_gpio_irq_set_type - Set the irq type for a gpio pin
|
||||
* @irq_data: irq data containing irq number of gpio pin
|
||||
* @type: interrupt type that is to be set for the gpio pin
|
||||
*
|
||||
* Return: 0 on success, negative on error.
|
||||
*/
|
||||
static int oh_gpio_irq_set_type(struct irq_data *irq_data, unsigned type)
|
||||
{
|
||||
u64 itype, ipol, mask;
|
||||
unsigned pin;
|
||||
unsigned long flags;
|
||||
irq_flow_handler_t handler;
|
||||
struct oh_gpio *gpio = to_oh_gpio(irq_data_get_irq_chip_data(irq_data));
|
||||
|
||||
pin = irq_data->hwirq;
|
||||
mask = BIT_ULL(pin);
|
||||
|
||||
spin_lock_irqsave(&gpio->lock, flags);
|
||||
|
||||
itype = oh_gpio_reg_read(gpio, OH_GPIO_ITYPE);
|
||||
ipol = oh_gpio_reg_read(gpio, OH_GPIO_IPOL);
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
itype &= ~mask;
|
||||
ipol |= mask;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
itype &= ~mask;
|
||||
ipol &= ~mask;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
itype |= mask;
|
||||
ipol |= mask;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
itype |= mask;
|
||||
ipol &= ~mask;
|
||||
break;
|
||||
default:
|
||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
oh_gpio_reg_write(itype, gpio, OH_GPIO_ITYPE);
|
||||
oh_gpio_reg_write(ipol, gpio, OH_GPIO_IPOL);
|
||||
|
||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||
|
||||
handler = type & IRQ_TYPE_LEVEL_MASK ? handle_level_irq
|
||||
: handle_edge_irq;
|
||||
irq_set_handler_locked(irq_data, handler);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip oh_gpio_irqchip = {
|
||||
.name = DRIVERNAME,
|
||||
.irq_ack = oh_gpio_irq_ack,
|
||||
.irq_mask = oh_gpio_irq_mask,
|
||||
.irq_unmask = oh_gpio_irq_unmask,
|
||||
.irq_set_type = oh_gpio_irq_set_type,
|
||||
};
|
||||
|
||||
/**
|
||||
* oh_gpio_irq_handler - IRQ handler
|
||||
* @irq: oh_gpio irq number
|
||||
* @devid: pointer to oh_gpio struct
|
||||
*
|
||||
* Reads the interrupt latch register register to get the gpio pin number(s)
|
||||
* that have pending interrupts. It then calls the generic irq handlers for
|
||||
* those pins irqs.
|
||||
*
|
||||
* Return: IRQ_HANDLED if any interrupts were handled, IRQ_NONE otherwise.
|
||||
*/
|
||||
static irqreturn_t oh_gpio_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
u64 ilat;
|
||||
unsigned long flags, ilat_lo, ilat_hi;
|
||||
int offset;
|
||||
struct oh_gpio *gpio = dev_id;
|
||||
struct irq_domain *irqdomain = gpio->chip.irqdomain;
|
||||
|
||||
spin_lock_irqsave(&gpio->lock, flags);
|
||||
ilat = oh_gpio_reg_read(gpio, OH_GPIO_ILAT);
|
||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||
|
||||
if (!ilat)
|
||||
return IRQ_NONE;
|
||||
|
||||
/* No generic 64-bit for_each_set_bit. Need to split in high/low */
|
||||
ilat_lo = (unsigned long) ((ilat >> 0) & 0xffffffff);
|
||||
ilat_hi = (unsigned long) ((ilat >> 32) & 0xffffffff);
|
||||
|
||||
for_each_set_bit(offset, &ilat_lo, 32)
|
||||
generic_handle_irq(irq_find_mapping(irqdomain, offset));
|
||||
|
||||
for_each_set_bit(offset, &ilat_hi, 32)
|
||||
generic_handle_irq(irq_find_mapping(irqdomain, 32 + offset));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static const struct of_device_id oh_gpio_of_match[] = {
|
||||
{ .compatible = "oh,gpio" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, oh_gpio_of_match);
|
||||
|
||||
/**
|
||||
* oh_gpio_probe - Platform probe for a oh_gpio device
|
||||
* @pdev: platform device
|
||||
*
|
||||
* Note: All interrupts are cleared + masked after function exits.
|
||||
*
|
||||
* Return: 0 on success, negative error otherwise.
|
||||
*/
|
||||
static int oh_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret, irq;
|
||||
u32 ngpios;
|
||||
struct oh_gpio *gpio;
|
||||
struct gpio_chip *chip;
|
||||
struct resource *res;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
|
||||
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
|
||||
if (!gpio)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, gpio);
|
||||
|
||||
ret = of_property_read_u32(np, "ngpios", &ngpios);
|
||||
if (ret == -ENOENT) {
|
||||
dev_info(&pdev->dev,
|
||||
"ngpios property missing, defaulting to %u\n",
|
||||
OH_GPIO_MAX_NR_GPIOS);
|
||||
ngpios = OH_GPIO_MAX_NR_GPIOS;
|
||||
} else if (ret) {
|
||||
dev_err(&pdev->dev, "ngpios property is not valid\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ngpios > OH_GPIO_MAX_NR_GPIOS) {
|
||||
dev_err(&pdev->dev,
|
||||
"ngpios property is %u, max allowed is %u\n",
|
||||
(unsigned) ngpios, OH_GPIO_MAX_NR_GPIOS);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
gpio->base_addr = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(gpio->base_addr))
|
||||
return PTR_ERR(gpio->base_addr);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
dev_err(&pdev->dev, "invalid IRQ\n");
|
||||
return irq;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, irq, oh_gpio_irq_handler, 0,
|
||||
dev_name(&pdev->dev), gpio);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "could not request IRQ\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
spin_lock_init(&gpio->lock);
|
||||
|
||||
/* configure the gpio chip */
|
||||
chip = &gpio->chip;
|
||||
chip->label = "oh_gpio";
|
||||
chip->owner = THIS_MODULE;
|
||||
chip->dev = &pdev->dev;
|
||||
chip->base = -1;
|
||||
chip->ngpio = (u16) ngpios;
|
||||
chip->get = oh_gpio_get_value;
|
||||
chip->set = oh_gpio_set_value;
|
||||
chip->get_direction = oh_gpio_get_direction;
|
||||
chip->direction_input = oh_gpio_direction_in;
|
||||
chip->direction_output = oh_gpio_direction_out;
|
||||
|
||||
/* mask / clear all interrupts */
|
||||
oh_gpio_reg_write(~0ULL, gpio, OH_GPIO_IMASK);
|
||||
oh_gpio_reg_write(~0ULL, gpio, OH_GPIO_ILATCLR);
|
||||
|
||||
/* register gpio chip */
|
||||
ret = gpiochip_add(chip);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to add gpio chip\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpiochip_irqchip_add(chip, &oh_gpio_irqchip, 0,
|
||||
handle_level_irq, IRQ_TYPE_NONE);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to add irq chip\n");
|
||||
gpiochip_remove(chip);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* oh_gpio_remove - Driver removal function
|
||||
* @pdev: platform device
|
||||
*
|
||||
* Return: 0 always
|
||||
*/
|
||||
static int oh_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct oh_gpio *gpio = platform_get_drvdata(pdev);
|
||||
|
||||
gpiochip_remove(&gpio->chip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver oh_gpio_driver = {
|
||||
.driver = {
|
||||
.name = DRIVERNAME,
|
||||
.of_match_table = oh_gpio_of_match,
|
||||
},
|
||||
.probe = oh_gpio_probe,
|
||||
.remove = oh_gpio_remove,
|
||||
};
|
||||
module_platform_driver(oh_gpio_driver);
|
||||
|
||||
MODULE_AUTHOR("Ola Jeppsson <ola@adapteva.com>");
|
||||
MODULE_DESCRIPTION("OH GPIO driver");
|
||||
MODULE_VERSION("0.1");
|
||||
MODULE_LICENSE("GPL");
|
6
src/gpio/fpga/bit2bin.bif
Normal file
6
src/gpio/fpga/bit2bin.bif
Normal file
@ -0,0 +1,6 @@
|
||||
the_ROM_image:
|
||||
{
|
||||
[bootloader]dummy.elf
|
||||
./system.runs/impl_1/system_wrapper.bit
|
||||
}
|
||||
|
15
src/gpio/fpga/build.sh
Executable file
15
src/gpio/fpga/build.sh
Executable file
@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
#clean up
|
||||
rm system_wrapper.bit.bin bit2bin.bin
|
||||
|
||||
#package IP
|
||||
vivado -mode batch -source package.tcl
|
||||
|
||||
#create bit stream
|
||||
vivado -mode batch -source run.tcl
|
||||
|
||||
#xilinx stuff...
|
||||
bootgen -image bit2bin.bif -split bin
|
||||
cp system_wrapper.bit.bin parallella.bit.bin
|
||||
|
BIN
src/gpio/fpga/dummy.elf
Normal file
BIN
src/gpio/fpga/dummy.elf
Normal file
Binary file not shown.
23
src/gpio/fpga/ip_params.tcl
Normal file
23
src/gpio/fpga/ip_params.tcl
Normal file
@ -0,0 +1,23 @@
|
||||
# NOTE: See UG1118 for more information
|
||||
|
||||
set design parallella_gpio
|
||||
set projdir ./
|
||||
set root "../.."
|
||||
set partname "xc7z020clg400-1"
|
||||
|
||||
set hdl_files [list \
|
||||
$root/gpio/hdl \
|
||||
$root/common/hdl/ \
|
||||
$root/emesh/hdl \
|
||||
$root/emmu/hdl \
|
||||
$root/axi/hdl \
|
||||
$root/emailbox/hdl \
|
||||
$root/edma/hdl \
|
||||
$root/elink/hdl \
|
||||
$root/parallella/hdl \
|
||||
]
|
||||
|
||||
set ip_files []
|
||||
|
||||
set constraints_files []
|
||||
|
3
src/gpio/fpga/package.tcl
Normal file
3
src/gpio/fpga/package.tcl
Normal file
@ -0,0 +1,3 @@
|
||||
#STEP1: DEFINE KEY PARAMETERS
|
||||
source ./ip_params.tcl
|
||||
source ../../common/fpga/create_ip.tcl
|
12
src/gpio/fpga/run.tcl
Normal file
12
src/gpio/fpga/run.tcl
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
#STEP1: DEFINE KEY PARAMETERS
|
||||
source ./run_params.tcl
|
||||
|
||||
#STEP2: CREATE PROJECT AND READ IN FILES
|
||||
source ../../common/fpga/system_init.tcl
|
||||
|
||||
#STEP 3 (OPTIONAL): EDIT system.bd in VIVADO gui, then go to STEP 4.
|
||||
##...
|
||||
|
||||
#STEP 4: SYNTEHSIZE AND CREATE BITSTRAM
|
||||
source ../../common/fpga/system_build.tcl
|
22
src/gpio/fpga/run_params.tcl
Normal file
22
src/gpio/fpga/run_params.tcl
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
#Design name ("system" recommended)
|
||||
set design system
|
||||
|
||||
#Project directory ("." recommended)
|
||||
set projdir ./
|
||||
|
||||
#Device name
|
||||
set partname "xc7z020clg400-1"
|
||||
|
||||
#Paths to all IP blocks to use in Vivado "system.bd"
|
||||
|
||||
set ip_repos [list "."]
|
||||
|
||||
#All source files
|
||||
set hdl_files []
|
||||
|
||||
#All constraints files
|
||||
set constraints_files [list \
|
||||
../../parallella/fpga/parallella_io.xdc \
|
||||
../../parallella/fpga/parallella_7020_io.xdc \
|
||||
]
|
227
src/gpio/fpga/system_bd.tcl
Normal file
227
src/gpio/fpga/system_bd.tcl
Normal file
@ -0,0 +1,227 @@
|
||||
|
||||
################################################################
|
||||
# This is a generated script based on design: system
|
||||
#
|
||||
# Though there are limitations about the generated script,
|
||||
# the main purpose of this utility is to make learning
|
||||
# IP Integrator Tcl commands easier.
|
||||
################################################################
|
||||
|
||||
################################################################
|
||||
# Check if script is running in correct Vivado version.
|
||||
################################################################
|
||||
set scripts_vivado_version 2015.2
|
||||
set current_vivado_version [version -short]
|
||||
|
||||
if { [string first $scripts_vivado_version $current_vivado_version] == -1 } {
|
||||
puts ""
|
||||
puts "ERROR: This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script."
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
################################################################
|
||||
# START
|
||||
################################################################
|
||||
|
||||
# To test this script, run the following commands from Vivado Tcl console:
|
||||
# source system_script.tcl
|
||||
|
||||
# If you do not already have a project created,
|
||||
# you can create a project using the following command:
|
||||
# create_project project_1 myproj -part xc7z020clg400-1
|
||||
|
||||
# CHECKING IF PROJECT EXISTS
|
||||
if { [get_projects -quiet] eq "" } {
|
||||
puts "ERROR: Please open or create a project!"
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
|
||||
# CHANGE DESIGN NAME HERE
|
||||
set design_name system
|
||||
|
||||
# If you do not already have an existing IP Integrator design open,
|
||||
# you can create a design using the following command:
|
||||
# create_bd_design $design_name
|
||||
|
||||
# Creating design if needed
|
||||
set errMsg ""
|
||||
set nRet 0
|
||||
|
||||
set cur_design [current_bd_design -quiet]
|
||||
set list_cells [get_bd_cells -quiet]
|
||||
|
||||
if { ${design_name} eq "" } {
|
||||
# USE CASES:
|
||||
# 1) Design_name not set
|
||||
|
||||
set errMsg "ERROR: Please set the variable <design_name> to a non-empty value."
|
||||
set nRet 1
|
||||
|
||||
} elseif { ${cur_design} ne "" && ${list_cells} eq "" } {
|
||||
# USE CASES:
|
||||
# 2): Current design opened AND is empty AND names same.
|
||||
# 3): Current design opened AND is empty AND names diff; design_name NOT in project.
|
||||
# 4): Current design opened AND is empty AND names diff; design_name exists in project.
|
||||
|
||||
if { $cur_design ne $design_name } {
|
||||
puts "INFO: Changing value of <design_name> from <$design_name> to <$cur_design> since current design is empty."
|
||||
set design_name [get_property NAME $cur_design]
|
||||
}
|
||||
puts "INFO: Constructing design in IPI design <$cur_design>..."
|
||||
|
||||
} elseif { ${cur_design} ne "" && $list_cells ne "" && $cur_design eq $design_name } {
|
||||
# USE CASES:
|
||||
# 5) Current design opened AND has components AND same names.
|
||||
|
||||
set errMsg "ERROR: Design <$design_name> already exists in your project, please set the variable <design_name> to another value."
|
||||
set nRet 1
|
||||
} elseif { [get_files -quiet ${design_name}.bd] ne "" } {
|
||||
# USE CASES:
|
||||
# 6) Current opened design, has components, but diff names, design_name exists in project.
|
||||
# 7) No opened design, design_name exists in project.
|
||||
|
||||
set errMsg "ERROR: Design <$design_name> already exists in your project, please set the variable <design_name> to another value."
|
||||
set nRet 2
|
||||
|
||||
} else {
|
||||
# USE CASES:
|
||||
# 8) No opened design, design_name not in project.
|
||||
# 9) Current opened design, has components, but diff names, design_name not in project.
|
||||
|
||||
puts "INFO: Currently there is no design <$design_name> in project, so creating one..."
|
||||
|
||||
create_bd_design $design_name
|
||||
|
||||
puts "INFO: Making design <$design_name> as current_bd_design."
|
||||
current_bd_design $design_name
|
||||
|
||||
}
|
||||
|
||||
puts "INFO: Currently the variable <design_name> is equal to \"$design_name\"."
|
||||
|
||||
if { $nRet != 0 } {
|
||||
puts $errMsg
|
||||
return $nRet
|
||||
}
|
||||
|
||||
##################################################################
|
||||
# DESIGN PROCs
|
||||
##################################################################
|
||||
|
||||
|
||||
|
||||
# Procedure to create entire design; Provide argument to make
|
||||
# procedure reusable. If parentCell is "", will use root.
|
||||
proc create_root_design { parentCell } {
|
||||
|
||||
if { $parentCell eq "" } {
|
||||
set parentCell [get_bd_cells /]
|
||||
}
|
||||
|
||||
# Get object for parentCell
|
||||
set parentObj [get_bd_cells $parentCell]
|
||||
if { $parentObj == "" } {
|
||||
puts "ERROR: Unable to find parent cell <$parentCell>!"
|
||||
return
|
||||
}
|
||||
|
||||
# Make sure parentObj is hier blk
|
||||
set parentType [get_property TYPE $parentObj]
|
||||
if { $parentType ne "hier" } {
|
||||
puts "ERROR: Parent <$parentObj> has TYPE = <$parentType>. Expected to be <hier>."
|
||||
return
|
||||
}
|
||||
|
||||
# Save current instance; Restore later
|
||||
set oldCurInst [current_bd_instance .]
|
||||
|
||||
# Set parent object as current
|
||||
current_bd_instance $parentObj
|
||||
|
||||
|
||||
# Create interface ports
|
||||
|
||||
# Create ports
|
||||
set gpio_n [ create_bd_port -dir IO -from 23 -to 0 gpio_n ]
|
||||
set gpio_p [ create_bd_port -dir IO -from 23 -to 0 gpio_p ]
|
||||
|
||||
# Create instance: parallella_gpio_0, and set properties
|
||||
set parallella_gpio_0 [ create_bd_cell -type ip -vlnv www.parallella.org:user:parallella_gpio:1.0 parallella_gpio_0 ]
|
||||
|
||||
# Create instance: proc_sys_reset_0, and set properties
|
||||
set proc_sys_reset_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 proc_sys_reset_0 ]
|
||||
|
||||
# Create instance: processing_system7_0, and set properties
|
||||
set processing_system7_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:processing_system7:5.5 processing_system7_0 ]
|
||||
set_property -dict [ list CONFIG.PCW_CORE0_FIQ_INTR {0} \
|
||||
CONFIG.PCW_ENET0_ENET0_IO {MIO 16 .. 27} CONFIG.PCW_ENET0_GRP_MDIO_ENABLE {1} \
|
||||
CONFIG.PCW_ENET0_PERIPHERAL_ENABLE {1} CONFIG.PCW_ENET1_PERIPHERAL_ENABLE {0} \
|
||||
CONFIG.PCW_EN_CLK3_PORT {1} CONFIG.PCW_FPGA0_PERIPHERAL_FREQMHZ {100} \
|
||||
CONFIG.PCW_FPGA3_PERIPHERAL_FREQMHZ {100} CONFIG.PCW_GPIO_EMIO_GPIO_ENABLE {1} \
|
||||
CONFIG.PCW_GPIO_MIO_GPIO_ENABLE {1} CONFIG.PCW_GPIO_MIO_GPIO_IO {MIO} \
|
||||
CONFIG.PCW_I2C0_I2C0_IO {EMIO} CONFIG.PCW_I2C0_PERIPHERAL_ENABLE {1} \
|
||||
CONFIG.PCW_I2C0_RESET_ENABLE {0} CONFIG.PCW_IRQ_F2P_INTR {1} \
|
||||
CONFIG.PCW_IRQ_F2P_MODE {DIRECT} CONFIG.PCW_PRESET_BANK1_VOLTAGE {LVCMOS 1.8V} \
|
||||
CONFIG.PCW_QSPI_GRP_SINGLE_SS_ENABLE {1} CONFIG.PCW_QSPI_PERIPHERAL_ENABLE {1} \
|
||||
CONFIG.PCW_SD1_PERIPHERAL_ENABLE {1} CONFIG.PCW_SD1_SD1_IO {MIO 10 .. 15} \
|
||||
CONFIG.PCW_SDIO_PERIPHERAL_FREQMHZ {50} CONFIG.PCW_UART1_PERIPHERAL_ENABLE {1} \
|
||||
CONFIG.PCW_UART1_UART1_IO {MIO 8 .. 9} CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY0 {0.434} \
|
||||
CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY1 {0.398} CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY2 {0.410} \
|
||||
CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY3 {0.455} CONFIG.PCW_UIPARAM_DDR_CL {9} \
|
||||
CONFIG.PCW_UIPARAM_DDR_CWL {9} CONFIG.PCW_UIPARAM_DDR_DEVICE_CAPACITY {8192 MBits} \
|
||||
CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_0 {0.315} CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_1 {0.391} \
|
||||
CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_2 {0.374} CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_3 {0.271} \
|
||||
CONFIG.PCW_UIPARAM_DDR_DRAM_WIDTH {32 Bits} CONFIG.PCW_UIPARAM_DDR_FREQ_MHZ {400.00} \
|
||||
CONFIG.PCW_UIPARAM_DDR_PARTNO {Custom} CONFIG.PCW_UIPARAM_DDR_T_FAW {50} \
|
||||
CONFIG.PCW_UIPARAM_DDR_T_RAS_MIN {40} CONFIG.PCW_UIPARAM_DDR_T_RC {60} \
|
||||
CONFIG.PCW_UIPARAM_DDR_T_RCD {9} CONFIG.PCW_UIPARAM_DDR_T_RP {9} \
|
||||
CONFIG.PCW_UIPARAM_DDR_USE_INTERNAL_VREF {1} CONFIG.PCW_USB0_PERIPHERAL_ENABLE {1} \
|
||||
CONFIG.PCW_USB0_RESET_ENABLE {0} CONFIG.PCW_USB1_PERIPHERAL_ENABLE {1} \
|
||||
CONFIG.PCW_USE_FABRIC_INTERRUPT {1} CONFIG.PCW_USE_M_AXI_GP1 {1} \
|
||||
CONFIG.PCW_USE_S_AXI_HP0 {1} ] $processing_system7_0
|
||||
|
||||
# Create instance: processing_system7_0_axi_periph, and set properties
|
||||
set processing_system7_0_axi_periph [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 processing_system7_0_axi_periph ]
|
||||
set_property -dict [ list CONFIG.NUM_MI {1} ] $processing_system7_0_axi_periph
|
||||
|
||||
# Create instance: sys_concat_intc, and set properties
|
||||
set sys_concat_intc [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 sys_concat_intc ]
|
||||
set_property -dict [ list CONFIG.NUM_PORTS {16} ] $sys_concat_intc
|
||||
|
||||
# Create interface connections
|
||||
connect_bd_intf_net -intf_net processing_system7_0_M_AXI_GP0 [get_bd_intf_pins processing_system7_0/M_AXI_GP0] [get_bd_intf_pins processing_system7_0_axi_periph/S00_AXI]
|
||||
connect_bd_intf_net -intf_net processing_system7_0_axi_periph_M00_AXI [get_bd_intf_pins parallella_gpio_0/s_axi] [get_bd_intf_pins processing_system7_0_axi_periph/M00_AXI]
|
||||
|
||||
# Create port connections
|
||||
connect_bd_net -net parallella_gpio_0_constant_zero [get_bd_pins sys_concat_intc/In0] [get_bd_pins sys_concat_intc/In1] [get_bd_pins sys_concat_intc/In2] [get_bd_pins sys_concat_intc/In3] [get_bd_pins sys_concat_intc/In4] [get_bd_pins sys_concat_intc/In5] [get_bd_pins sys_concat_intc/In6] [get_bd_pins sys_concat_intc/In7] [get_bd_pins sys_concat_intc/In8] [get_bd_pins sys_concat_intc/In9] [get_bd_pins sys_concat_intc/In11] [get_bd_pins sys_concat_intc/In12] [get_bd_pins sys_concat_intc/In13] [get_bd_pins sys_concat_intc/In14] [get_bd_pins sys_concat_intc/In15]
|
||||
connect_bd_net -net parallella_gpio_0_gpio_irq [get_bd_pins parallella_gpio_0/gpio_irq] [get_bd_pins sys_concat_intc/In10]
|
||||
connect_bd_net -net parallella_gpio_0_gpio_n [get_bd_ports gpio_n] [get_bd_pins parallella_gpio_0/gpio_n]
|
||||
connect_bd_net -net parallella_gpio_0_gpio_p [get_bd_ports gpio_p] [get_bd_pins parallella_gpio_0/gpio_p]
|
||||
connect_bd_net -net proc_sys_reset_0_interconnect_aresetn [get_bd_pins proc_sys_reset_0/interconnect_aresetn] [get_bd_pins processing_system7_0_axi_periph/ARESETN]
|
||||
connect_bd_net -net proc_sys_reset_0_peripheral_aresetn [get_bd_pins parallella_gpio_0/s_axi_aresetn] [get_bd_pins parallella_gpio_0/sys_nreset] [get_bd_pins proc_sys_reset_0/peripheral_aresetn] [get_bd_pins processing_system7_0_axi_periph/M00_ARESETN] [get_bd_pins processing_system7_0_axi_periph/S00_ARESETN]
|
||||
connect_bd_net -net processing_system7_0_FCLK_CLK0 [get_bd_pins parallella_gpio_0/sys_clk] [get_bd_pins proc_sys_reset_0/slowest_sync_clk] [get_bd_pins processing_system7_0/FCLK_CLK0] [get_bd_pins processing_system7_0/M_AXI_GP0_ACLK] [get_bd_pins processing_system7_0/M_AXI_GP1_ACLK] [get_bd_pins processing_system7_0/S_AXI_HP0_ACLK] [get_bd_pins processing_system7_0_axi_periph/ACLK] [get_bd_pins processing_system7_0_axi_periph/M00_ACLK] [get_bd_pins processing_system7_0_axi_periph/S00_ACLK]
|
||||
connect_bd_net -net processing_system7_0_FCLK_RESET0_N [get_bd_pins proc_sys_reset_0/ext_reset_in] [get_bd_pins processing_system7_0/FCLK_RESET0_N]
|
||||
connect_bd_net -net sys_concat_intc_dout [get_bd_pins processing_system7_0/IRQ_F2P] [get_bd_pins sys_concat_intc/dout]
|
||||
|
||||
# Create address segments
|
||||
create_bd_addr_seg -range 0x40000000 -offset 0x40000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs parallella_gpio_0/s_axi/axi_lite] SEG_parallella_gpio_0_axi_lite
|
||||
|
||||
|
||||
# Restore current instance
|
||||
current_bd_instance $oldCurInst
|
||||
|
||||
save_bd_design
|
||||
}
|
||||
# End of create_root_design()
|
||||
|
||||
|
||||
##################################################################
|
||||
# MAIN FLOW
|
||||
##################################################################
|
||||
|
||||
create_root_design ""
|
||||
|
||||
|
29
src/gpio/fpga/system_params.tcl
Normal file
29
src/gpio/fpga/system_params.tcl
Normal file
@ -0,0 +1,29 @@
|
||||
# NOTE: See UG1118 for more information
|
||||
|
||||
#########################################
|
||||
# VARIABLES
|
||||
#########################################
|
||||
set design axi_gpio
|
||||
set projdir ./
|
||||
set root "../.."
|
||||
set partname "xc7z020clg400-1"
|
||||
|
||||
set hdl_files [list \
|
||||
$root/gpio/hdl \
|
||||
$root/common/hdl/ \
|
||||
$root/emesh/hdl \
|
||||
$root/emmu/hdl \
|
||||
$root/axi/hdl \
|
||||
$root/emailbox/hdl \
|
||||
$root/edma/hdl \
|
||||
$root/elink/hdl \
|
||||
$root/parallella/hdl \
|
||||
]
|
||||
|
||||
set ip_files []
|
||||
|
||||
set constraints_files [list \
|
||||
../../parallella/fpga/parallella_io.xdc \
|
||||
../../parallella/fpga/parallella_7020_io.xdc \
|
||||
]
|
||||
|
210
src/gpio/hdl/axi_gpio.v
Normal file
210
src/gpio/hdl/axi_gpio.v
Normal file
@ -0,0 +1,210 @@
|
||||
//#############################################################################
|
||||
//# Purpose: AXI GPIO module #
|
||||
//#############################################################################
|
||||
//# Author: Ola Jeppsson #
|
||||
//# SPDX-License-Identifier: MIT #
|
||||
//#############################################################################
|
||||
|
||||
module axi_gpio(/*AUTOARG*/
|
||||
// Outputs
|
||||
s_axi_wready, s_axi_rvalid, s_axi_rresp, s_axi_rlast, s_axi_rid,
|
||||
s_axi_rdata, s_axi_bvalid, s_axi_bresp, s_axi_bid, s_axi_awready,
|
||||
s_axi_arready, gpio_out, gpio_irq, gpio_dir,
|
||||
// Inputs
|
||||
s_axi_wvalid, s_axi_wstrb, s_axi_wlast, s_axi_wid, s_axi_wdata,
|
||||
s_axi_rready, s_axi_bready, s_axi_awvalid, s_axi_awsize,
|
||||
s_axi_awqos, s_axi_awprot, s_axi_awlock, s_axi_awlen, s_axi_awid,
|
||||
s_axi_awcache, s_axi_awburst, s_axi_awaddr, s_axi_arvalid,
|
||||
s_axi_arsize, s_axi_arqos, s_axi_arprot, s_axi_arlock, s_axi_arlen,
|
||||
s_axi_arid, s_axi_aresetn, s_axi_arcache, s_axi_arburst,
|
||||
s_axi_araddr, gpio_in, sys_nreset, sys_clk
|
||||
);
|
||||
|
||||
//########################################################
|
||||
// INTERFACE
|
||||
//########################################################
|
||||
parameter AW = 32; // address width
|
||||
parameter PW = 2*AW+40; // packet width
|
||||
parameter ID = 12'h810; // addr[31:20] id
|
||||
parameter S_IDW = 12; // ID width for S_AXI
|
||||
parameter N = 24; // number of gpio pins
|
||||
|
||||
//clk, reset
|
||||
input sys_nreset; // active low async reset
|
||||
input sys_clk; // system clock for AXI
|
||||
|
||||
//############################
|
||||
// HOST GENERATERD
|
||||
//############################
|
||||
//Slave Write
|
||||
wire s_wr_access;
|
||||
wire [PW-1:0] s_wr_packet;
|
||||
wire s_wr_wait;
|
||||
|
||||
//Slave Read Request
|
||||
wire s_rd_access;
|
||||
wire [PW-1:0] s_rd_packet;
|
||||
wire s_rd_wait;
|
||||
|
||||
//Slave Read Response
|
||||
wire s_rr_access;
|
||||
wire [PW-1:0] s_rr_packet;
|
||||
wire s_rr_wait;
|
||||
|
||||
//##############################################################
|
||||
|
||||
/*AUTOINPUT*/
|
||||
// Beginning of automatic inputs (from unused autoinst inputs)
|
||||
input [N-1:0] gpio_in; // To gpio of gpio.v
|
||||
input [31:0] s_axi_araddr; // To esaxi of esaxi.v
|
||||
input [1:0] s_axi_arburst; // To esaxi of esaxi.v
|
||||
input [3:0] s_axi_arcache; // To esaxi of esaxi.v
|
||||
input s_axi_aresetn; // To esaxi of esaxi.v
|
||||
input [S_IDW-1:0] s_axi_arid; // To esaxi of esaxi.v
|
||||
input [7:0] s_axi_arlen; // To esaxi of esaxi.v
|
||||
input s_axi_arlock; // To esaxi of esaxi.v
|
||||
input [2:0] s_axi_arprot; // To esaxi of esaxi.v
|
||||
input [3:0] s_axi_arqos; // To esaxi of esaxi.v
|
||||
input [2:0] s_axi_arsize; // To esaxi of esaxi.v
|
||||
input s_axi_arvalid; // To esaxi of esaxi.v
|
||||
input [31:0] s_axi_awaddr; // To esaxi of esaxi.v
|
||||
input [1:0] s_axi_awburst; // To esaxi of esaxi.v
|
||||
input [3:0] s_axi_awcache; // To esaxi of esaxi.v
|
||||
input [S_IDW-1:0] s_axi_awid; // To esaxi of esaxi.v
|
||||
input [7:0] s_axi_awlen; // To esaxi of esaxi.v
|
||||
input s_axi_awlock; // To esaxi of esaxi.v
|
||||
input [2:0] s_axi_awprot; // To esaxi of esaxi.v
|
||||
input [3:0] s_axi_awqos; // To esaxi of esaxi.v
|
||||
input [2:0] s_axi_awsize; // To esaxi of esaxi.v
|
||||
input s_axi_awvalid; // To esaxi of esaxi.v
|
||||
input s_axi_bready; // To esaxi of esaxi.v
|
||||
input s_axi_rready; // To esaxi of esaxi.v
|
||||
input [31:0] s_axi_wdata; // To esaxi of esaxi.v
|
||||
input [S_IDW-1:0] s_axi_wid; // To esaxi of esaxi.v
|
||||
input s_axi_wlast; // To esaxi of esaxi.v
|
||||
input [3:0] s_axi_wstrb; // To esaxi of esaxi.v
|
||||
input s_axi_wvalid; // To esaxi of esaxi.v
|
||||
// End of automatics
|
||||
|
||||
/*AUTOOUTPUT*/
|
||||
// Beginning of automatic outputs (from unused autoinst outputs)
|
||||
output [N-1:0] gpio_dir; // From gpio of gpio.v
|
||||
output gpio_irq; // From gpio of gpio.v
|
||||
output [N-1:0] gpio_out; // From gpio of gpio.v
|
||||
output s_axi_arready; // From esaxi of esaxi.v
|
||||
output s_axi_awready; // From esaxi of esaxi.v
|
||||
output [S_IDW-1:0] s_axi_bid; // From esaxi of esaxi.v
|
||||
output [1:0] s_axi_bresp; // From esaxi of esaxi.v
|
||||
output s_axi_bvalid; // From esaxi of esaxi.v
|
||||
output [31:0] s_axi_rdata; // From esaxi of esaxi.v
|
||||
output [S_IDW-1:0] s_axi_rid; // From esaxi of esaxi.v
|
||||
output s_axi_rlast; // From esaxi of esaxi.v
|
||||
output [1:0] s_axi_rresp; // From esaxi of esaxi.v
|
||||
output s_axi_rvalid; // From esaxi of esaxi.v
|
||||
output s_axi_wready; // From esaxi of esaxi.v
|
||||
// End of automatics
|
||||
|
||||
/*AUTOWIRE*/
|
||||
|
||||
/*AUTOREG*/
|
||||
|
||||
wire gpio_wait_out;
|
||||
wire gpio_access_out;
|
||||
wire [PW-1:0] gpio_packet_out;
|
||||
wire gpio_access_in;
|
||||
wire [PW-1:0] gpio_packet_in;
|
||||
wire gpio_wait_in;
|
||||
|
||||
gpio #(.AW(AW),.N(N))
|
||||
gpio(
|
||||
//Outputs
|
||||
.wait_out (gpio_wait_out),
|
||||
.access_out (gpio_access_out),
|
||||
.packet_out (gpio_packet_out[PW-1:0]),
|
||||
//Inputs
|
||||
.nreset (sys_nreset),
|
||||
.clk (sys_clk),
|
||||
.access_in (gpio_access_in),
|
||||
.packet_in (gpio_packet_in[PW-1:0]),
|
||||
.wait_in (gpio_wait_in),
|
||||
/*AUTOINST*/
|
||||
// Outputs
|
||||
.gpio_out (gpio_out[N-1:0]),
|
||||
.gpio_dir (gpio_dir[N-1:0]),
|
||||
.gpio_irq (gpio_irq),
|
||||
// Inputs
|
||||
.gpio_in (gpio_in[N-1:0]));
|
||||
|
||||
//########################################################
|
||||
//AXI SLAVE
|
||||
//########################################################
|
||||
|
||||
emesh_mux #(.N(2),.AW(AW))
|
||||
mux2(// Outputs
|
||||
.wait_out ({s_rd_wait, s_wr_wait}),
|
||||
.access_out (gpio_access_in),
|
||||
.packet_out (gpio_packet_in[PW-1:0]),
|
||||
// Inputs
|
||||
.access_in ({s_rd_access, s_wr_access}),
|
||||
.packet_in ({s_rd_packet[PW-1:0], s_wr_packet[PW-1:0]}),
|
||||
.wait_in (s_rr_wait)
|
||||
);
|
||||
|
||||
esaxi #(.S_IDW(S_IDW))
|
||||
esaxi (.s_axi_aclk (sys_clk),
|
||||
.wr_access (s_wr_access),
|
||||
.wr_packet (s_wr_packet[PW-1:0]),
|
||||
.rr_wait (s_rr_wait),
|
||||
.rd_wait (s_rd_wait),
|
||||
.rr_access (gpio_access_out),
|
||||
.rr_packet (gpio_packet_out[PW-1:0]),
|
||||
.wr_wait (s_wr_wait),
|
||||
.rd_access (s_rd_access),
|
||||
.rd_packet (s_rd_packet[PW-1:0]),
|
||||
/*AUTOINST*/
|
||||
// Outputs
|
||||
.s_axi_arready (s_axi_arready),
|
||||
.s_axi_awready (s_axi_awready),
|
||||
.s_axi_bid (s_axi_bid[S_IDW-1:0]),
|
||||
.s_axi_bresp (s_axi_bresp[1:0]),
|
||||
.s_axi_bvalid (s_axi_bvalid),
|
||||
.s_axi_rid (s_axi_rid[S_IDW-1:0]),
|
||||
.s_axi_rdata (s_axi_rdata[31:0]),
|
||||
.s_axi_rlast (s_axi_rlast),
|
||||
.s_axi_rresp (s_axi_rresp[1:0]),
|
||||
.s_axi_rvalid (s_axi_rvalid),
|
||||
.s_axi_wready (s_axi_wready),
|
||||
// Inputs
|
||||
.s_axi_aresetn (s_axi_aresetn),
|
||||
.s_axi_arid (s_axi_arid[S_IDW-1:0]),
|
||||
.s_axi_araddr (s_axi_araddr[31:0]),
|
||||
.s_axi_arburst (s_axi_arburst[1:0]),
|
||||
.s_axi_arcache (s_axi_arcache[3:0]),
|
||||
.s_axi_arlock (s_axi_arlock),
|
||||
.s_axi_arlen (s_axi_arlen[7:0]),
|
||||
.s_axi_arprot (s_axi_arprot[2:0]),
|
||||
.s_axi_arqos (s_axi_arqos[3:0]),
|
||||
.s_axi_arsize (s_axi_arsize[2:0]),
|
||||
.s_axi_arvalid (s_axi_arvalid),
|
||||
.s_axi_awid (s_axi_awid[S_IDW-1:0]),
|
||||
.s_axi_awaddr (s_axi_awaddr[31:0]),
|
||||
.s_axi_awburst (s_axi_awburst[1:0]),
|
||||
.s_axi_awcache (s_axi_awcache[3:0]),
|
||||
.s_axi_awlock (s_axi_awlock),
|
||||
.s_axi_awlen (s_axi_awlen[7:0]),
|
||||
.s_axi_awprot (s_axi_awprot[2:0]),
|
||||
.s_axi_awqos (s_axi_awqos[3:0]),
|
||||
.s_axi_awsize (s_axi_awsize[2:0]),
|
||||
.s_axi_awvalid (s_axi_awvalid),
|
||||
.s_axi_bready (s_axi_bready),
|
||||
.s_axi_rready (s_axi_rready),
|
||||
.s_axi_wid (s_axi_wid[S_IDW-1:0]),
|
||||
.s_axi_wdata (s_axi_wdata[31:0]),
|
||||
.s_axi_wlast (s_axi_wlast),
|
||||
.s_axi_wstrb (s_axi_wstrb[3:0]),
|
||||
.s_axi_wvalid (s_axi_wvalid));
|
||||
|
||||
endmodule // axi_gpio
|
||||
// Local Variables:
|
||||
// verilog-library-directories:("." "../../axi/hdl" "../../common/hdl" "../../emesh/hdl")
|
||||
// End:
|
@ -7,9 +7,9 @@
|
||||
//#############################################################################
|
||||
|
||||
`include "gpio_regmap.vh"
|
||||
module gpio #(
|
||||
parameter integer N = 24, // number of gpio pins
|
||||
parameter integer AW = 32 // architecture address width
|
||||
module gpio #( parameter integer N = 24, // number of gpio pins
|
||||
parameter integer AW = 32, // architecture address width
|
||||
parameter integer PW = 104 // packet width
|
||||
)
|
||||
(
|
||||
input nreset, // asynchronous active low reset
|
||||
@ -20,8 +20,8 @@ module gpio #(
|
||||
output access_out, // register access
|
||||
output [PW-1:0] packet_out, // data/address
|
||||
input wait_in, // pushback from mesh
|
||||
output [N-1:0] gpio_out, // data to drive to IO pins
|
||||
output [N-1:0] gpio_dir, // gpio direction(0=input)
|
||||
output reg [N-1:0] gpio_out, // data to drive to IO pins
|
||||
output reg [N-1:0] gpio_dir, // gpio direction(0=input)
|
||||
input [N-1:0] gpio_in, // data from IO pins
|
||||
output gpio_irq // OR of GPIO_ILAT register
|
||||
);
|
||||
@ -30,18 +30,13 @@ module gpio #(
|
||||
//# wires/regs/ params
|
||||
//################################
|
||||
|
||||
//local parameters
|
||||
localparam integer PW = 2*AW+40; // packet width
|
||||
|
||||
//registers
|
||||
reg [N-1:0] gpio_dir;
|
||||
reg [N-1:0] gpio_out;
|
||||
reg [N-1:0] gpio_imask;
|
||||
reg [N-1:0] gpio_itype;
|
||||
reg [N-1:0] gpio_ipol;
|
||||
reg [N-1:0] gpio_ilat;
|
||||
reg [N-1:0] gpio_in_old;
|
||||
reg [AW-1:0] read_data; // read is always 32 bits
|
||||
reg [N-1:0] read_data;
|
||||
|
||||
//wires
|
||||
wire [N-1:0] ilat_clr;
|
||||
@ -51,6 +46,19 @@ module gpio #(
|
||||
wire [N-1:0] rising_edge;
|
||||
wire [N-1:0] falling_edge;
|
||||
wire [N-1:0] irq_event;
|
||||
wire reg_write;
|
||||
wire reg_read;
|
||||
wire reg_double;
|
||||
wire dir_write;
|
||||
wire imask_write;
|
||||
wire itype_write;
|
||||
wire ipol_write;
|
||||
wire ilatclr_write;
|
||||
wire out_write;
|
||||
wire outset_write;
|
||||
wire outclr_write;
|
||||
wire outxor_write;
|
||||
wire outreg_write;
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
@ -66,7 +74,8 @@ module gpio #(
|
||||
//# DECODE LOGIC
|
||||
//################################
|
||||
|
||||
packet2emesh #(.AW(AW))
|
||||
packet2emesh #(.AW(AW),
|
||||
.PW(PW))
|
||||
p2e(
|
||||
/*AUTOINST*/
|
||||
// Outputs
|
||||
@ -85,7 +94,7 @@ module gpio #(
|
||||
assign reg_wdata[N-1:0] = data_in[N-1:0];
|
||||
|
||||
assign dir_write = reg_write & (dstaddr_in[6:3]==`GPIO_DIR);
|
||||
assign out_write = reg_write & (dstaddr_in[6:3]==`GPIO_OUT);
|
||||
assign outreg_write = reg_write & (dstaddr_in[6:3]==`GPIO_OUT);
|
||||
assign imask_write = reg_write & (dstaddr_in[6:3]==`GPIO_IMASK);
|
||||
assign itype_write = reg_write & (dstaddr_in[6:3]==`GPIO_ITYPE);
|
||||
assign ipol_write = reg_write & (dstaddr_in[6:3]==`GPIO_IPOL);
|
||||
@ -94,7 +103,7 @@ module gpio #(
|
||||
assign outset_write = reg_write & (dstaddr_in[6:3]==`GPIO_OUTSET);
|
||||
assign outxor_write = reg_write & (dstaddr_in[6:3]==`GPIO_OUTXOR);
|
||||
|
||||
assign out_reg_write = out_write |
|
||||
assign out_write = outreg_write |
|
||||
outclr_write |
|
||||
outset_write |
|
||||
outxor_write;
|
||||
@ -113,8 +122,7 @@ module gpio #(
|
||||
//# GPIO_IN
|
||||
//################################
|
||||
|
||||
oh_dsync #(.DW(N))
|
||||
dsync (.dout (gpio_in_sync[N-1:0]),
|
||||
oh_dsync oh_dsync[N-1:0] (.dout (gpio_in_sync[N-1:0]),
|
||||
.clk (clk),
|
||||
.nreset (nreset),
|
||||
.din (gpio_in[N-1:0]));
|
||||
@ -129,7 +137,7 @@ module gpio #(
|
||||
oh_mux4 #(.DW(N))
|
||||
oh_mux4 (.out (out_dmux[N-1:0]),
|
||||
// Inputs
|
||||
.in0 (reg_wdata[N-1:0]), .sel0 (out_write),
|
||||
.in0 (reg_wdata[N-1:0]), .sel0 (outreg_write),
|
||||
.in1 (gpio_out[N-1:0] & ~reg_wdata[N-1:0]),.sel1 (outclr_write),
|
||||
.in2 (gpio_out[N-1:0] | reg_wdata[N-1:0]), .sel2 (outset_write),
|
||||
.in3 (gpio_out[N-1:0] ^ reg_wdata[N-1:0]), .sel3 (outxor_write));
|
||||
@ -137,7 +145,7 @@ module gpio #(
|
||||
always @ (posedge clk or negedge nreset)
|
||||
if(!nreset)
|
||||
gpio_out[N-1:0] <= 'b0;
|
||||
else if(out_reg_write)
|
||||
else if(out_write)
|
||||
gpio_out[N-1:0] <= out_dmux[N-1:0];
|
||||
|
||||
//################################
|
||||
@ -203,16 +211,17 @@ module gpio #(
|
||||
always @ (posedge clk)
|
||||
if(reg_read)
|
||||
case(dstaddr_in[6:3])
|
||||
`GPIO_IN : read_data[AW-1:0] <= gpio_in_sync[N-1:0];
|
||||
`GPIO_ILAT : read_data[AW-1:0] <= gpio_ilat[N-1:0];
|
||||
`GPIO_DIR : read_data[AW-1:0] <= gpio_dir[N-1:0];
|
||||
`GPIO_IMASK: read_data[AW-1:0] <= gpio_imask[N-1:0];
|
||||
`GPIO_IPOL : read_data[AW-1:0] <= gpio_ipol[N-1:0];
|
||||
`GPIO_ITYPE: read_data[AW-1:0] <= gpio_itype[N-1:0];
|
||||
default : read_data[AW-1:0] <='b0;
|
||||
`GPIO_IN : read_data[N-1:0] <= gpio_in_sync[N-1:0];
|
||||
`GPIO_ILAT : read_data[N-1:0] <= gpio_ilat[N-1:0];
|
||||
`GPIO_DIR : read_data[N-1:0] <= gpio_dir[N-1:0];
|
||||
`GPIO_IMASK: read_data[N-1:0] <= gpio_imask[N-1:0];
|
||||
`GPIO_IPOL : read_data[N-1:0] <= gpio_ipol[N-1:0];
|
||||
`GPIO_ITYPE: read_data[N-1:0] <= gpio_itype[N-1:0];
|
||||
default : read_data[N-1:0] <='b0;
|
||||
endcase // case (dstaddr_in[7:3])
|
||||
|
||||
emesh_readback #(.AW(AW))
|
||||
emesh_readback #(.AW(AW),
|
||||
.PW(PW))
|
||||
emesh_readback (/*AUTOINST*/
|
||||
// Outputs
|
||||
.wait_out (wait_out),
|
||||
|
171
src/gpio/hdl/parallella_gpio.v
Normal file
171
src/gpio/hdl/parallella_gpio.v
Normal file
@ -0,0 +1,171 @@
|
||||
//#############################################################################
|
||||
//# Purpose: Parallella GPIO top #
|
||||
//#############################################################################
|
||||
//# Author: Ola Jeppsson #
|
||||
//# SPDX-License-Identifier: MIT #
|
||||
//#############################################################################
|
||||
|
||||
module parallella_gpio(/*AUTOARG*/
|
||||
// Outputs
|
||||
s_axi_wready, s_axi_rvalid, s_axi_rresp, s_axi_rlast, s_axi_rid,
|
||||
s_axi_rdata, s_axi_bvalid, s_axi_bresp, s_axi_bid, s_axi_awready,
|
||||
s_axi_arready, gpio_irq,
|
||||
// Inouts
|
||||
gpio_n, gpio_p,
|
||||
// Inputs
|
||||
s_axi_wvalid, s_axi_wstrb, s_axi_wlast, s_axi_wid, s_axi_wdata,
|
||||
s_axi_rready, s_axi_bready, s_axi_awvalid, s_axi_awsize,
|
||||
s_axi_awqos, s_axi_awprot, s_axi_awlock, s_axi_awlen, s_axi_awid,
|
||||
s_axi_awcache, s_axi_awburst, s_axi_awaddr, s_axi_arvalid,
|
||||
s_axi_arsize, s_axi_arqos, s_axi_arprot, s_axi_arlock, s_axi_arlen,
|
||||
s_axi_arid, s_axi_aresetn, s_axi_arcache, s_axi_arburst,
|
||||
s_axi_araddr, constant_zero, constant_one, sys_nreset, sys_clk
|
||||
);
|
||||
|
||||
//########################################################
|
||||
// INTERFACE
|
||||
//########################################################
|
||||
parameter AW = 32; // address width
|
||||
parameter DW = 32;
|
||||
parameter PW = 2*AW+40; // packet width
|
||||
parameter ID = 12'h7ff; // addr[31:20] id
|
||||
parameter S_IDW = 12; // ID width for S_AXI
|
||||
parameter NGPIO = 24; // number of gpio pins
|
||||
|
||||
// constants
|
||||
input constant_zero; // Always 0
|
||||
input constant_one; // Always 1
|
||||
|
||||
//clk, reset
|
||||
input sys_nreset; // active low async reset
|
||||
input sys_clk; // system clock for AXI
|
||||
|
||||
inout [NGPIO-1:0] gpio_n; // physical gpio pins
|
||||
inout [NGPIO-1:0] gpio_p; // physical gpio pins
|
||||
|
||||
wire [NGPIO-1:0] gpio_in; // oh gpio in
|
||||
wire [NGPIO-1:0] gpio_out; // oh gpio out
|
||||
wire [NGPIO-1:0] gpio_dir; // oh gpio direction
|
||||
wire [NGPIO-1:0] pgpio_in; // parallella gpio in
|
||||
wire [NGPIO-1:0] pgpio_out; // parallella gpio out
|
||||
|
||||
/*AUTOINPUT*/
|
||||
// Beginning of automatic inputs (from unused autoinst inputs)
|
||||
input [31:0] s_axi_araddr; // To axi_gpio of axi_gpio.v
|
||||
input [1:0] s_axi_arburst; // To axi_gpio of axi_gpio.v
|
||||
input [3:0] s_axi_arcache; // To axi_gpio of axi_gpio.v
|
||||
input s_axi_aresetn; // To axi_gpio of axi_gpio.v
|
||||
input [S_IDW-1:0] s_axi_arid; // To axi_gpio of axi_gpio.v
|
||||
input [7:0] s_axi_arlen; // To axi_gpio of axi_gpio.v
|
||||
input s_axi_arlock; // To axi_gpio of axi_gpio.v
|
||||
input [2:0] s_axi_arprot; // To axi_gpio of axi_gpio.v
|
||||
input [3:0] s_axi_arqos; // To axi_gpio of axi_gpio.v
|
||||
input [2:0] s_axi_arsize; // To axi_gpio of axi_gpio.v
|
||||
input s_axi_arvalid; // To axi_gpio of axi_gpio.v
|
||||
input [31:0] s_axi_awaddr; // To axi_gpio of axi_gpio.v
|
||||
input [1:0] s_axi_awburst; // To axi_gpio of axi_gpio.v
|
||||
input [3:0] s_axi_awcache; // To axi_gpio of axi_gpio.v
|
||||
input [S_IDW-1:0] s_axi_awid; // To axi_gpio of axi_gpio.v
|
||||
input [7:0] s_axi_awlen; // To axi_gpio of axi_gpio.v
|
||||
input s_axi_awlock; // To axi_gpio of axi_gpio.v
|
||||
input [2:0] s_axi_awprot; // To axi_gpio of axi_gpio.v
|
||||
input [3:0] s_axi_awqos; // To axi_gpio of axi_gpio.v
|
||||
input [2:0] s_axi_awsize; // To axi_gpio of axi_gpio.v
|
||||
input s_axi_awvalid; // To axi_gpio of axi_gpio.v
|
||||
input s_axi_bready; // To axi_gpio of axi_gpio.v
|
||||
input s_axi_rready; // To axi_gpio of axi_gpio.v
|
||||
input [31:0] s_axi_wdata; // To axi_gpio of axi_gpio.v
|
||||
input [S_IDW-1:0] s_axi_wid; // To axi_gpio of axi_gpio.v
|
||||
input s_axi_wlast; // To axi_gpio of axi_gpio.v
|
||||
input [3:0] s_axi_wstrb; // To axi_gpio of axi_gpio.v
|
||||
input s_axi_wvalid; // To axi_gpio of axi_gpio.v
|
||||
// End of automatics
|
||||
|
||||
/*AUTOOUTPUT*/
|
||||
// Beginning of automatic outputs (from unused autoinst outputs)
|
||||
output gpio_irq; // From axi_gpio of axi_gpio.v
|
||||
output s_axi_arready; // From axi_gpio of axi_gpio.v
|
||||
output s_axi_awready; // From axi_gpio of axi_gpio.v
|
||||
output [S_IDW-1:0] s_axi_bid; // From axi_gpio of axi_gpio.v
|
||||
output [1:0] s_axi_bresp; // From axi_gpio of axi_gpio.v
|
||||
output s_axi_bvalid; // From axi_gpio of axi_gpio.v
|
||||
output [31:0] s_axi_rdata; // From axi_gpio of axi_gpio.v
|
||||
output [S_IDW-1:0] s_axi_rid; // From axi_gpio of axi_gpio.v
|
||||
output s_axi_rlast; // From axi_gpio of axi_gpio.v
|
||||
output [1:0] s_axi_rresp; // From axi_gpio of axi_gpio.v
|
||||
output s_axi_rvalid; // From axi_gpio of axi_gpio.v
|
||||
output s_axi_wready; // From axi_gpio of axi_gpio.v
|
||||
// End of automatics
|
||||
|
||||
/*AUTOWIRE*/
|
||||
|
||||
/*AUTOREG*/
|
||||
|
||||
assign constant_zero = 1'b0;
|
||||
assign constant_one = 1'b1;
|
||||
|
||||
pgpio #(.NGPIO(NGPIO),.NPS(NGPIO))
|
||||
pgpio (.ps_gpio_i (gpio_in[NGPIO-1:0]),
|
||||
.ps_gpio_o (gpio_out[NGPIO-1:0]),
|
||||
.ps_gpio_t (~gpio_dir[NGPIO-1:0]),
|
||||
/*AUTOINST*/
|
||||
// Inouts
|
||||
.gpio_p (gpio_p[NGPIO-1:0]),
|
||||
.gpio_n (gpio_n[NGPIO-1:0]));
|
||||
|
||||
|
||||
axi_gpio #(.S_IDW(S_IDW),.AW(AW),.N(NGPIO),.ID(ID))
|
||||
axi_gpio (
|
||||
.gpio_out (gpio_out[NGPIO-1:0]),
|
||||
.gpio_dir (gpio_dir[NGPIO-1:0]),
|
||||
.gpio_in (gpio_in[NGPIO-1:0]),
|
||||
/*AUTOINST*/
|
||||
// Outputs
|
||||
.gpio_irq (gpio_irq),
|
||||
.s_axi_arready (s_axi_arready),
|
||||
.s_axi_awready (s_axi_awready),
|
||||
.s_axi_bid (s_axi_bid[S_IDW-1:0]),
|
||||
.s_axi_bresp (s_axi_bresp[1:0]),
|
||||
.s_axi_bvalid (s_axi_bvalid),
|
||||
.s_axi_rdata (s_axi_rdata[31:0]),
|
||||
.s_axi_rid (s_axi_rid[S_IDW-1:0]),
|
||||
.s_axi_rlast (s_axi_rlast),
|
||||
.s_axi_rresp (s_axi_rresp[1:0]),
|
||||
.s_axi_rvalid (s_axi_rvalid),
|
||||
.s_axi_wready (s_axi_wready),
|
||||
// Inputs
|
||||
.sys_nreset (sys_nreset),
|
||||
.sys_clk (sys_clk),
|
||||
.s_axi_araddr (s_axi_araddr[31:0]),
|
||||
.s_axi_arburst (s_axi_arburst[1:0]),
|
||||
.s_axi_arcache (s_axi_arcache[3:0]),
|
||||
.s_axi_aresetn (s_axi_aresetn),
|
||||
.s_axi_arid (s_axi_arid[S_IDW-1:0]),
|
||||
.s_axi_arlen (s_axi_arlen[7:0]),
|
||||
.s_axi_arlock (s_axi_arlock),
|
||||
.s_axi_arprot (s_axi_arprot[2:0]),
|
||||
.s_axi_arqos (s_axi_arqos[3:0]),
|
||||
.s_axi_arsize (s_axi_arsize[2:0]),
|
||||
.s_axi_arvalid (s_axi_arvalid),
|
||||
.s_axi_awaddr (s_axi_awaddr[31:0]),
|
||||
.s_axi_awburst (s_axi_awburst[1:0]),
|
||||
.s_axi_awcache (s_axi_awcache[3:0]),
|
||||
.s_axi_awid (s_axi_awid[S_IDW-1:0]),
|
||||
.s_axi_awlen (s_axi_awlen[7:0]),
|
||||
.s_axi_awlock (s_axi_awlock),
|
||||
.s_axi_awprot (s_axi_awprot[2:0]),
|
||||
.s_axi_awqos (s_axi_awqos[3:0]),
|
||||
.s_axi_awsize (s_axi_awsize[2:0]),
|
||||
.s_axi_awvalid (s_axi_awvalid),
|
||||
.s_axi_bready (s_axi_bready),
|
||||
.s_axi_rready (s_axi_rready),
|
||||
.s_axi_wdata (s_axi_wdata[31:0]),
|
||||
.s_axi_wid (s_axi_wid[S_IDW-1:0]),
|
||||
.s_axi_wlast (s_axi_wlast),
|
||||
.s_axi_wstrb (s_axi_wstrb[3:0]),
|
||||
.s_axi_wvalid (s_axi_wvalid));
|
||||
|
||||
endmodule // parallella_gpio
|
||||
// Local Variables:
|
||||
// verilog-library-directories:("." "../../axi/hdl" "../../common/hdl" "../../emesh/hdl" "../../parallella/hdl")
|
||||
// End:
|
8
src/mio/driver/hello-mio/Makefile
Normal file
8
src/mio/driver/hello-mio/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
CFLAGS ?= -g
|
||||
|
||||
all: hello-mio
|
||||
|
||||
clean:
|
||||
rm -f hello-mio
|
||||
|
||||
.PHONY: all clean
|
0
src/mio/driver/hello-mio/README.md
Normal file
0
src/mio/driver/hello-mio/README.md
Normal file
175
src/mio/driver/hello-mio/hello-mio.c
Normal file
175
src/mio/driver/hello-mio/hello-mio.c
Normal file
@ -0,0 +1,175 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define PAGE_SHIFT 12
|
||||
|
||||
#define MIO_CONFIG 0 // general config
|
||||
#define MIO_STATUS 1 // status
|
||||
#define MIO_CLKDIV 2 // clk divider config
|
||||
#define MIO_CLKPHASE 3 // clk divider config
|
||||
#define MIO_ODELAY 4 // output data delay element
|
||||
#define MIO_IDELAY 5 // input data delay element
|
||||
#define MIO_ADDR0 6 // destination address for amode
|
||||
#define MIO_ADDR1 7 // destination address for amode
|
||||
|
||||
#define MIO_STATUS_RX_EMPTY (1 << 0)
|
||||
#define MIO_STATUS_RX_PROG_FULL (1 << 1)
|
||||
#define MIO_STATUS_RX_FULL (1 << 2)
|
||||
#define MIO_STATUS_TX_EMPTY (1 << 3)
|
||||
#define MIO_STATUS_TX_PROG_FULL (1 << 4)
|
||||
#define MIO_STATUS_TX_FULL (1 << 5)
|
||||
|
||||
void mio_set_clkdiv(volatile uint32_t *regs, uint32_t clkdiv)
|
||||
{
|
||||
uint32_t rise0, fall0, rise1, fall1;
|
||||
uint32_t clkphase;
|
||||
|
||||
if (clkdiv > 254)
|
||||
clkdiv = 254;
|
||||
|
||||
rise0 = 0;
|
||||
fall0 = 0xff & ((clkdiv + 1) >> 1); // 180 degrees
|
||||
rise1 = 0xff & ((clkdiv + 1) >> 2); // 90 degrees
|
||||
fall1 = 0xff & (((clkdiv + 1) >> 2) +
|
||||
((clkdiv + 1) >> 1)); // 270 degrees
|
||||
|
||||
regs[MIO_CLKDIV] = clkdiv;
|
||||
regs[MIO_CLKPHASE] = fall1 << 24 |
|
||||
rise1 << 16 |
|
||||
fall0 << 8 |
|
||||
rise0 << 0;
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
bool pass = true;
|
||||
|
||||
int fd;
|
||||
union acme_ptr {
|
||||
void *v;
|
||||
volatile uint8_t *u8;
|
||||
volatile uint16_t *u16;
|
||||
volatile uint32_t *u32;
|
||||
};
|
||||
union acme_ptr wormhole, regs, mem;
|
||||
|
||||
fd = open("/dev/uio0", O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
return errno;
|
||||
}
|
||||
|
||||
/* uio_pdrv_genirq uses (offset >> PAGE_SHIFT) as index into the region
|
||||
* list. Device tree snippet:
|
||||
* mio: mio@7fd00000 {
|
||||
* #address-cells = <1>;
|
||||
* #size-cells = <1>;
|
||||
* ranges;
|
||||
* compatible = "oh,mio";
|
||||
* reg = <0x7fc00000 0x100000>, // TX wormhole
|
||||
* <0x7fd00000 0x100000>, // MIO registers
|
||||
* <0x3e000000 0x100000>; // TX destination
|
||||
* };
|
||||
*/
|
||||
|
||||
wormhole.v = mmap(NULL, 0x100000, PROT_WRITE | PROT_READ, MAP_SHARED,
|
||||
fd, 0 << PAGE_SHIFT);
|
||||
if (wormhole.v == MAP_FAILED) {
|
||||
perror("mmap wormhole");
|
||||
return errno;
|
||||
}
|
||||
|
||||
regs.v = mmap(NULL, 0x100000, PROT_WRITE | PROT_READ, MAP_SHARED,
|
||||
fd, 1 << PAGE_SHIFT);
|
||||
if (regs.v == MAP_FAILED) {
|
||||
perror("mmap regs");
|
||||
return errno;
|
||||
}
|
||||
|
||||
mem.v = mmap(NULL, 0x100000, PROT_WRITE | PROT_READ, MAP_SHARED,
|
||||
fd, 2 << PAGE_SHIFT);
|
||||
if (mem.v == MAP_FAILED) {
|
||||
perror("mmap mem");
|
||||
return errno;
|
||||
}
|
||||
|
||||
mio_set_clkdiv(regs.u32, 10);
|
||||
|
||||
// Clear memory region
|
||||
unsigned i, j;
|
||||
for (i = 0; i < 0x40000; i++)
|
||||
mem.u32[i] = 0;
|
||||
|
||||
regs.u32[1] = 0;
|
||||
printf("status: 0x%08x\n", regs.u32[1]);
|
||||
|
||||
printf("Testing pattern 1\n");
|
||||
|
||||
for (i = 0; i < 0x40000; i++) {
|
||||
uint32_t val = (i + 1) * 0x10101010;
|
||||
wormhole.u32[i] = val;
|
||||
/* HACK: Pushback broken mio_wait_out <--> s_wr_wait broken */
|
||||
/* FIFO depth = 32 */
|
||||
while (mem.u32[i] != val) {
|
||||
// for (j = 0; j < 500; j++)
|
||||
asm("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop" ::: "memory");
|
||||
// if (mem.u32[i] == val)
|
||||
// break;
|
||||
|
||||
// printf("PAT1 mem[%d]: 0x%08x expected: 0x%08x. Retrying\n",
|
||||
// i, mem.u32[i], val);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 0x40000; i++) {
|
||||
uint32_t val = (i + 1) * 0x10101010;
|
||||
while (mem.u32[i] != val) {
|
||||
printf("PAT1 mem[%d]: 0x%08x expected: 0x%08x. Retrying\n",
|
||||
i, mem.u32[i], val);
|
||||
usleep(50);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Testing pattern 2\n");
|
||||
for (i = 0; i < 0x40000; i++) {
|
||||
uint32_t val = (i + 1) * 0x01010101;
|
||||
wormhole.u32[i] = val;
|
||||
/* HACK: Pushback broken mio_wait_out <--> s_wr_wait broken */
|
||||
/* FIFO depth = 32 */
|
||||
while (mem.u32[i] != val) {
|
||||
// for (j = 0; j < 500; j++)
|
||||
asm("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop" ::: "memory");
|
||||
// if (mem.u32[i] == val)
|
||||
// break;
|
||||
|
||||
// printf("PAT2 mem[%d]: 0x%08x expected: 0x%08x. Retrying\n",
|
||||
// i, mem.u32[i], val);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 0x40000; i++) {
|
||||
uint32_t val = (i + 1) * 0x01010101;
|
||||
while (mem.u32[i] != val) {
|
||||
printf("PAT2 mem[%d]: 0x%08x expected: 0x%08x. Retrying\n",
|
||||
i, mem.u32[i], val);
|
||||
usleep(50);
|
||||
}
|
||||
}
|
||||
|
||||
munmap(wormhole.v, 0x100000);
|
||||
munmap(regs.v, 0x100000);
|
||||
munmap(mem.v, 0x100000);
|
||||
|
||||
close(fd);
|
||||
|
||||
/* If we reached here the test did pass */
|
||||
printf(pass ? "PASS\n" : "FAIL\n");
|
||||
return pass ? 0 : 1;
|
||||
}
|
16
src/mio/driver/linux-uio/README.md
Normal file
16
src/mio/driver/linux-uio/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
# OH Linux generic UIO driver
|
||||
|
||||
Modules and devicetree compiled for Pubuntu 2016.3.x
|
||||
|
||||
1. Copy `zynq-parallella-oh-mio.dtb` to SD card boot partition, name it `devicetree.dtb`.
|
||||
2. Reboot Parallella
|
||||
3. (OPTIONAL) Load bitstream: `sudo dd if=parallella.bit.bin of=/dev/xdevcfg`
|
||||
3. Load the required modules:
|
||||
```
|
||||
sudo insmod uio.ko
|
||||
sudo insmod uio_pdrv_genirq.ko of_id=oh,mio
|
||||
sudo rmmod uio_pdrv_genirq.ko
|
||||
sudo insmod uio_pdrv_genirq.ko of_id=oh,mio
|
||||
chmod 777 /dev/uio0
|
||||
```
|
||||
4. You can now compile and run hello-mio in oh.git/src/mio/driver/hello-mio
|
BIN
src/mio/driver/linux-uio/uio.ko
Normal file
BIN
src/mio/driver/linux-uio/uio.ko
Normal file
Binary file not shown.
BIN
src/mio/driver/linux-uio/uio_pdrv_genirq.ko
Normal file
BIN
src/mio/driver/linux-uio/uio_pdrv_genirq.ko
Normal file
Binary file not shown.
BIN
src/mio/driver/linux-uio/zynq-parallella-oh-mio.dtb
Normal file
BIN
src/mio/driver/linux-uio/zynq-parallella-oh-mio.dtb
Normal file
Binary file not shown.
54
src/mio/driver/linux-uio/zynq-parallella-oh-mio.dts
Normal file
54
src/mio/driver/linux-uio/zynq-parallella-oh-mio.dts
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Parallella Foundation
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/dts-v1/;
|
||||
#include "zynq-parallella1.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Adapteva Parallella Board with OH MIO bitstream";
|
||||
};
|
||||
|
||||
&amba {
|
||||
mio: mio@7fd00000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
compatible = "oh,mio";
|
||||
reg = <0x7fc00000 0x100000>, /* TX wormhole */
|
||||
<0x7fd00000 0x100000>, /* MIO registers */
|
||||
<0x3e000000 0x100000>; /* TX destination */
|
||||
};
|
||||
};
|
||||
|
||||
&usb_phy0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb_phy1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&elink0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
status = "disabled";
|
||||
};
|
@ -15,8 +15,7 @@ module mio (/*AUTOARG*/
|
||||
parameter NMIO = 8; // IO width
|
||||
parameter AW = 32; // address width
|
||||
parameter MPW = 128; // mio packet width (>PW)
|
||||
|
||||
localparam PW = 2*AW+40; // emesh packet width
|
||||
parameter PW = 2*AW+40; // emesh packet width
|
||||
parameter DEF_CFG = 0; // Default config
|
||||
parameter DEF_CLK = 0; // Default clock
|
||||
parameter TARGET = "GENERIC";// GENERIC,XILINX,ALTERA,GENERIC,ASIC
|
||||
@ -102,6 +101,7 @@ module mio (/*AUTOARG*/
|
||||
*/
|
||||
|
||||
mio_regs #(.AW(AW),
|
||||
.PW(PW),
|
||||
.DEF_CFG(DEF_CFG),
|
||||
.DEF_CLK(DEF_CLK))
|
||||
mio_regs (.dmode (),
|
||||
@ -220,6 +220,7 @@ module mio (/*AUTOARG*/
|
||||
);
|
||||
*/
|
||||
mio_if #(.AW(AW),
|
||||
.PW(PW),
|
||||
.MPW(MPW))
|
||||
mio_if (
|
||||
/*AUTOINST*/
|
||||
|
@ -61,7 +61,8 @@ module mio_dp (/*AUTOARG*/
|
||||
/*AUTOWIRE*/
|
||||
|
||||
mtx #(.NMIO(NMIO),
|
||||
.PW(PW))
|
||||
.PW(PW),
|
||||
.TARGET(TARGET))
|
||||
mtx (/*AUTOINST*/
|
||||
// Outputs
|
||||
.tx_empty (tx_empty),
|
||||
@ -83,7 +84,8 @@ module mio_dp (/*AUTOARG*/
|
||||
.tx_wait (tx_wait));
|
||||
|
||||
mrx #(.NMIO(NMIO),
|
||||
.PW(PW))
|
||||
.PW(PW),
|
||||
.TARGET(TARGET))
|
||||
mrx (/*AUTOINST*/
|
||||
// Outputs
|
||||
.rx_empty (rx_empty),
|
||||
|
@ -15,7 +15,7 @@ module mio_if (/*AUTOARG*/
|
||||
|
||||
//parameters
|
||||
parameter AW = 32; // address width
|
||||
parameter PW = 2*AW +40; // emesh packet width
|
||||
parameter PW = 104; // emesh packet width
|
||||
parameter MPW = 128; // mio packet width (> PW)
|
||||
|
||||
// reset, clk, config
|
||||
@ -87,7 +87,8 @@ module mio_if (/*AUTOARG*/
|
||||
//#################################################
|
||||
|
||||
// parse packet
|
||||
packet2emesh #(.AW(AW))
|
||||
packet2emesh #(.AW(AW),
|
||||
.PW(PW))
|
||||
pe2 (.packet_in (rx_packet_in[PW-1:0]),
|
||||
/*AUTOINST*/
|
||||
// Outputs
|
||||
@ -133,7 +134,8 @@ module mio_if (/*AUTOARG*/
|
||||
srcaddr_in[AW-1:0];
|
||||
|
||||
//Construct outgoing packet
|
||||
emesh2packet #(.AW(AW))
|
||||
emesh2packet #(.AW(AW),
|
||||
.PW(PW))
|
||||
e2p (/*AUTOINST*/
|
||||
// Outputs
|
||||
.packet_out (packet_out[PW-1:0]),
|
||||
|
@ -1,70 +1,79 @@
|
||||
//#############################################################################
|
||||
//# Function: MIO Configuration Registers #
|
||||
//# (See README.md for complete documentation) #
|
||||
//#############################################################################
|
||||
//# Author: Andreas Olofsson #
|
||||
//# License: MIT (see LICENSE file in this repository) #
|
||||
//#############################################################################
|
||||
|
||||
`include "mio_regmap.vh"
|
||||
module mio_regs (/*AUTOARG*/
|
||||
// Outputs
|
||||
wait_out, access_out, packet_out, tx_en, rx_en, ddr_mode, emode,
|
||||
amode, dmode, datasize, lsbfirst, framepol, ctrlmode, dstaddr,
|
||||
clkchange, clkdiv, clkphase0, clkphase1,
|
||||
// Inputs
|
||||
clk, nreset, access_in, packet_in, wait_in, tx_full, tx_prog_full,
|
||||
tx_empty, rx_full, rx_prog_full, rx_empty
|
||||
module mio_regs #(parameter N = 8, // number of I/O pins
|
||||
parameter AW = 32, // address width
|
||||
parameter PW = 104, // packet width
|
||||
parameter DEF_CFG = 0, // reset MIO_CONFIG value
|
||||
parameter DEF_CLK = 0 // reset MIO_CLKDIV value
|
||||
)
|
||||
(
|
||||
// clk,reset
|
||||
input clk,
|
||||
input nreset,
|
||||
// register access interface
|
||||
input access_in, // incoming access
|
||||
input [PW-1:0] packet_in, // incoming packet
|
||||
output wait_out,
|
||||
output access_out, // outgoing read packet
|
||||
output [PW-1:0] packet_out, // outgoing read packet
|
||||
input wait_in,
|
||||
// config outputs
|
||||
output tx_en, // enable tx
|
||||
output rx_en, // enable rx
|
||||
output ddr_mode, // ddr mode for mio
|
||||
output emode, // epiphany packet mode
|
||||
output amode, // mio packet mode
|
||||
output dmode, // mio packet mode
|
||||
output [7:0] datasize, // mio datasize
|
||||
output lsbfirst, // lsb shift first
|
||||
output framepol, // framepolarity (0=actrive high)
|
||||
output [4:0] ctrlmode, // emode ctrlmode
|
||||
output [AW-1:0] dstaddr, // destination address for RX dmode
|
||||
output clkchange, // indicates a clock change
|
||||
output [7:0] clkdiv, // mio clk clock setting
|
||||
output [15:0] clkphase0, // [7:0]=rising,[15:8]=falling
|
||||
output [15:0] clkphase1, // [7:0]=rising,[15:8]=falling
|
||||
// status inputs
|
||||
input tx_full, //tx fifo is full (should not happen!)
|
||||
input tx_prog_full, //tx fifo is nearing full
|
||||
input tx_empty, //tx fifo is empty
|
||||
input rx_full, //rx fifo is full (should not happen!)
|
||||
input rx_prog_full, //rx fifo is nearing full
|
||||
input rx_empty //rx fifo is empty
|
||||
);
|
||||
|
||||
// parameters
|
||||
parameter N = 8; // number of I/O pins
|
||||
parameter AW = 32; // address width
|
||||
localparam PW = 2*AW+40; // packet width
|
||||
parameter DEF_CFG = 0; // reset MIO_CONFI value
|
||||
parameter DEF_CLK = 0; // reset MIO_CLKDIV value
|
||||
localparam DEF_RISE0 = 0; // 0 degrees
|
||||
localparam DEF_FALL0 = ((DEF_CLK+8'd1)>>8'd1); // 180 degrees
|
||||
localparam DEF_RISE1 = ((DEF_CLK+8'd1)>>8'd2); // 90 degrees
|
||||
localparam DEF_FALL1 = ((DEF_CLK+8'd1)>>8'd2)+
|
||||
((DEF_CLK+8'd1)>>8'd1); // 270 degrees
|
||||
|
||||
// clk,reset
|
||||
input clk;
|
||||
input nreset;
|
||||
//##############
|
||||
//# LOCAL WIRES
|
||||
//##############
|
||||
|
||||
// registre access interface
|
||||
input access_in; // incoming access
|
||||
input [PW-1:0] packet_in; // incoming packet
|
||||
output wait_out;
|
||||
output access_out; // outgoing read packet
|
||||
output [PW-1:0] packet_out; // outgoing read packet
|
||||
input wait_in;
|
||||
|
||||
// config
|
||||
output tx_en; // enable tx
|
||||
output rx_en; // enable rx
|
||||
output ddr_mode; // ddr mode for mio
|
||||
output emode; // epiphany packet mode
|
||||
output amode; // mio packet mode
|
||||
output dmode; // mio packet mode
|
||||
output [7:0] datasize; // mio datasize
|
||||
output lsbfirst; // lsb shift first
|
||||
output framepol; // framepolarity (0=actrive high)
|
||||
output [4:0] ctrlmode; // emode ctrlmode
|
||||
|
||||
//address
|
||||
output [AW-1:0] dstaddr; // destination address for RX dmode
|
||||
|
||||
// clock
|
||||
output clkchange; // indicates a clock change
|
||||
output [7:0] clkdiv; // mio clk clock setting
|
||||
output [15:0] clkphase0; // [7:0]=rising,[15:8]=falling
|
||||
output [15:0] clkphase1; // [7:0]=rising,[15:8]=falling
|
||||
|
||||
// status
|
||||
input tx_full; //tx fifo is full (should not happen!)
|
||||
input tx_prog_full; //tx fifo is nearing full
|
||||
input tx_empty; //tx fifo is empty
|
||||
input rx_full; //rx fifo is full (should not happen!)
|
||||
input rx_prog_full; //rx fifo is nearing full
|
||||
input rx_empty; //rx fifo is empty
|
||||
|
||||
//######################################################################
|
||||
//# BODY
|
||||
//######################################################################
|
||||
reg [20:0] config_reg;
|
||||
reg [15:0] status_reg;
|
||||
reg [31:0] clkdiv_reg;
|
||||
reg [63:0] addr_reg;
|
||||
reg [31:0] clkphase_reg;
|
||||
wire [7:0] status_in;
|
||||
wire reg_write;
|
||||
wire config_write;
|
||||
wire status_write;
|
||||
wire clkdiv_write;
|
||||
wire clkphase_write;
|
||||
wire idelay_write;
|
||||
wire odelay_write;
|
||||
wire addr0_write;
|
||||
wire addr1_write;
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
@ -76,19 +85,12 @@ module mio_regs (/*AUTOARG*/
|
||||
wire write_in; // From p2e of packet2emesh.v
|
||||
// End of automatics
|
||||
|
||||
//regs
|
||||
reg [18:0] config_reg;
|
||||
reg [7:0] status_reg;
|
||||
wire [7:0] status_in;
|
||||
reg [31:0] clkdiv_reg;
|
||||
reg [63:0] addr_reg;
|
||||
reg [31:0] clkphase_reg;
|
||||
|
||||
//#####################################
|
||||
//# DECODE
|
||||
//#####################################
|
||||
|
||||
packet2emesh #(.AW(AW))
|
||||
packet2emesh #(.AW(AW),
|
||||
.PW(PW))
|
||||
p2e (/*AUTOINST*/
|
||||
// Outputs
|
||||
.write_in (write_in),
|
||||
@ -119,10 +121,10 @@ module mio_regs (/*AUTOARG*/
|
||||
always @ (posedge clk or negedge nreset)
|
||||
if(!nreset)
|
||||
begin
|
||||
config_reg[18:0] <= DEF_CFG;
|
||||
config_reg[20:0] <= DEF_CFG;
|
||||
end
|
||||
else if(config_write)
|
||||
config_reg[18:0] <= data_in[18:0];
|
||||
config_reg[20:0] <= data_in[20:0];
|
||||
|
||||
assign tx_en = ~config_reg[0]; // tx disable
|
||||
assign rx_en = ~config_reg[1]; // rx disable
|
||||
@ -149,11 +151,11 @@ module mio_regs (/*AUTOARG*/
|
||||
|
||||
always @ (posedge clk or negedge nreset)
|
||||
if(!nreset)
|
||||
status_reg[7:0] <= 'b0;
|
||||
status_reg[15:0] <= 'b0;
|
||||
else if(status_write)
|
||||
status_reg[7:0] <= data_in[7:0];
|
||||
status_reg[15:0] <= data_in[7:0];
|
||||
else
|
||||
status_reg[7:0] <= {(status_reg[15:8] | status_in[7:0]), // sticky bits
|
||||
status_reg[15:0] <= {(status_reg[15:8] | status_in[7:0]), // sticky bits
|
||||
status_in[7:0]}; // immediate bits
|
||||
|
||||
//###############################
|
||||
|
@ -39,6 +39,9 @@ module mrx_io (/*AUTOARG*/
|
||||
wire [2*NMIO-1:0] ddr_data;
|
||||
reg [2*NMIO-1:0] sdr_data;
|
||||
reg byte0_sel;
|
||||
wire io_nreset;
|
||||
wire rx_frame;
|
||||
|
||||
|
||||
//########################################
|
||||
//# CLOCK, RESET
|
||||
@ -61,7 +64,7 @@ module mrx_io (/*AUTOARG*/
|
||||
//########################################
|
||||
|
||||
always @ (posedge rx_clk or negedge io_nreset)
|
||||
if(!nreset)
|
||||
if(!io_nreset)
|
||||
io_access <= 1'b0;
|
||||
else
|
||||
io_access <= rx_frame;
|
||||
@ -75,8 +78,8 @@ module mrx_io (/*AUTOARG*/
|
||||
.q2 (ddr_data[2*NMIO-1:NMIO]),
|
||||
.clk (rx_clk),
|
||||
.ce (rx_frame),
|
||||
.din (rx_packet[NMIO-1:0])
|
||||
);
|
||||
.din (rx_packet[NMIO-1:0]));
|
||||
|
||||
//########################################
|
||||
//# DATA (SDR)
|
||||
//########################################
|
||||
|
@ -38,6 +38,9 @@ module mrx_protocol (/*AUTOARG*/
|
||||
reg [2:0] mrx_state;
|
||||
reg [CW-1:0] mrx_count;
|
||||
reg fifo_access;
|
||||
wire shift;
|
||||
wire transfer_done;
|
||||
|
||||
|
||||
//##########################
|
||||
//# STATE MACHINE
|
||||
|
@ -35,19 +35,24 @@ module mtx_io (/*AUTOARG*/
|
||||
//# BODYINTER
|
||||
//#####################################################################
|
||||
|
||||
//regs
|
||||
localparam ASIC = `CFG_ASIC;
|
||||
|
||||
//Regs
|
||||
reg tx_access;
|
||||
wire [NMIO-1:0] tx_packet_ddr;
|
||||
reg [NMIO-1:0] tx_packet_sdr;
|
||||
reg byte0_sel;
|
||||
wire [2*NMIO-1:0] ddr_data;
|
||||
wire io_nreset;
|
||||
|
||||
|
||||
//########################################
|
||||
//# RESET
|
||||
//########################################
|
||||
|
||||
//synchronize reset to io_clk
|
||||
oh_rsync oh_rsync(.nrst_out (io_nreset),
|
||||
oh_rsync #(.ASIC(ASIC))
|
||||
oh_rsync(.nrst_out (io_nreset),
|
||||
.clk (io_clk),
|
||||
.nrst_in (nreset));
|
||||
|
||||
|
@ -3,7 +3,8 @@ module dut(/*AUTOARG*/
|
||||
// Outputs
|
||||
dut_active, clkout, wait_out, access_out, packet_out,
|
||||
// Inputs
|
||||
clk1, clk2, nreset, vdd, vss, access_in, packet_in, wait_in
|
||||
reg_write, reg_addr, clk1, clk2, nreset, vdd, vss, access_in,
|
||||
packet_in, wait_in
|
||||
);
|
||||
|
||||
//##########################################################################
|
||||
@ -16,9 +17,7 @@ module dut(/*AUTOARG*/
|
||||
parameter M_IDW = 6;
|
||||
parameter PW = 2*AW + 40;
|
||||
parameter N = 1;
|
||||
parameter IRQW = 10;
|
||||
parameter LAW = 16;
|
||||
|
||||
parameter IW = 10;
|
||||
|
||||
//clock,reset
|
||||
input clk1;
|
||||
@ -49,15 +48,12 @@ module dut(/*AUTOARG*/
|
||||
wire [PW-1:0] mem_packet;
|
||||
|
||||
/*AUTOINPUT*/
|
||||
// Beginning of automatic inputs (from unused autoinst inputs)
|
||||
input [5:0] reg_addr; // To pic of pic.v
|
||||
input reg_write; // To pic of pic.v
|
||||
// End of automatics
|
||||
|
||||
|
||||
wire ic_flush; // From pic of pic.v
|
||||
wire [IRQW-1:0] ic_ilat_reg; // From pic of pic.v
|
||||
wire [IRQW-1:0] ic_imask_reg; // From pic of pic.v
|
||||
wire [IRQW-1:0] ic_ipend_reg; // From pic of pic.v
|
||||
wire [LAW-1:0] ic_iret_reg; // From pic of pic.v
|
||||
wire ic_irq; // From pic of pic.v
|
||||
wire [LAW-1:0] ic_irq_addr; // From pic of pic.v
|
||||
wire [5:0] reg_addr;
|
||||
|
||||
// End of automatics
|
||||
/*AUTOWIRE*/
|
||||
@ -66,6 +62,13 @@ module dut(/*AUTOARG*/
|
||||
wire [AW-1:0] data_in; // From p2e of packet2emesh.v
|
||||
wire [1:0] datamode_in; // From p2e of packet2emesh.v
|
||||
wire [AW-1:0] dstaddr_in; // From p2e of packet2emesh.v
|
||||
wire ic_flush; // From pic of pic.v
|
||||
wire [IW-1:0] ic_ilat_reg; // From pic of pic.v
|
||||
wire [IW-1:0] ic_imask_reg; // From pic of pic.v
|
||||
wire [IW-1:0] ic_ipend_reg; // From pic of pic.v
|
||||
wire [AW-1:0] ic_iret_reg; // From pic of pic.v
|
||||
wire ic_irq; // From pic of pic.v
|
||||
wire [AW-1:0] ic_irq_addr; // From pic of pic.v
|
||||
wire [AW-1:0] srcaddr_in; // From p2e of packet2emesh.v
|
||||
wire write_in; // From p2e of packet2emesh.v
|
||||
// End of automatics
|
||||
@ -91,27 +94,28 @@ module dut(/*AUTOARG*/
|
||||
|
||||
|
||||
|
||||
pic #(.LAW(LAW),
|
||||
.IRQW(IRQW))
|
||||
pic (// Outputs
|
||||
.ic_flush (ic_flush),
|
||||
.ic_iret_reg (ic_iret_reg[LAW-1:0]),
|
||||
.ic_imask_reg (ic_imask_reg[IRQW-1:0]),
|
||||
.ic_ilat_reg (ic_ilat_reg[IRQW-1:0]),
|
||||
.ic_ipend_reg (ic_ipend_reg[IRQW-1:0]),
|
||||
.ic_irq (ic_irq),
|
||||
.ic_irq_addr (ic_irq_addr[LAW-1:0]),
|
||||
// Inputs
|
||||
pic #(.AW(AW),
|
||||
.IW(IW))
|
||||
pic (.reg_wdata (data_in[31:0]),
|
||||
.ext_irq ({(IW){1'b0}}),
|
||||
.sq_pc_next ({(AW){1'b0}}),
|
||||
.de_rti (1'b0),
|
||||
.sq_irq_en (1'b1),
|
||||
.sq_ic_wait (1'b0),
|
||||
.clk (clk1),
|
||||
/*AUTOINST*/
|
||||
// Outputs
|
||||
.ic_iret_reg (ic_iret_reg[AW-1:0]),
|
||||
.ic_imask_reg (ic_imask_reg[IW-1:0]),
|
||||
.ic_ilat_reg (ic_ilat_reg[IW-1:0]),
|
||||
.ic_ipend_reg (ic_ipend_reg[IW-1:0]),
|
||||
.ic_flush (ic_flush),
|
||||
.ic_irq (ic_irq),
|
||||
.ic_irq_addr (ic_irq_addr[AW-1:0]),
|
||||
// Inputs
|
||||
.nreset (nreset),
|
||||
.reg_write (reg_write),
|
||||
.reg_addr (reg_addr[5:0]),
|
||||
.reg_wdata (data_in[31:0]),
|
||||
.ext_irq ({(IRQW){1'b0}}),
|
||||
.sq_pc_next_ra ({(LAW){1'b0}}),
|
||||
.de_rti_e1 (1'b0),
|
||||
.sq_global_irq_en (1'b1),
|
||||
.sq_ic_wait (1'b0));
|
||||
.reg_addr (reg_addr[5:0]));
|
||||
|
||||
|
||||
endmodule
|
||||
|
@ -1,84 +1,77 @@
|
||||
//#############################################################################
|
||||
//# Function: Programmable Interrupt Controller #
|
||||
//#############################################################################
|
||||
//# Author: Andreas Olofsson #
|
||||
//# License: MIT (see LICENSE file in OH! repository) #
|
||||
//#############################################################################
|
||||
`include "pic_regmap.vh"
|
||||
//###########################################################################
|
||||
//# IRQC: Simple nessted interrupt controller
|
||||
//#
|
||||
//############################################################################
|
||||
module pic(/*AUTOARG*/
|
||||
// Outputs
|
||||
ic_flush, ic_iret_reg, ic_imask_reg, ic_ilat_reg, ic_ipend_reg,
|
||||
ic_irq, ic_irq_addr,
|
||||
// Inputs
|
||||
clk, nreset, reg_write, reg_addr, reg_wdata, ext_irq,
|
||||
sq_pc_next_ra, de_rti_e1, sq_global_irq_en, sq_ic_wait
|
||||
module pic #( parameter AW = 32, // address width
|
||||
parameter IW = 10, // number of interrupts supported
|
||||
parameter USE = 1 // set to 0 to disable
|
||||
)
|
||||
(
|
||||
// CLK, RESET
|
||||
input clk, // main clock
|
||||
input nreset, // active low async reset
|
||||
// REGISTER ACCESS
|
||||
input reg_write, // reg write signal
|
||||
input [5:0] reg_addr, // reg addr[5:0]
|
||||
input [31:0] reg_wdata, // data input
|
||||
output reg [AW-1:0] ic_iret_reg, // interrupt return register
|
||||
output reg [IW-1:0] ic_imask_reg, // interrupt mask register
|
||||
output reg [IW-1:0] ic_ilat_reg, // latched irq signals (but not started)
|
||||
output reg [IW-1:0] ic_ipend_reg, // interrrupts pending/active
|
||||
// PIPELINE
|
||||
input [IW-1:0] ext_irq, // interrupt signals
|
||||
input [AW-1:0] sq_pc_next, //PC to save to IRET
|
||||
input de_rti, //jump to IRET
|
||||
input sq_irq_en, // global interrupt enable
|
||||
input sq_ic_wait, // wait until it's safe to interrupt
|
||||
output ic_flush, // flush pipeline
|
||||
// INTERRUPT
|
||||
output ic_irq, // tells core to jump to adress in irq_addr
|
||||
output reg [AW-1:0] ic_irq_addr// interrupt vector
|
||||
);
|
||||
|
||||
//#####################################################################
|
||||
//# INTERFACE
|
||||
//#####################################################################
|
||||
//Parameters
|
||||
parameter LAW = 32;
|
||||
parameter IRQW = 10;
|
||||
/*TODO: Implement, don't wrap whole logic, let tool synthesize!
|
||||
generate
|
||||
if(USE==0)
|
||||
begin: off
|
||||
assign ic_imask_reg = 'b0;
|
||||
assign ic_ilat_reg = 'b0;
|
||||
assign ic_ipend_reg = 'b0;
|
||||
assign ic_irq = 'b0;
|
||||
assign ic_irq_addr = 'b0;
|
||||
assign ic_flush = 'b0;
|
||||
end
|
||||
else
|
||||
begin : g0
|
||||
*/
|
||||
|
||||
//Basic Interface
|
||||
input clk; //main clock
|
||||
input nreset; //active low async reset
|
||||
|
||||
//Sysreg Write Access
|
||||
input reg_write; //write signal
|
||||
input [5:0] reg_addr; //addr[5:0]
|
||||
input [31:0] reg_wdata; //data input
|
||||
|
||||
//Control signals
|
||||
input [IRQW-1:0] ext_irq; //interrupt signals
|
||||
input [LAW-1:0] sq_pc_next_ra; //PC to save to IRET
|
||||
input de_rti_e1; //jump to IRET
|
||||
input sq_global_irq_en; //disables all interrupts
|
||||
input sq_ic_wait; //wait until it's safe to interrupt (delete?)
|
||||
output ic_flush; //flush pipeline to get rid if all instructions
|
||||
|
||||
//Register Read Outputs
|
||||
output [LAW-1:0] ic_iret_reg; //interrupt return register
|
||||
output [IRQW-1:0] ic_imask_reg; //interrupt mask register
|
||||
output [IRQW-1:0] ic_ilat_reg; //latched ext_irq signals (but not started)
|
||||
output [IRQW-1:0] ic_ipend_reg; //interrrupts pending/active
|
||||
|
||||
//Interrupt Vector
|
||||
output ic_irq; //tells core to jump to adress in irq_addr
|
||||
output [LAW-1:0] ic_irq_addr; //interrupt vector
|
||||
|
||||
//#####################################################################
|
||||
//# BODY
|
||||
//#####################################################################
|
||||
//###############
|
||||
//# LOCAL WIRES
|
||||
//###############
|
||||
|
||||
//For loop integers
|
||||
integer i,j,m1,m2,n1,n2,p;
|
||||
|
||||
//Control registers
|
||||
reg [LAW-1:0] ic_iret_reg;
|
||||
reg [IRQW-1:0] ic_ilat_reg;
|
||||
reg [IRQW-1:0] ic_imask_reg;
|
||||
reg [IRQW-1:0] ic_ipend_reg;
|
||||
reg [LAW-1:0] ic_irq_addr;
|
||||
|
||||
//Functions
|
||||
reg [IRQW-1:0] ic_ilat_in;
|
||||
reg [IRQW-1:0] ic_ilat_priority_en_n;
|
||||
reg [IRQW-1:0] ic_ipend_priority_en_n;
|
||||
reg [IRQW-1:0] ic_irq_shadow;
|
||||
reg [IRQW-1:0] ic_irq_entry;
|
||||
|
||||
reg [IW-1:0] ic_ilat_in;
|
||||
reg [IW-1:0] ic_ilat_priority_en_n;
|
||||
reg [IW-1:0] ic_ipend_priority_en_n;
|
||||
reg [IW-1:0] ic_irq_shadow;
|
||||
reg [IW-1:0] ic_irq_entry;
|
||||
//Wires
|
||||
wire [IRQW-1:0] ic_masked_ilat;
|
||||
wire [LAW-1:0] ic_ivt[IRQW-1:0];
|
||||
wire [IRQW-1:0] ic_ipend_in;//changed to generate
|
||||
wire [IRQW:0] ic_ipend_shifted_reg;
|
||||
wire [IRQW-1:0] ic_imask_in;
|
||||
wire [IRQW-1:0] ic_irq_select;
|
||||
wire [IRQW-1:0] ic_global_en;
|
||||
wire [IRQW-1:0] ic_event;
|
||||
wire [IRQW-1:0] ic_ilat_set_data;
|
||||
wire [IRQW-1:0] ic_ilat_clear_data;
|
||||
|
||||
wire [IW-1:0] ic_masked_ilat;
|
||||
wire [AW-1:0] ic_ivt[IW-1:0];
|
||||
wire [IW-1:0] ic_ipend_in;
|
||||
wire [IW:0] ic_ipend_shifted_reg;
|
||||
wire [IW-1:0] ic_imask_in;
|
||||
wire [IW-1:0] ic_irq_select;
|
||||
wire [IW-1:0] ic_global_en;
|
||||
wire [IW-1:0] ic_event;
|
||||
wire [IW-1:0] ic_ilat_set_data;
|
||||
wire [IW-1:0] ic_ilat_clear_data;
|
||||
wire ic_write_imask;
|
||||
wire ic_write_ipend;
|
||||
wire ic_write_ilat;
|
||||
@ -96,30 +89,28 @@ module pic(/*AUTOARG*/
|
||||
assign ic_write_ilatclr = reg_write &(reg_addr[5:0] ==`ECORE_ILATCL);
|
||||
assign ic_write_iret = reg_write & reg_addr[5:0] ==`ECORE_IRET;
|
||||
|
||||
|
||||
//###########################
|
||||
//# RISING EDGE DETECTOR
|
||||
//###########################
|
||||
always @ (posedge clk or negedge nreset)
|
||||
if(!nreset)
|
||||
ic_irq_shadow[IRQW-1:0] <= 'b0;
|
||||
ic_irq_shadow[IW-1:0] <= 'b0;
|
||||
else
|
||||
ic_irq_shadow[IRQW-1:0] <= ext_irq[IRQW-1:0] ;
|
||||
|
||||
assign ic_event[IRQW-1:0] = ext_irq[IRQW-1:0] & ~ic_irq_shadow[IRQW-1:0] ;
|
||||
ic_irq_shadow[IW-1:0] <= ext_irq[IW-1:0] ;
|
||||
|
||||
assign ic_event[IW-1:0] = ext_irq[IW-1:0] & ~ic_irq_shadow[IW-1:0] ;
|
||||
|
||||
//###########################
|
||||
//# ILAT
|
||||
//###########################
|
||||
assign ic_ilat_set_data[IRQW-1:0] = reg_wdata[IRQW-1:0] |
|
||||
ic_ilat_reg[IRQW-1:0];
|
||||
assign ic_ilat_set_data[IW-1:0] = reg_wdata[IW-1:0] |
|
||||
ic_ilat_reg[IW-1:0];
|
||||
|
||||
assign ic_ilat_clear_data[IRQW-1:0] = ~reg_wdata[IRQW-1:0] &
|
||||
ic_ilat_reg[IRQW-1:0];
|
||||
assign ic_ilat_clear_data[IW-1:0] = ~reg_wdata[IW-1:0] &
|
||||
ic_ilat_reg[IW-1:0];
|
||||
|
||||
always @*
|
||||
for(i=0;i<IRQW;i=i+1)
|
||||
for(i=0;i<IW;i=i+1)
|
||||
ic_ilat_in[i] =(ic_write_ilat & reg_wdata[i])| // explicit write
|
||||
(ic_write_ilatset & ic_ilat_set_data[i]) | // ilatset
|
||||
(ic_event[i]) | // irq signal
|
||||
@ -131,32 +122,31 @@ module pic(/*AUTOARG*/
|
||||
//Don't clock gate the ILAT, should always be ready to recieve
|
||||
always @ (posedge clk or negedge nreset)
|
||||
if (!nreset)
|
||||
ic_ilat_reg[IRQW-1:0] <= 'b0;
|
||||
ic_ilat_reg[IW-1:0] <= 'b0;
|
||||
else
|
||||
ic_ilat_reg[IRQW-1:0] <= ic_ilat_in[IRQW-1:0];
|
||||
|
||||
ic_ilat_reg[IW-1:0] <= ic_ilat_in[IW-1:0];
|
||||
|
||||
//###########################
|
||||
//# IPEND
|
||||
//###########################
|
||||
assign ic_ipend_shifted_reg[IRQW:0] = {ic_ipend_reg[IRQW-1:0],1'b0};
|
||||
assign ic_ipend_shifted_reg[IW:0] = {ic_ipend_reg[IW-1:0],1'b0};
|
||||
|
||||
genvar q;
|
||||
generate
|
||||
for(q=IRQW-1;q>=0;q=q-1) begin : gen_ipend
|
||||
for(q=IW-1;q>=0;q=q-1) begin : gen_ipend
|
||||
assign ic_ipend_in[q]=(ic_irq_entry[q]) |
|
||||
(ic_ipend_reg[q] & ~de_rti_e1) |
|
||||
(ic_ipend_reg[q] & ~de_rti) |
|
||||
(|ic_ipend_shifted_reg[q:0]); //BUG?????
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always @ (posedge clk or negedge nreset)
|
||||
if (!nreset)
|
||||
ic_ipend_reg[IRQW-1:0] <= 'b0;
|
||||
ic_ipend_reg[IW-1:0] <= 'b0;
|
||||
else if(ic_write_ipend)
|
||||
ic_ipend_reg[IRQW-1:0] <= reg_wdata[IRQW-1:0];
|
||||
ic_ipend_reg[IW-1:0] <= reg_wdata[IW-1:0];
|
||||
else
|
||||
ic_ipend_reg[IRQW-1:0] <= ic_ipend_in[IRQW-1:0];
|
||||
ic_ipend_reg[IW-1:0] <= ic_ipend_in[IW-1:0];
|
||||
|
||||
//###########################
|
||||
//# IMASK
|
||||
@ -164,25 +154,25 @@ module pic(/*AUTOARG*/
|
||||
|
||||
always @ (posedge clk or negedge nreset)
|
||||
if (!nreset)
|
||||
ic_imask_reg[IRQW-1:0] <= 'b0;
|
||||
ic_imask_reg[IW-1:0] <= 'b0;
|
||||
else if(ic_write_imask)
|
||||
ic_imask_reg[IRQW-1:0] <= reg_wdata[IRQW-1:0];
|
||||
ic_imask_reg[IW-1:0] <= reg_wdata[IW-1:0];
|
||||
|
||||
//###########################
|
||||
//# IRET
|
||||
//###########################
|
||||
always @ (posedge clk)
|
||||
if(ic_flush)
|
||||
ic_iret_reg[LAW-1:0] <= sq_pc_next_ra[LAW-1:0];
|
||||
ic_iret_reg[AW-1:0] <= sq_pc_next[AW-1:0];
|
||||
else if(ic_write_iret)
|
||||
ic_iret_reg[LAW-1:0] <= reg_wdata[LAW-1:0];
|
||||
ic_iret_reg[AW-1:0] <= reg_wdata[AW-1:0];
|
||||
|
||||
//###########################
|
||||
//# IRQ VECTOR TABLE
|
||||
//###########################
|
||||
genvar k;
|
||||
generate
|
||||
for(k=0;k<IRQW;k=k+1) begin: irqs
|
||||
for(k=0;k<IW;k=k+1) begin: irqs
|
||||
assign ic_ivt[k]=(`IRQ_VECTOR_TABLE+4*k);
|
||||
end
|
||||
endgenerate
|
||||
@ -190,10 +180,10 @@ module pic(/*AUTOARG*/
|
||||
//mux
|
||||
always @*
|
||||
begin
|
||||
ic_irq_addr[LAW-1:0] = {(LAW){1'b0}};
|
||||
for(p=0;p<IRQW;p=p+1)
|
||||
ic_irq_addr[LAW-1:0] = ic_irq_addr[LAW-1:0] |
|
||||
({(LAW){ic_irq_entry[p]}} & ic_ivt[p]);
|
||||
ic_irq_addr[AW-1:0] = {(AW){1'b0}};
|
||||
for(p=0;p<IW;p=p+1)
|
||||
ic_irq_addr[AW-1:0] = ic_irq_addr[AW-1:0] |
|
||||
({(AW){ic_irq_entry[p]}} & ic_ivt[p]);
|
||||
end
|
||||
|
||||
//###########################
|
||||
@ -201,8 +191,8 @@ module pic(/*AUTOARG*/
|
||||
//###########################
|
||||
|
||||
//Masking interrupts
|
||||
assign ic_masked_ilat[IRQW-1:0] = ic_ilat_reg[IRQW-1:0] &
|
||||
~{ic_imask_reg[IRQW-1:1],1'b0};
|
||||
assign ic_masked_ilat[IW-1:0] = ic_ilat_reg[IW-1:0] &
|
||||
~{ic_imask_reg[IW-1:1],1'b0};
|
||||
|
||||
//Interrupt sent to sequencer if:
|
||||
//1.) no bit set in ipend for anything at that bit level or below
|
||||
@ -214,7 +204,7 @@ module pic(/*AUTOARG*/
|
||||
//This circuit is needed for the case when interrupts arrive simulataneously
|
||||
always @*
|
||||
begin
|
||||
for(m1=IRQW-1;m1>0;m1=m1-1)
|
||||
for(m1=IW-1;m1>0;m1=m1-1)
|
||||
begin
|
||||
ic_ilat_priority_en_n[m1]=1'b0;
|
||||
for(m2=m1-1;m2>=0;m2=m2-1)
|
||||
@ -224,11 +214,10 @@ module pic(/*AUTOARG*/
|
||||
ic_ilat_priority_en_n[0]=1'b0;
|
||||
end
|
||||
|
||||
|
||||
//IPEND PRIORITY
|
||||
always @*
|
||||
begin
|
||||
for(n1=IRQW-1;n1>=0;n1=n1-1)
|
||||
for(n1=IW-1;n1>=0;n1=n1-1)
|
||||
begin
|
||||
ic_ipend_priority_en_n[n1]=1'b0;
|
||||
for(n2=n1;n2>=0;n2=n2-1)
|
||||
@ -239,23 +228,25 @@ module pic(/*AUTOARG*/
|
||||
end
|
||||
|
||||
//Outgoing Interrupt (to sequencer)
|
||||
assign ic_irq_select[IRQW-1:0]= ic_masked_ilat[IRQW-1:0] & //only if the ILAT bit is not masked by IMASK
|
||||
~ic_ilat_priority_en_n[IRQW-1:0] & //only if there is no masked ilat bit <current
|
||||
~ic_ipend_priority_en_n[IRQW-1:0] & //only if there is no ipend bit <=current
|
||||
{(IRQW){sq_global_irq_en}}; //global vector for nested interrupts
|
||||
assign ic_irq_select[IW-1:0]= ic_masked_ilat[IW-1:0] & //only if the ILAT bit is not masked by IMASK
|
||||
~ic_ilat_priority_en_n[IW-1:0] & //only if there is no masked ilat bit <current
|
||||
~ic_ipend_priority_en_n[IW-1:0] & //only if there is no ipend bit <=current
|
||||
{(IW){sq_irq_en}}; //global vector for nested interrupts
|
||||
|
||||
//Pipelining interrupt to account for stall signal
|
||||
//TODO: Understand this better...
|
||||
always @ (posedge clk or negedge nreset)
|
||||
if(!nreset)
|
||||
ic_irq_entry[IRQW-1:0] <= 'b0;
|
||||
ic_irq_entry[IW-1:0] <= 'b0;
|
||||
else if(~sq_ic_wait)//includes fetch wait
|
||||
ic_irq_entry[IRQW-1:0] <= ic_irq_select[IRQW-1:0];// & ~ic_irq_entry[IRQW-1:0] ;
|
||||
ic_irq_entry[IW-1:0] <= ic_irq_select[IW-1:0];// & ~ic_irq_entry[IW-1:0] ;
|
||||
|
||||
assign ic_irq =|(ic_irq_entry[IRQW-1:0]);
|
||||
assign ic_irq =|(ic_irq_entry[IW-1:0]);
|
||||
|
||||
//Flush for one cycle interrupt pulse
|
||||
assign ic_flush =|(ic_irq_select[IRQW-1:0]);
|
||||
assign ic_flush =|(ic_irq_select[IW-1:0]);
|
||||
|
||||
endmodule // pic
|
||||
|
||||
|
||||
endmodule // interrupt_controller
|
||||
|
||||
|
3
src/spi/fpga/axi_spi_timing.xdc
Normal file
3
src/spi/fpga/axi_spi_timing.xdc
Normal file
@ -0,0 +1,3 @@
|
||||
# SPI slave clock
|
||||
create_clock -name spi_s_sclk -period 10 [get_ports spi_s_sclk]
|
||||
|
6
src/spi/fpga/bit2bin.bif
Normal file
6
src/spi/fpga/bit2bin.bif
Normal file
@ -0,0 +1,6 @@
|
||||
the_ROM_image:
|
||||
{
|
||||
[bootloader]dummy.elf
|
||||
./system.runs/impl_1/system_wrapper.bit
|
||||
}
|
||||
|
15
src/spi/fpga/build.sh
Executable file
15
src/spi/fpga/build.sh
Executable file
@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
#clean up
|
||||
rm system_wrapper.bit.bin bit2bin.bin
|
||||
|
||||
#package IP
|
||||
vivado -mode batch -source package.tcl
|
||||
|
||||
#create bit stream
|
||||
vivado -mode batch -source run.tcl
|
||||
|
||||
#xilinx stuff...
|
||||
bootgen -image bit2bin.bif -split bin
|
||||
cp system_wrapper.bit.bin parallella.bit.bin
|
||||
|
21
src/spi/fpga/clean.sh
Executable file
21
src/spi/fpga/clean.sh
Executable file
@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
rm -rf component.xml
|
||||
rm -rf parallella.bit.bin
|
||||
rm -rf parallella_spi.cache
|
||||
rm -rf parallella_spi.hw
|
||||
rm -rf parallella_spi.sim
|
||||
rm -rf parallella_spi.xpr
|
||||
rm -rf parallella_spi.zip
|
||||
rm -rf reports
|
||||
rm -rf results
|
||||
rm -rf src
|
||||
rm -rf system.cache
|
||||
rm -rf system.hw
|
||||
rm -rf system.runs
|
||||
rm -rf system.sim
|
||||
rm -rf system.srcs
|
||||
rm -rf system_wrapper.bit.bin
|
||||
rm -rf system.xpr
|
||||
rm -rf vivado*.jou
|
||||
rm -rf vivado*.log
|
||||
rm -rf xgui
|
BIN
src/spi/fpga/dummy.elf
Normal file
BIN
src/spi/fpga/dummy.elf
Normal file
Binary file not shown.
23
src/spi/fpga/ip_params.tcl
Normal file
23
src/spi/fpga/ip_params.tcl
Normal file
@ -0,0 +1,23 @@
|
||||
# NOTE: See UG1118 for more information
|
||||
|
||||
set design parallella_spi
|
||||
set projdir ./
|
||||
set root "../.."
|
||||
set partname "xc7z020clg400-1"
|
||||
|
||||
set hdl_files [list \
|
||||
$root/spi/hdl \
|
||||
$root/common/hdl/ \
|
||||
$root/emesh/hdl \
|
||||
$root/emmu/hdl \
|
||||
$root/axi/hdl \
|
||||
$root/emailbox/hdl \
|
||||
$root/edma/hdl \
|
||||
$root/elink/hdl \
|
||||
$root/parallella/hdl \
|
||||
]
|
||||
|
||||
set ip_files []
|
||||
|
||||
set constraints_files []
|
||||
|
3
src/spi/fpga/package.tcl
Normal file
3
src/spi/fpga/package.tcl
Normal file
@ -0,0 +1,3 @@
|
||||
#STEP1: DEFINE KEY PARAMETERS
|
||||
source ./ip_params.tcl
|
||||
source ../../common/fpga/create_ip.tcl
|
12
src/spi/fpga/run.tcl
Normal file
12
src/spi/fpga/run.tcl
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
#STEP1: DEFINE KEY PARAMETERS
|
||||
source ./run_params.tcl
|
||||
|
||||
#STEP2: CREATE PROJECT AND READ IN FILES
|
||||
source ../../common/fpga/system_init.tcl
|
||||
|
||||
#STEP 3 (OPTIONAL): EDIT system.bd in VIVADO gui, then go to STEP 4.
|
||||
##...
|
||||
|
||||
#STEP 4: SYNTEHSIZE AND CREATE BITSTRAM
|
||||
source ../../common/fpga/system_build.tcl
|
23
src/spi/fpga/run_params.tcl
Normal file
23
src/spi/fpga/run_params.tcl
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
#Design name ("system" recommended)
|
||||
set design system
|
||||
|
||||
#Project directory ("." recommended)
|
||||
set projdir ./
|
||||
|
||||
#Device name
|
||||
set partname "xc7z020clg400-1"
|
||||
|
||||
#Paths to all IP blocks to use in Vivado "system.bd"
|
||||
|
||||
set ip_repos [list "."]
|
||||
|
||||
#All source files
|
||||
set hdl_files []
|
||||
|
||||
#All constraints files
|
||||
set constraints_files [list \
|
||||
../../parallella/fpga/parallella_io.xdc \
|
||||
../../parallella/fpga/parallella_7020_io.xdc \
|
||||
./axi_spi_timing.xdc \
|
||||
]
|
227
src/spi/fpga/system_bd.tcl
Normal file
227
src/spi/fpga/system_bd.tcl
Normal file
@ -0,0 +1,227 @@
|
||||
|
||||
################################################################
|
||||
# This is a generated script based on design: system
|
||||
#
|
||||
# Though there are limitations about the generated script,
|
||||
# the main purpose of this utility is to make learning
|
||||
# IP Integrator Tcl commands easier.
|
||||
################################################################
|
||||
|
||||
################################################################
|
||||
# Check if script is running in correct Vivado version.
|
||||
################################################################
|
||||
set scripts_vivado_version 2015.2
|
||||
set current_vivado_version [version -short]
|
||||
|
||||
if { [string first $scripts_vivado_version $current_vivado_version] == -1 } {
|
||||
puts ""
|
||||
puts "ERROR: This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script."
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
################################################################
|
||||
# START
|
||||
################################################################
|
||||
|
||||
# To test this script, run the following commands from Vivado Tcl console:
|
||||
# source system_script.tcl
|
||||
|
||||
# If you do not already have a project created,
|
||||
# you can create a project using the following command:
|
||||
# create_project project_1 myproj -part xc7z020clg400-1
|
||||
|
||||
# CHECKING IF PROJECT EXISTS
|
||||
if { [get_projects -quiet] eq "" } {
|
||||
puts "ERROR: Please open or create a project!"
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
|
||||
# CHANGE DESIGN NAME HERE
|
||||
set design_name system
|
||||
|
||||
# If you do not already have an existing IP Integrator design open,
|
||||
# you can create a design using the following command:
|
||||
# create_bd_design $design_name
|
||||
|
||||
# Creating design if needed
|
||||
set errMsg ""
|
||||
set nRet 0
|
||||
|
||||
set cur_design [current_bd_design -quiet]
|
||||
set list_cells [get_bd_cells -quiet]
|
||||
|
||||
if { ${design_name} eq "" } {
|
||||
# USE CASES:
|
||||
# 1) Design_name not set
|
||||
|
||||
set errMsg "ERROR: Please set the variable <design_name> to a non-empty value."
|
||||
set nRet 1
|
||||
|
||||
} elseif { ${cur_design} ne "" && ${list_cells} eq "" } {
|
||||
# USE CASES:
|
||||
# 2): Current design opened AND is empty AND names same.
|
||||
# 3): Current design opened AND is empty AND names diff; design_name NOT in project.
|
||||
# 4): Current design opened AND is empty AND names diff; design_name exists in project.
|
||||
|
||||
if { $cur_design ne $design_name } {
|
||||
puts "INFO: Changing value of <design_name> from <$design_name> to <$cur_design> since current design is empty."
|
||||
set design_name [get_property NAME $cur_design]
|
||||
}
|
||||
puts "INFO: Constructing design in IPI design <$cur_design>..."
|
||||
|
||||
} elseif { ${cur_design} ne "" && $list_cells ne "" && $cur_design eq $design_name } {
|
||||
# USE CASES:
|
||||
# 5) Current design opened AND has components AND same names.
|
||||
|
||||
set errMsg "ERROR: Design <$design_name> already exists in your project, please set the variable <design_name> to another value."
|
||||
set nRet 1
|
||||
} elseif { [get_files -quiet ${design_name}.bd] ne "" } {
|
||||
# USE CASES:
|
||||
# 6) Current opened design, has components, but diff names, design_name exists in project.
|
||||
# 7) No opened design, design_name exists in project.
|
||||
|
||||
set errMsg "ERROR: Design <$design_name> already exists in your project, please set the variable <design_name> to another value."
|
||||
set nRet 2
|
||||
|
||||
} else {
|
||||
# USE CASES:
|
||||
# 8) No opened design, design_name not in project.
|
||||
# 9) Current opened design, has components, but diff names, design_name not in project.
|
||||
|
||||
puts "INFO: Currently there is no design <$design_name> in project, so creating one..."
|
||||
|
||||
create_bd_design $design_name
|
||||
|
||||
puts "INFO: Making design <$design_name> as current_bd_design."
|
||||
current_bd_design $design_name
|
||||
|
||||
}
|
||||
|
||||
puts "INFO: Currently the variable <design_name> is equal to \"$design_name\"."
|
||||
|
||||
if { $nRet != 0 } {
|
||||
puts $errMsg
|
||||
return $nRet
|
||||
}
|
||||
|
||||
##################################################################
|
||||
# DESIGN PROCs
|
||||
##################################################################
|
||||
|
||||
|
||||
|
||||
# Procedure to create entire design; Provide argument to make
|
||||
# procedure reusable. If parentCell is "", will use root.
|
||||
proc create_root_design { parentCell } {
|
||||
|
||||
if { $parentCell eq "" } {
|
||||
set parentCell [get_bd_cells /]
|
||||
}
|
||||
|
||||
# Get object for parentCell
|
||||
set parentObj [get_bd_cells $parentCell]
|
||||
if { $parentObj == "" } {
|
||||
puts "ERROR: Unable to find parent cell <$parentCell>!"
|
||||
return
|
||||
}
|
||||
|
||||
# Make sure parentObj is hier blk
|
||||
set parentType [get_property TYPE $parentObj]
|
||||
if { $parentType ne "hier" } {
|
||||
puts "ERROR: Parent <$parentObj> has TYPE = <$parentType>. Expected to be <hier>."
|
||||
return
|
||||
}
|
||||
|
||||
# Save current instance; Restore later
|
||||
set oldCurInst [current_bd_instance .]
|
||||
|
||||
# Set parent object as current
|
||||
current_bd_instance $parentObj
|
||||
|
||||
|
||||
# Create interface ports
|
||||
|
||||
# Create ports
|
||||
set gpio_n [ create_bd_port -dir IO -from 23 -to 0 gpio_n ]
|
||||
set gpio_p [ create_bd_port -dir IO -from 23 -to 0 gpio_p ]
|
||||
|
||||
# Create instance: parallella_spi_0, and set properties
|
||||
set parallella_spi_0 [ create_bd_cell -type ip -vlnv www.parallella.org:user:parallella_spi:1.0 parallella_spi_0 ]
|
||||
|
||||
# Create instance: proc_sys_reset_0, and set properties
|
||||
set proc_sys_reset_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 proc_sys_reset_0 ]
|
||||
|
||||
# Create instance: processing_system7_0, and set properties
|
||||
set processing_system7_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:processing_system7:5.5 processing_system7_0 ]
|
||||
set_property -dict [ list CONFIG.PCW_CORE0_FIQ_INTR {0} \
|
||||
CONFIG.PCW_ENET0_ENET0_IO {MIO 16 .. 27} CONFIG.PCW_ENET0_GRP_MDIO_ENABLE {1} \
|
||||
CONFIG.PCW_ENET0_PERIPHERAL_ENABLE {1} CONFIG.PCW_ENET1_PERIPHERAL_ENABLE {0} \
|
||||
CONFIG.PCW_EN_CLK3_PORT {1} CONFIG.PCW_FPGA0_PERIPHERAL_FREQMHZ {100} \
|
||||
CONFIG.PCW_FPGA3_PERIPHERAL_FREQMHZ {100} CONFIG.PCW_GPIO_EMIO_GPIO_ENABLE {1} \
|
||||
CONFIG.PCW_GPIO_MIO_GPIO_ENABLE {1} CONFIG.PCW_GPIO_MIO_GPIO_IO {MIO} \
|
||||
CONFIG.PCW_I2C0_I2C0_IO {EMIO} CONFIG.PCW_I2C0_PERIPHERAL_ENABLE {1} \
|
||||
CONFIG.PCW_I2C0_RESET_ENABLE {0} CONFIG.PCW_IRQ_F2P_INTR {1} \
|
||||
CONFIG.PCW_IRQ_F2P_MODE {DIRECT} CONFIG.PCW_PRESET_BANK1_VOLTAGE {LVCMOS 1.8V} \
|
||||
CONFIG.PCW_QSPI_GRP_SINGLE_SS_ENABLE {1} CONFIG.PCW_QSPI_PERIPHERAL_ENABLE {1} \
|
||||
CONFIG.PCW_SD1_PERIPHERAL_ENABLE {1} CONFIG.PCW_SD1_SD1_IO {MIO 10 .. 15} \
|
||||
CONFIG.PCW_SDIO_PERIPHERAL_FREQMHZ {50} CONFIG.PCW_UART1_PERIPHERAL_ENABLE {1} \
|
||||
CONFIG.PCW_UART1_UART1_IO {MIO 8 .. 9} CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY0 {0.434} \
|
||||
CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY1 {0.398} CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY2 {0.410} \
|
||||
CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY3 {0.455} CONFIG.PCW_UIPARAM_DDR_CL {9} \
|
||||
CONFIG.PCW_UIPARAM_DDR_CWL {9} CONFIG.PCW_UIPARAM_DDR_DEVICE_CAPACITY {8192 MBits} \
|
||||
CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_0 {0.315} CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_1 {0.391} \
|
||||
CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_2 {0.374} CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_3 {0.271} \
|
||||
CONFIG.PCW_UIPARAM_DDR_DRAM_WIDTH {32 Bits} CONFIG.PCW_UIPARAM_DDR_FREQ_MHZ {400.00} \
|
||||
CONFIG.PCW_UIPARAM_DDR_PARTNO {Custom} CONFIG.PCW_UIPARAM_DDR_T_FAW {50} \
|
||||
CONFIG.PCW_UIPARAM_DDR_T_RAS_MIN {40} CONFIG.PCW_UIPARAM_DDR_T_RC {60} \
|
||||
CONFIG.PCW_UIPARAM_DDR_T_RCD {9} CONFIG.PCW_UIPARAM_DDR_T_RP {9} \
|
||||
CONFIG.PCW_UIPARAM_DDR_USE_INTERNAL_VREF {1} CONFIG.PCW_USB0_PERIPHERAL_ENABLE {1} \
|
||||
CONFIG.PCW_USB0_RESET_ENABLE {0} CONFIG.PCW_USB1_PERIPHERAL_ENABLE {1} \
|
||||
CONFIG.PCW_USE_FABRIC_INTERRUPT {1} CONFIG.PCW_USE_M_AXI_GP1 {1} \
|
||||
CONFIG.PCW_USE_S_AXI_HP0 {1} ] $processing_system7_0
|
||||
|
||||
# Create instance: processing_system7_0_axi_periph, and set properties
|
||||
set processing_system7_0_axi_periph [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 processing_system7_0_axi_periph ]
|
||||
set_property -dict [ list CONFIG.NUM_MI {1} ] $processing_system7_0_axi_periph
|
||||
|
||||
# Create instance: sys_concat_intc, and set properties
|
||||
set sys_concat_intc [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 sys_concat_intc ]
|
||||
set_property -dict [ list CONFIG.NUM_PORTS {16} ] $sys_concat_intc
|
||||
|
||||
# Create interface connections
|
||||
connect_bd_intf_net -intf_net processing_system7_0_M_AXI_GP0 [get_bd_intf_pins processing_system7_0/M_AXI_GP0] [get_bd_intf_pins processing_system7_0_axi_periph/S00_AXI]
|
||||
connect_bd_intf_net -intf_net processing_system7_0_axi_periph_M00_AXI [get_bd_intf_pins parallella_spi_0/s_axi] [get_bd_intf_pins processing_system7_0_axi_periph/M00_AXI]
|
||||
|
||||
# Create port connections
|
||||
connect_bd_net -net parallella_spi_0_constant_zero [get_bd_pins sys_concat_intc/In0] [get_bd_pins sys_concat_intc/In1] [get_bd_pins sys_concat_intc/In2] [get_bd_pins sys_concat_intc/In3] [get_bd_pins sys_concat_intc/In4] [get_bd_pins sys_concat_intc/In5] [get_bd_pins sys_concat_intc/In6] [get_bd_pins sys_concat_intc/In7] [get_bd_pins sys_concat_intc/In8] [get_bd_pins sys_concat_intc/In10] [get_bd_pins sys_concat_intc/In11] [get_bd_pins sys_concat_intc/In12] [get_bd_pins sys_concat_intc/In13] [get_bd_pins sys_concat_intc/In14] [get_bd_pins sys_concat_intc/In15]
|
||||
connect_bd_net -net parallella_spi_0_gpio_n [get_bd_ports gpio_n] [get_bd_pins parallella_spi_0/gpio_n]
|
||||
connect_bd_net -net parallella_spi_0_gpio_p [get_bd_ports gpio_p] [get_bd_pins parallella_spi_0/gpio_p]
|
||||
connect_bd_net -net parallella_spi_0_spi_irq [get_bd_pins parallella_spi_0/spi_irq] [get_bd_pins sys_concat_intc/In9]
|
||||
connect_bd_net -net proc_sys_reset_0_interconnect_aresetn [get_bd_pins proc_sys_reset_0/interconnect_aresetn] [get_bd_pins processing_system7_0_axi_periph/ARESETN]
|
||||
connect_bd_net -net proc_sys_reset_0_peripheral_aresetn [get_bd_pins parallella_spi_0/s_axi_aresetn] [get_bd_pins parallella_spi_0/sys_nreset] [get_bd_pins proc_sys_reset_0/peripheral_aresetn] [get_bd_pins processing_system7_0_axi_periph/M00_ARESETN] [get_bd_pins processing_system7_0_axi_periph/S00_ARESETN]
|
||||
connect_bd_net -net processing_system7_0_FCLK_CLK0 [get_bd_pins parallella_spi_0/sys_clk] [get_bd_pins proc_sys_reset_0/slowest_sync_clk] [get_bd_pins processing_system7_0/FCLK_CLK0] [get_bd_pins processing_system7_0/M_AXI_GP0_ACLK] [get_bd_pins processing_system7_0/M_AXI_GP1_ACLK] [get_bd_pins processing_system7_0/S_AXI_HP0_ACLK] [get_bd_pins processing_system7_0_axi_periph/ACLK] [get_bd_pins processing_system7_0_axi_periph/M00_ACLK] [get_bd_pins processing_system7_0_axi_periph/S00_ACLK]
|
||||
connect_bd_net -net processing_system7_0_FCLK_RESET0_N [get_bd_pins proc_sys_reset_0/ext_reset_in] [get_bd_pins processing_system7_0/FCLK_RESET0_N]
|
||||
connect_bd_net -net sys_concat_intc_dout [get_bd_pins processing_system7_0/IRQ_F2P] [get_bd_pins sys_concat_intc/dout]
|
||||
|
||||
# Create address segments
|
||||
create_bd_addr_seg -range 0x40000000 -offset 0x40000000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs parallella_spi_0/s_axi/axi_lite] SEG_parallella_spi_0_axi_lite
|
||||
|
||||
|
||||
# Restore current instance
|
||||
current_bd_instance $oldCurInst
|
||||
|
||||
save_bd_design
|
||||
}
|
||||
# End of create_root_design()
|
||||
|
||||
|
||||
##################################################################
|
||||
# MAIN FLOW
|
||||
##################################################################
|
||||
|
||||
create_root_design ""
|
||||
|
||||
|
30
src/spi/fpga/system_params.tcl
Normal file
30
src/spi/fpga/system_params.tcl
Normal file
@ -0,0 +1,30 @@
|
||||
# NOTE: See UG1118 for more information
|
||||
|
||||
#########################################
|
||||
# VARIABLES
|
||||
#########################################
|
||||
set design axi_spi
|
||||
set projdir ./
|
||||
set root "../.."
|
||||
set partname "xc7z020clg400-1"
|
||||
|
||||
set hdl_files [list \
|
||||
$root/spi/hdl \
|
||||
$root/common/hdl/ \
|
||||
$root/emesh/hdl \
|
||||
$root/emmu/hdl \
|
||||
$root/axi/hdl \
|
||||
$root/emailbox/hdl \
|
||||
$root/edma/hdl \
|
||||
$root/elink/hdl \
|
||||
$root/parallella/hdl \
|
||||
]
|
||||
|
||||
set ip_files []
|
||||
|
||||
set constraints_files [list \
|
||||
../../parallella/fpga/parallella_io.xdc \
|
||||
../../parallella/fpga/parallella_7020_io.xdc \
|
||||
./axi_spi_timing.xdc \
|
||||
]
|
||||
|
223
src/spi/hdl/axi_spi.v
Normal file
223
src/spi/hdl/axi_spi.v
Normal file
@ -0,0 +1,223 @@
|
||||
//#############################################################################
|
||||
//# Purpose: AXI spi module #
|
||||
//#############################################################################
|
||||
//# Author: Ola Jeppsson #
|
||||
//# SPDX-License-Identifier: MIT #
|
||||
//#############################################################################
|
||||
|
||||
module axi_spi(/*AUTOARG*/
|
||||
// Outputs
|
||||
spi_s_miso, spi_m_ss, spi_m_sclk, spi_m_mosi, spi_irq,
|
||||
s_axi_wready, s_axi_rvalid, s_axi_rresp, s_axi_rlast, s_axi_rid,
|
||||
s_axi_rdata, s_axi_bvalid, s_axi_bresp, s_axi_bid, s_axi_awready,
|
||||
s_axi_arready,
|
||||
// Inputs
|
||||
spi_s_ss, spi_s_sclk, spi_s_mosi, spi_m_miso, s_axi_wvalid,
|
||||
s_axi_wstrb, s_axi_wlast, s_axi_wid, s_axi_wdata, s_axi_rready,
|
||||
s_axi_bready, s_axi_awvalid, s_axi_awsize, s_axi_awqos,
|
||||
s_axi_awprot, s_axi_awlock, s_axi_awlen, s_axi_awid, s_axi_awcache,
|
||||
s_axi_awburst, s_axi_awaddr, s_axi_arvalid, s_axi_arsize,
|
||||
s_axi_arqos, s_axi_arprot, s_axi_arlock, s_axi_arlen, s_axi_arid,
|
||||
s_axi_aresetn, s_axi_arcache, s_axi_arburst, s_axi_araddr,
|
||||
sys_nreset, sys_clk
|
||||
);
|
||||
|
||||
//########################################################
|
||||
// INTERFACE
|
||||
//########################################################
|
||||
parameter AW = 32; // address width
|
||||
parameter PW = 2*AW+40; // packet width
|
||||
parameter ID = 12'h810; // addr[31:20] id
|
||||
parameter S_IDW = 12; // ID width for S_AXI
|
||||
|
||||
//clk, reset
|
||||
input sys_nreset; // active low async reset
|
||||
input sys_clk; // system clock for AXI
|
||||
|
||||
//############################
|
||||
// HOST GENERATERD
|
||||
//############################
|
||||
//Slave Write
|
||||
wire s_wr_access;
|
||||
wire [PW-1:0] s_wr_packet;
|
||||
wire s_wr_wait;
|
||||
|
||||
//Slave Read Request
|
||||
wire s_rd_access;
|
||||
wire [PW-1:0] s_rd_packet;
|
||||
wire s_rd_wait;
|
||||
|
||||
//Slave Read Response
|
||||
wire s_rr_access;
|
||||
wire [PW-1:0] s_rr_packet;
|
||||
wire s_rr_wait;
|
||||
|
||||
//##############################################################
|
||||
|
||||
/*AUTOINPUT*/
|
||||
// Beginning of automatic inputs (from unused autoinst inputs)
|
||||
input [31:0] s_axi_araddr; // To esaxi of esaxi.v
|
||||
input [1:0] s_axi_arburst; // To esaxi of esaxi.v
|
||||
input [3:0] s_axi_arcache; // To esaxi of esaxi.v
|
||||
input s_axi_aresetn; // To esaxi of esaxi.v
|
||||
input [S_IDW-1:0] s_axi_arid; // To esaxi of esaxi.v
|
||||
input [7:0] s_axi_arlen; // To esaxi of esaxi.v
|
||||
input s_axi_arlock; // To esaxi of esaxi.v
|
||||
input [2:0] s_axi_arprot; // To esaxi of esaxi.v
|
||||
input [3:0] s_axi_arqos; // To esaxi of esaxi.v
|
||||
input [2:0] s_axi_arsize; // To esaxi of esaxi.v
|
||||
input s_axi_arvalid; // To esaxi of esaxi.v
|
||||
input [31:0] s_axi_awaddr; // To esaxi of esaxi.v
|
||||
input [1:0] s_axi_awburst; // To esaxi of esaxi.v
|
||||
input [3:0] s_axi_awcache; // To esaxi of esaxi.v
|
||||
input [S_IDW-1:0] s_axi_awid; // To esaxi of esaxi.v
|
||||
input [7:0] s_axi_awlen; // To esaxi of esaxi.v
|
||||
input s_axi_awlock; // To esaxi of esaxi.v
|
||||
input [2:0] s_axi_awprot; // To esaxi of esaxi.v
|
||||
input [3:0] s_axi_awqos; // To esaxi of esaxi.v
|
||||
input [2:0] s_axi_awsize; // To esaxi of esaxi.v
|
||||
input s_axi_awvalid; // To esaxi of esaxi.v
|
||||
input s_axi_bready; // To esaxi of esaxi.v
|
||||
input s_axi_rready; // To esaxi of esaxi.v
|
||||
input [31:0] s_axi_wdata; // To esaxi of esaxi.v
|
||||
input [S_IDW-1:0] s_axi_wid; // To esaxi of esaxi.v
|
||||
input s_axi_wlast; // To esaxi of esaxi.v
|
||||
input [3:0] s_axi_wstrb; // To esaxi of esaxi.v
|
||||
input s_axi_wvalid; // To esaxi of esaxi.v
|
||||
input spi_m_miso; // To spi of spi.v
|
||||
input spi_s_mosi; // To spi of spi.v
|
||||
input spi_s_sclk; // To spi of spi.v
|
||||
input spi_s_ss; // To spi of spi.v
|
||||
// End of automatics
|
||||
|
||||
/*AUTOOUTPUT*/
|
||||
// Beginning of automatic outputs (from unused autoinst outputs)
|
||||
output s_axi_arready; // From esaxi of esaxi.v
|
||||
output s_axi_awready; // From esaxi of esaxi.v
|
||||
output [S_IDW-1:0] s_axi_bid; // From esaxi of esaxi.v
|
||||
output [1:0] s_axi_bresp; // From esaxi of esaxi.v
|
||||
output s_axi_bvalid; // From esaxi of esaxi.v
|
||||
output [31:0] s_axi_rdata; // From esaxi of esaxi.v
|
||||
output [S_IDW-1:0] s_axi_rid; // From esaxi of esaxi.v
|
||||
output s_axi_rlast; // From esaxi of esaxi.v
|
||||
output [1:0] s_axi_rresp; // From esaxi of esaxi.v
|
||||
output s_axi_rvalid; // From esaxi of esaxi.v
|
||||
output s_axi_wready; // From esaxi of esaxi.v
|
||||
output spi_irq; // From spi of spi.v
|
||||
output spi_m_mosi; // From spi of spi.v
|
||||
output spi_m_sclk; // From spi of spi.v
|
||||
output spi_m_ss; // From spi of spi.v
|
||||
output spi_s_miso; // From spi of spi.v
|
||||
// End of automatics
|
||||
|
||||
/*AUTOWIRE*/
|
||||
|
||||
/*AUTOREG*/
|
||||
|
||||
wire spi_wait_out;
|
||||
wire spi_access_out;
|
||||
wire [PW-1:0] spi_packet_out;
|
||||
wire spi_access_in;
|
||||
wire [PW-1:0] spi_packet_in;
|
||||
wire spi_wait_in;
|
||||
|
||||
/* spi AUTO_TEMPLATE (.\([sm]_.*\) (spi_\1[]),); */
|
||||
spi #(.AW(AW))
|
||||
spi (
|
||||
//Outputs
|
||||
.hw_en (1'b1),
|
||||
.wait_out (spi_wait_out),
|
||||
.access_out (spi_access_out),
|
||||
.packet_out (spi_packet_out[PW-1:0]),
|
||||
//Inputs
|
||||
.nreset (sys_nreset),
|
||||
.clk (sys_clk),
|
||||
.access_in (spi_access_in),
|
||||
.packet_in (spi_packet_in[PW-1:0]),
|
||||
.wait_in (spi_wait_in),
|
||||
/*AUTOINST*/
|
||||
// Outputs
|
||||
.spi_irq (spi_irq),
|
||||
.m_sclk (spi_m_sclk), // Templated
|
||||
.m_mosi (spi_m_mosi), // Templated
|
||||
.m_ss (spi_m_ss), // Templated
|
||||
.s_miso (spi_s_miso), // Templated
|
||||
// Inputs
|
||||
.m_miso (spi_m_miso), // Templated
|
||||
.s_sclk (spi_s_sclk), // Templated
|
||||
.s_mosi (spi_s_mosi), // Templated
|
||||
.s_ss (spi_s_ss)); // Templated
|
||||
|
||||
//########################################################
|
||||
//AXI SLAVE
|
||||
//########################################################
|
||||
|
||||
emesh_mux #(.N(2),.AW(AW))
|
||||
mux2(// Outputs
|
||||
.wait_out ({s_rd_wait, s_wr_wait}),
|
||||
.access_out (spi_access_in),
|
||||
.packet_out (spi_packet_in[PW-1:0]),
|
||||
// Inputs
|
||||
.access_in ({s_rd_access, s_wr_access}),
|
||||
.packet_in ({s_rd_packet[PW-1:0], s_wr_packet[PW-1:0]}),
|
||||
.wait_in (s_rr_wait)
|
||||
);
|
||||
|
||||
esaxi #(.S_IDW(S_IDW))
|
||||
esaxi (.s_axi_aclk (sys_clk),
|
||||
.wr_access (s_wr_access),
|
||||
.wr_packet (s_wr_packet[PW-1:0]),
|
||||
.rr_wait (s_rr_wait),
|
||||
.rd_wait (s_rd_wait),
|
||||
.rr_access (spi_access_out),
|
||||
.rr_packet (spi_packet_out[PW-1:0]),
|
||||
.wr_wait (s_wr_wait),
|
||||
.rd_access (s_rd_access),
|
||||
.rd_packet (s_rd_packet[PW-1:0]),
|
||||
/*AUTOINST*/
|
||||
// Outputs
|
||||
.s_axi_arready (s_axi_arready),
|
||||
.s_axi_awready (s_axi_awready),
|
||||
.s_axi_bid (s_axi_bid[S_IDW-1:0]),
|
||||
.s_axi_bresp (s_axi_bresp[1:0]),
|
||||
.s_axi_bvalid (s_axi_bvalid),
|
||||
.s_axi_rid (s_axi_rid[S_IDW-1:0]),
|
||||
.s_axi_rdata (s_axi_rdata[31:0]),
|
||||
.s_axi_rlast (s_axi_rlast),
|
||||
.s_axi_rresp (s_axi_rresp[1:0]),
|
||||
.s_axi_rvalid (s_axi_rvalid),
|
||||
.s_axi_wready (s_axi_wready),
|
||||
// Inputs
|
||||
.s_axi_aresetn (s_axi_aresetn),
|
||||
.s_axi_arid (s_axi_arid[S_IDW-1:0]),
|
||||
.s_axi_araddr (s_axi_araddr[31:0]),
|
||||
.s_axi_arburst (s_axi_arburst[1:0]),
|
||||
.s_axi_arcache (s_axi_arcache[3:0]),
|
||||
.s_axi_arlock (s_axi_arlock),
|
||||
.s_axi_arlen (s_axi_arlen[7:0]),
|
||||
.s_axi_arprot (s_axi_arprot[2:0]),
|
||||
.s_axi_arqos (s_axi_arqos[3:0]),
|
||||
.s_axi_arsize (s_axi_arsize[2:0]),
|
||||
.s_axi_arvalid (s_axi_arvalid),
|
||||
.s_axi_awid (s_axi_awid[S_IDW-1:0]),
|
||||
.s_axi_awaddr (s_axi_awaddr[31:0]),
|
||||
.s_axi_awburst (s_axi_awburst[1:0]),
|
||||
.s_axi_awcache (s_axi_awcache[3:0]),
|
||||
.s_axi_awlock (s_axi_awlock),
|
||||
.s_axi_awlen (s_axi_awlen[7:0]),
|
||||
.s_axi_awprot (s_axi_awprot[2:0]),
|
||||
.s_axi_awqos (s_axi_awqos[3:0]),
|
||||
.s_axi_awsize (s_axi_awsize[2:0]),
|
||||
.s_axi_awvalid (s_axi_awvalid),
|
||||
.s_axi_bready (s_axi_bready),
|
||||
.s_axi_rready (s_axi_rready),
|
||||
.s_axi_wid (s_axi_wid[S_IDW-1:0]),
|
||||
.s_axi_wdata (s_axi_wdata[31:0]),
|
||||
.s_axi_wlast (s_axi_wlast),
|
||||
.s_axi_wstrb (s_axi_wstrb[3:0]),
|
||||
.s_axi_wvalid (s_axi_wvalid));
|
||||
|
||||
endmodule // axi_spi
|
||||
// Local Variables:
|
||||
// verilog-library-directories:("." "../../axi/hdl" "../../common/hdl" "../../emesh/hdl")
|
||||
// End:
|
202
src/spi/hdl/parallella_spi.v
Normal file
202
src/spi/hdl/parallella_spi.v
Normal file
@ -0,0 +1,202 @@
|
||||
//#############################################################################
|
||||
//# Purpose: Parallella SPI top #
|
||||
//#############################################################################
|
||||
//# Author: Ola Jeppsson #
|
||||
//# SPDX-License-Identifier: MIT #
|
||||
//#############################################################################
|
||||
|
||||
module parallella_spi(/*AUTOARG*/
|
||||
// Outputs
|
||||
spi_s_miso, spi_m_ss, spi_m_sclk, spi_m_mosi, spi_irq,
|
||||
s_axi_wready, s_axi_rvalid, s_axi_rresp, s_axi_rlast, s_axi_rid,
|
||||
s_axi_rdata, s_axi_bvalid, s_axi_bresp, s_axi_bid, s_axi_awready,
|
||||
s_axi_arready,
|
||||
// Inouts
|
||||
gpio_n, gpio_p,
|
||||
// Inputs
|
||||
s_axi_wvalid, s_axi_wstrb, s_axi_wlast, s_axi_wid, s_axi_wdata,
|
||||
s_axi_rready, s_axi_bready, s_axi_awvalid, s_axi_awsize,
|
||||
s_axi_awqos, s_axi_awprot, s_axi_awlock, s_axi_awlen, s_axi_awid,
|
||||
s_axi_awcache, s_axi_awburst, s_axi_awaddr, s_axi_arvalid,
|
||||
s_axi_arsize, s_axi_arqos, s_axi_arprot, s_axi_arlock, s_axi_arlen,
|
||||
s_axi_arid, s_axi_aresetn, s_axi_arcache, s_axi_arburst,
|
||||
s_axi_araddr, constant_zero, constant_one, sys_nreset, sys_clk
|
||||
);
|
||||
|
||||
//########################################################
|
||||
// INTERFACE
|
||||
//########################################################
|
||||
parameter AW = 32; // address width
|
||||
parameter DW = 32;
|
||||
parameter PW = 2*AW+40; // packet width
|
||||
parameter ID = 12'h7fe; // addr[31:20] id
|
||||
parameter S_IDW = 12; // ID width for S_AXI
|
||||
parameter NGPIO = 24; // number of gpio pins
|
||||
|
||||
// constants
|
||||
input constant_zero; // Always 0
|
||||
input constant_one; // Always 1
|
||||
|
||||
//clk, reset
|
||||
input sys_nreset; // active low async reset
|
||||
input sys_clk; // system clock for AXI
|
||||
|
||||
// gpio pins
|
||||
inout [NGPIO-1:0] gpio_n; // physical spi pins
|
||||
inout [NGPIO-1:0] gpio_p; // physical spi pins
|
||||
wire [NGPIO-1:0] gpio_in; // out gpio pins
|
||||
wire [NGPIO-1:0] gpio_out; // in gpio pins
|
||||
wire [NGPIO-1:0] gpio_dir; // gpio pin direction
|
||||
|
||||
// spi
|
||||
wire spi_s_miso;
|
||||
wire spi_m_ss;
|
||||
wire spi_m_sclk;
|
||||
wire spi_m_mosi;
|
||||
wire spi_s_ss;
|
||||
wire spi_s_sclk;
|
||||
wire spi_s_mosi;
|
||||
wire spi_m_miso;
|
||||
|
||||
/*AUTOINPUT*/
|
||||
// Beginning of automatic inputs (from unused autoinst inputs)
|
||||
input [31:0] s_axi_araddr; // To axi_spi of axi_spi.v
|
||||
input [1:0] s_axi_arburst; // To axi_spi of axi_spi.v
|
||||
input [3:0] s_axi_arcache; // To axi_spi of axi_spi.v
|
||||
input s_axi_aresetn; // To axi_spi of axi_spi.v
|
||||
input [S_IDW-1:0] s_axi_arid; // To axi_spi of axi_spi.v
|
||||
input [7:0] s_axi_arlen; // To axi_spi of axi_spi.v
|
||||
input s_axi_arlock; // To axi_spi of axi_spi.v
|
||||
input [2:0] s_axi_arprot; // To axi_spi of axi_spi.v
|
||||
input [3:0] s_axi_arqos; // To axi_spi of axi_spi.v
|
||||
input [2:0] s_axi_arsize; // To axi_spi of axi_spi.v
|
||||
input s_axi_arvalid; // To axi_spi of axi_spi.v
|
||||
input [31:0] s_axi_awaddr; // To axi_spi of axi_spi.v
|
||||
input [1:0] s_axi_awburst; // To axi_spi of axi_spi.v
|
||||
input [3:0] s_axi_awcache; // To axi_spi of axi_spi.v
|
||||
input [S_IDW-1:0] s_axi_awid; // To axi_spi of axi_spi.v
|
||||
input [7:0] s_axi_awlen; // To axi_spi of axi_spi.v
|
||||
input s_axi_awlock; // To axi_spi of axi_spi.v
|
||||
input [2:0] s_axi_awprot; // To axi_spi of axi_spi.v
|
||||
input [3:0] s_axi_awqos; // To axi_spi of axi_spi.v
|
||||
input [2:0] s_axi_awsize; // To axi_spi of axi_spi.v
|
||||
input s_axi_awvalid; // To axi_spi of axi_spi.v
|
||||
input s_axi_bready; // To axi_spi of axi_spi.v
|
||||
input s_axi_rready; // To axi_spi of axi_spi.v
|
||||
input [31:0] s_axi_wdata; // To axi_spi of axi_spi.v
|
||||
input [S_IDW-1:0] s_axi_wid; // To axi_spi of axi_spi.v
|
||||
input s_axi_wlast; // To axi_spi of axi_spi.v
|
||||
input [3:0] s_axi_wstrb; // To axi_spi of axi_spi.v
|
||||
input s_axi_wvalid; // To axi_spi of axi_spi.v
|
||||
// End of automatics
|
||||
|
||||
/*AUTOOUTPUT*/
|
||||
// Beginning of automatic outputs (from unused autoinst outputs)
|
||||
output s_axi_arready; // From axi_spi of axi_spi.v
|
||||
output s_axi_awready; // From axi_spi of axi_spi.v
|
||||
output [S_IDW-1:0] s_axi_bid; // From axi_spi of axi_spi.v
|
||||
output [1:0] s_axi_bresp; // From axi_spi of axi_spi.v
|
||||
output s_axi_bvalid; // From axi_spi of axi_spi.v
|
||||
output [31:0] s_axi_rdata; // From axi_spi of axi_spi.v
|
||||
output [S_IDW-1:0] s_axi_rid; // From axi_spi of axi_spi.v
|
||||
output s_axi_rlast; // From axi_spi of axi_spi.v
|
||||
output [1:0] s_axi_rresp; // From axi_spi of axi_spi.v
|
||||
output s_axi_rvalid; // From axi_spi of axi_spi.v
|
||||
output s_axi_wready; // From axi_spi of axi_spi.v
|
||||
output spi_irq; // From axi_spi of axi_spi.v
|
||||
output spi_m_mosi; // From axi_spi of axi_spi.v
|
||||
output spi_m_sclk; // From axi_spi of axi_spi.v
|
||||
output spi_m_ss; // From axi_spi of axi_spi.v
|
||||
output spi_s_miso; // From axi_spi of axi_spi.v
|
||||
// End of automatics
|
||||
|
||||
/*AUTOWIRE*/
|
||||
|
||||
/*AUTOREG*/
|
||||
|
||||
assign spi_s_ss = gpio_in[10];
|
||||
assign spi_s_miso = gpio_out[9];
|
||||
assign spi_s_mosi = gpio_in[8];
|
||||
assign spi_s_sclk = gpio_in[7]; /* Must map to a MRCC/SRCC pin */
|
||||
assign spi_m_ss = gpio_out[6];
|
||||
assign spi_m_miso = gpio_in[5];
|
||||
assign spi_m_mosi = gpio_out[4];
|
||||
assign spi_m_sclk = gpio_out[3];
|
||||
|
||||
/* NOTE: 0 = in, 1 = out */
|
||||
assign gpio_dir[NGPIO-1:0] = {{(NGPIO-8){1'b0}}, 8'b01001011};
|
||||
|
||||
assign constant_zero = 1'b0;
|
||||
assign constant_one = 1'b1;
|
||||
|
||||
pgpio #(.NGPIO(NGPIO),.NPS(NGPIO))
|
||||
pgpio (.ps_gpio_i (gpio_in[NGPIO-1:0]),
|
||||
.ps_gpio_o (gpio_out[NGPIO-1:0]),
|
||||
.ps_gpio_t (~gpio_dir[NGPIO-1:0]),
|
||||
/*AUTOINST*/
|
||||
// Inouts
|
||||
.gpio_p (gpio_p[NGPIO-1:0]),
|
||||
.gpio_n (gpio_n[NGPIO-1:0]));
|
||||
|
||||
|
||||
axi_spi #(.S_IDW(S_IDW),.AW(AW),.ID(ID))
|
||||
axi_spi (// Outputs
|
||||
.spi_irq (spi_irq),
|
||||
.spi_m_mosi (spi_m_mosi),
|
||||
.spi_m_sclk (spi_m_sclk),
|
||||
.spi_m_ss (spi_m_ss),
|
||||
.spi_s_miso (spi_s_miso),
|
||||
// Inputs
|
||||
.spi_m_miso (spi_m_miso),
|
||||
.spi_s_mosi (spi_s_mosi),
|
||||
.spi_s_sclk (spi_s_sclk),
|
||||
.spi_s_ss (spi_s_ss),
|
||||
/*AUTOINST*/
|
||||
// Outputs
|
||||
.s_axi_arready (s_axi_arready),
|
||||
.s_axi_awready (s_axi_awready),
|
||||
.s_axi_bid (s_axi_bid[S_IDW-1:0]),
|
||||
.s_axi_bresp (s_axi_bresp[1:0]),
|
||||
.s_axi_bvalid (s_axi_bvalid),
|
||||
.s_axi_rdata (s_axi_rdata[31:0]),
|
||||
.s_axi_rid (s_axi_rid[S_IDW-1:0]),
|
||||
.s_axi_rlast (s_axi_rlast),
|
||||
.s_axi_rresp (s_axi_rresp[1:0]),
|
||||
.s_axi_rvalid (s_axi_rvalid),
|
||||
.s_axi_wready (s_axi_wready),
|
||||
// Inputs
|
||||
.sys_nreset (sys_nreset),
|
||||
.sys_clk (sys_clk),
|
||||
.s_axi_araddr (s_axi_araddr[31:0]),
|
||||
.s_axi_arburst (s_axi_arburst[1:0]),
|
||||
.s_axi_arcache (s_axi_arcache[3:0]),
|
||||
.s_axi_aresetn (s_axi_aresetn),
|
||||
.s_axi_arid (s_axi_arid[S_IDW-1:0]),
|
||||
.s_axi_arlen (s_axi_arlen[7:0]),
|
||||
.s_axi_arlock (s_axi_arlock),
|
||||
.s_axi_arprot (s_axi_arprot[2:0]),
|
||||
.s_axi_arqos (s_axi_arqos[3:0]),
|
||||
.s_axi_arsize (s_axi_arsize[2:0]),
|
||||
.s_axi_arvalid (s_axi_arvalid),
|
||||
.s_axi_awaddr (s_axi_awaddr[31:0]),
|
||||
.s_axi_awburst (s_axi_awburst[1:0]),
|
||||
.s_axi_awcache (s_axi_awcache[3:0]),
|
||||
.s_axi_awid (s_axi_awid[S_IDW-1:0]),
|
||||
.s_axi_awlen (s_axi_awlen[7:0]),
|
||||
.s_axi_awlock (s_axi_awlock),
|
||||
.s_axi_awprot (s_axi_awprot[2:0]),
|
||||
.s_axi_awqos (s_axi_awqos[3:0]),
|
||||
.s_axi_awsize (s_axi_awsize[2:0]),
|
||||
.s_axi_awvalid (s_axi_awvalid),
|
||||
.s_axi_bready (s_axi_bready),
|
||||
.s_axi_rready (s_axi_rready),
|
||||
.s_axi_wdata (s_axi_wdata[31:0]),
|
||||
.s_axi_wid (s_axi_wid[S_IDW-1:0]),
|
||||
.s_axi_wlast (s_axi_wlast),
|
||||
.s_axi_wstrb (s_axi_wstrb[3:0]),
|
||||
.s_axi_wvalid (s_axi_wvalid));
|
||||
|
||||
endmodule // parallella_spi
|
||||
// Local Variables:
|
||||
// verilog-library-directories:("." "../../axi/hdl" "../../common/hdl" "../../emesh/hdl" "../../parallella/hdl")
|
||||
// End:
|
@ -2,59 +2,43 @@
|
||||
//# Purpose: SPI top (configurable as master or slave) #
|
||||
//#############################################################################
|
||||
//# Author: Andreas Olofsson #
|
||||
//# License: MIT (see below) #
|
||||
//# License: MIT (see LICENSE file in OH! repository) #
|
||||
//#############################################################################
|
||||
|
||||
module spi (/*AUTOARG*/
|
||||
// Outputs
|
||||
spi_irq, access_out, packet_out, wait_out, m_sclk, m_mosi, m_ss,
|
||||
s_miso,
|
||||
// Inputs
|
||||
nreset, clk, hw_en, access_in, packet_in, wait_in, m_miso, s_sclk,
|
||||
s_mosi, s_ss
|
||||
module spi #( parameter AW = 32, // address width
|
||||
parameter PW = 104, // packet size
|
||||
parameter UREGS = 13 // number of user slave regs
|
||||
)
|
||||
(//clk, reset, irq
|
||||
input nreset, // asynch active low reset
|
||||
input clk, // core clock
|
||||
input hw_en, // block enable pin
|
||||
output spi_irq, // interrupt output
|
||||
//packet from core
|
||||
input access_in, // access from core
|
||||
input [PW-1:0] packet_in, // packet from core
|
||||
input wait_in, // pushback from io
|
||||
//packet to core
|
||||
output access_out, // access to core
|
||||
output [PW-1:0] packet_out, // packet to core
|
||||
output wait_out, // pushback from core
|
||||
//master io interface
|
||||
output m_sclk, // master clock
|
||||
output m_mosi, // master output
|
||||
output m_ss, // slave select
|
||||
input m_miso, // master input
|
||||
//slave io interface
|
||||
input s_sclk, // slave clock
|
||||
input s_mosi, // slave input
|
||||
input s_ss, // slave select
|
||||
output s_miso // slave output
|
||||
);
|
||||
|
||||
//##################################################################
|
||||
//# INTERFACE
|
||||
//##################################################################
|
||||
|
||||
parameter AW = 32; // data width of fifo
|
||||
parameter PW = 2*AW+40; // packet size
|
||||
parameter UREGS = 13; // number of user slave regs
|
||||
|
||||
//clk, reset, irq
|
||||
input nreset; // asynch active low reset
|
||||
input clk; // core clock
|
||||
input hw_en; // block enable pin
|
||||
|
||||
//interrupt output
|
||||
output spi_irq; // interrupt output
|
||||
|
||||
//packet from core
|
||||
input access_in; // access from core
|
||||
input [PW-1:0] packet_in; // packet from core
|
||||
input wait_in; // pushback from io
|
||||
|
||||
//packet to core
|
||||
output access_out; // access to core
|
||||
output [PW-1:0] packet_out; // packet to core
|
||||
output wait_out; // pushback from core
|
||||
|
||||
//master io interface
|
||||
output m_sclk; // master clock
|
||||
output m_mosi; // master output
|
||||
output m_ss; // slave select
|
||||
input m_miso; // master input
|
||||
|
||||
//slave io interface
|
||||
input s_sclk; // slave clock
|
||||
input s_mosi; // slave input
|
||||
input s_ss; // slave select
|
||||
output s_miso; // slave output
|
||||
//###############
|
||||
//# LOCAL WIRES
|
||||
//###############
|
||||
|
||||
/*AUTOINPUT*/
|
||||
// End of automatics
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
wire m_access_out; // From spi_master of spi_master.v
|
||||
@ -78,7 +62,8 @@ module spi (/*AUTOARG*/
|
||||
);
|
||||
*/
|
||||
|
||||
spi_master #(.AW(AW))
|
||||
spi_master #(.AW(AW),
|
||||
.PW(PW))
|
||||
spi_master (/*AUTOINST*/
|
||||
// Outputs
|
||||
.sclk (m_sclk), // Templated
|
||||
@ -110,6 +95,7 @@ module spi (/*AUTOARG*/
|
||||
*/
|
||||
|
||||
spi_slave #(.AW(AW),
|
||||
.PW(PW),
|
||||
.UREGS(UREGS))
|
||||
spi_slave (/*AUTOINST*/
|
||||
// Outputs
|
||||
@ -137,7 +123,8 @@ module spi (/*AUTOARG*/
|
||||
assign wait_out = s_wait_out | m_wait_out;
|
||||
|
||||
emesh_mux #(.N(2),
|
||||
.AW(AW))
|
||||
.AW(AW),
|
||||
.PW(PW))
|
||||
emesh_mux (// Outputs
|
||||
.wait_out (),
|
||||
.access_out (access_out),
|
||||
@ -153,27 +140,3 @@ endmodule // spi
|
||||
// verilog-library-directories:("." "../hdl" "../../emesh/hdl")
|
||||
// End:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// The MIT License (MIT) //
|
||||
// //
|
||||
// Copyright (c) 2015-2016, Adapteva, Inc. //
|
||||
// //
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a //
|
||||
// copy of this software and associated documentation files (the "Software")//
|
||||
// to deal in the Software without restriction, including without limitation//
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
|
||||
// and/or sell copies of the Software, and to permit persons to whom the //
|
||||
// Software is furnished to do so, subject to the following conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included //
|
||||
// in all copies or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS //
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF //
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. //
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY //
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT//
|
||||
// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR //
|
||||
// THE USE OR OTHER DEALINGS IN THE SOFTWARE. //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1,44 +1,38 @@
|
||||
//#############################################################################
|
||||
//# Purpose: SPI master (configurable) #
|
||||
//# Purpose: SPI master #
|
||||
//#############################################################################
|
||||
//# Author: Andreas Olofsson #
|
||||
//# License: MIT (see below) #
|
||||
//# License: MIT (see LICENSE file in OH! repository) #
|
||||
//#############################################################################
|
||||
|
||||
module spi_master(/*AUTOARG*/
|
||||
// Outputs
|
||||
sclk, mosi, ss, wait_out, access_out, packet_out,
|
||||
// Inputs
|
||||
clk, nreset, hw_en, miso, access_in, packet_in, wait_in
|
||||
module spi_master # ( parameter DEPTH = 32, // fifo depth
|
||||
parameter REGS = 16, // total # of regs
|
||||
parameter AW = 32, // addresss width
|
||||
parameter PW = 104 // packet width
|
||||
)
|
||||
(
|
||||
//clk,reset, cfg
|
||||
input clk, // core clock
|
||||
input nreset, // async active low reset
|
||||
input hw_en, // hardware enable pin
|
||||
//IO interface
|
||||
output sclk, // spi clock
|
||||
output mosi, // slave input
|
||||
output ss, // slave select
|
||||
input miso, // slave output
|
||||
//packet to transmit
|
||||
input access_in, // access from core
|
||||
input [PW-1:0] packet_in, // data to core
|
||||
output wait_out, // pushback from spi register
|
||||
//return packet
|
||||
output access_out, // readback access
|
||||
output [PW-1:0] packet_out, // packet from spi register
|
||||
input wait_in // pushback by core
|
||||
);
|
||||
|
||||
//parameters
|
||||
parameter DEPTH = 32; // fifo depth
|
||||
parameter REGS = 16; // total regs
|
||||
parameter AW = 32; // addresss width
|
||||
localparam PW = (2*AW+40); // packet width
|
||||
|
||||
//clk,reset, cfg
|
||||
input clk; // core clock
|
||||
input nreset; // async active low reset
|
||||
input hw_en; // hardware enable pin
|
||||
|
||||
//IO interface
|
||||
output sclk; // spi clock
|
||||
output mosi; // slave input
|
||||
output ss; // slave select
|
||||
input miso; // slave output
|
||||
|
||||
//packet to transmit
|
||||
input access_in; // access from core
|
||||
input [PW-1:0] packet_in; // data to core
|
||||
output wait_out; // pushback from spi register
|
||||
|
||||
//return packet
|
||||
output access_out; // readback access
|
||||
output [PW-1:0] packet_out; // packet from spi register
|
||||
input wait_in; // pushback by core
|
||||
|
||||
//###############
|
||||
//# LOCAL WIRES
|
||||
//###############
|
||||
/*AUTOINPUT*/
|
||||
/*AUTOOUTPUT*/
|
||||
|
||||
@ -63,7 +57,8 @@ module spi_master(/*AUTOARG*/
|
||||
//# Master control registers
|
||||
//#####################################################
|
||||
|
||||
spi_master_regs #(.AW(AW))
|
||||
spi_master_regs #(.AW(AW),
|
||||
.PW(PW))
|
||||
spi_master_regs (/*AUTOINST*/
|
||||
// Outputs
|
||||
.cpol (cpol),
|
||||
@ -97,6 +92,7 @@ module spi_master(/*AUTOARG*/
|
||||
*/
|
||||
|
||||
spi_master_fifo #(.AW(AW),
|
||||
.PW(PW),
|
||||
.DEPTH(DEPTH))
|
||||
spi_master_fifo(
|
||||
/*AUTOINST*/
|
||||
@ -117,7 +113,7 @@ module spi_master(/*AUTOARG*/
|
||||
//# SPI IO (8 bit)
|
||||
//#####################################################
|
||||
|
||||
spi_master_io #(.AW(AW))
|
||||
spi_master_io
|
||||
spi_master_io (/*AUTOINST*/
|
||||
// Outputs
|
||||
.spi_state (spi_state[1:0]),
|
||||
@ -140,28 +136,3 @@ module spi_master(/*AUTOARG*/
|
||||
|
||||
|
||||
endmodule // spi_master
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// The MIT License (MIT) //
|
||||
// //
|
||||
// Copyright (c) 2015-2016, Adapteva, Inc. //
|
||||
// //
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a //
|
||||
// copy of this software and associated documentation files (the "Software")//
|
||||
// to deal in the Software without restriction, including without limitation//
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
|
||||
// and/or sell copies of the Software, and to permit persons to whom the //
|
||||
// Software is furnished to do so, subject to the following conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included //
|
||||
// in all copies or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS //
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF //
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. //
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY //
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT//
|
||||
// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR //
|
||||
// THE USE OR OTHER DEALINGS IN THE SOFTWARE. //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1,45 +1,46 @@
|
||||
//#############################################################################
|
||||
//# Purpose: SPI Master Transmit Fifo #
|
||||
//#############################################################################
|
||||
//# Author: Andreas Olofsson #
|
||||
//# License: MIT (see LICENSE file in OH! repository) #
|
||||
//#############################################################################
|
||||
|
||||
`include "spi_regmap.vh"
|
||||
module spi_master_fifo (/*AUTOARG*/
|
||||
// Outputs
|
||||
fifo_prog_full, wait_out, fifo_empty, fifo_dout,
|
||||
// Inputs
|
||||
clk, nreset, spi_en, access_in, packet_in, fifo_read
|
||||
);
|
||||
//#####################################################################
|
||||
//# INTERFACE
|
||||
//#####################################################################
|
||||
|
||||
//parameters
|
||||
parameter DEPTH = 16; // fifo entries
|
||||
parameter AW = 32; // architecture address width
|
||||
parameter SW = 8; // output packet width
|
||||
localparam PW = 2*AW+40; // input packet width
|
||||
parameter FAW = $clog2(DEPTH); // fifo address width
|
||||
parameter SRW = $clog2(PW/SW); // serializer cycle count width
|
||||
|
||||
module spi_master_fifo #(parameter DEPTH = 16, // fifo entries
|
||||
parameter AW = 32, // address width
|
||||
parameter PW = 104, // input packet width
|
||||
parameter SW = 8 // io packet width
|
||||
)
|
||||
(
|
||||
//clk,reset, cfg
|
||||
input clk; // clk
|
||||
input nreset; // async active low reset
|
||||
input spi_en; // spi enable
|
||||
output fifo_prog_full; // fifo full indicator for status
|
||||
|
||||
input clk, // clk
|
||||
input nreset, // async active low reset
|
||||
input spi_en, // spi enable
|
||||
output fifo_prog_full, // fifo full indicator for status
|
||||
// Incoming interface
|
||||
input access_in; // access by core
|
||||
input [PW-1:0] packet_in; // packet from core
|
||||
output wait_out; // pushback to core
|
||||
|
||||
input access_in, // access by core
|
||||
input [PW-1:0] packet_in, // packet from core
|
||||
output wait_out, // pushback to core
|
||||
// IO interface
|
||||
input fifo_read; // pull a byte to IO
|
||||
output fifo_empty; // fifo is empty
|
||||
output [SW-1:0] fifo_dout; // byte for IO
|
||||
input fifo_read, // pull a byte to IO
|
||||
output fifo_empty, // fifo is empty
|
||||
output [SW-1:0] fifo_dout // byte for IO
|
||||
);
|
||||
|
||||
//##################################
|
||||
//# BODY
|
||||
//##################################
|
||||
localparam FAW = $clog2(DEPTH); // fifo address width
|
||||
localparam SRW = $clog2(PW/SW); // serialization factor
|
||||
|
||||
//###############
|
||||
//# LOCAL WIRES
|
||||
//###############
|
||||
wire [7:0] datasize;
|
||||
wire [PW-1:0] tx_data;
|
||||
wire [SW-1:0] fifo_din;
|
||||
wire tx_write;
|
||||
wire fifo_wait;
|
||||
wire fifo_wr;
|
||||
wire fifo_full;
|
||||
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
@ -55,7 +56,8 @@ module spi_master_fifo (/*AUTOARG*/
|
||||
//# DECODE
|
||||
//###################################
|
||||
|
||||
packet2emesh #(.AW(AW))
|
||||
packet2emesh #(.AW(AW),
|
||||
.PW(PW))
|
||||
p2e (/*AUTOINST*/
|
||||
// Outputs
|
||||
.write_in (write_in),
|
||||
|
@ -1,59 +1,48 @@
|
||||
//#############################################################################
|
||||
//# Purpose: SPI slave IO and statemachine #
|
||||
//# Purpose: SPI master IO state-machine #
|
||||
//#############################################################################
|
||||
//# Author: Andreas Olofsson #
|
||||
//# License: MIT (see below) #
|
||||
//# License: MIT (see LICENSE file in OH! repository) #
|
||||
//#############################################################################
|
||||
|
||||
module spi_master_io(/*AUTOARG*/
|
||||
// Outputs
|
||||
spi_state, fifo_read, rx_data, rx_access, sclk, mosi, ss,
|
||||
// Inputs
|
||||
clk, nreset, cpol, cpha, lsbfirst, clkdiv_reg, fifo_dout,
|
||||
fifo_empty, miso
|
||||
module spi_master_io
|
||||
(
|
||||
//clk, reset, cfg
|
||||
input clk, // core clock
|
||||
input nreset, // async active low reset
|
||||
input cpol, // cpol
|
||||
input cpha, // cpha
|
||||
input lsbfirst, // send lsbfirst
|
||||
input [7:0] clkdiv_reg, // baudrate
|
||||
output reg [1:0] spi_state, // current spi tx state
|
||||
// data to transmit
|
||||
input [7:0] fifo_dout, // data payload
|
||||
input fifo_empty, //
|
||||
output fifo_read, // read new byte
|
||||
// receive data (for sregs)
|
||||
output [63:0] rx_data, // rx data
|
||||
output rx_access, // transfer done
|
||||
// IO interface
|
||||
output sclk, // spi clock
|
||||
output mosi, // slave input
|
||||
output ss, // slave select
|
||||
input miso // slave output
|
||||
);
|
||||
|
||||
//#################################
|
||||
//# INTERFACE
|
||||
//#################################
|
||||
|
||||
//parameters
|
||||
parameter REGS = 16; // total regs (16/32/64)
|
||||
parameter AW = 32; // address width
|
||||
localparam PW = (2*AW+40); // packet width
|
||||
|
||||
//clk, reset, cfg
|
||||
input clk; // core clock
|
||||
input nreset; // async active low reset
|
||||
|
||||
//cfg
|
||||
input cpol; // cpol
|
||||
input cpha; // cpha
|
||||
input lsbfirst; // send lsbfirst
|
||||
input [7:0] clkdiv_reg; // baudrate
|
||||
output [1:0] spi_state; // current spi tx state
|
||||
|
||||
//data to transmit
|
||||
input [7:0] fifo_dout; // data payload
|
||||
input fifo_empty; //
|
||||
output fifo_read; // read new byte
|
||||
|
||||
//receive data (for sregs)
|
||||
output [63:0] rx_data; // rx data
|
||||
output rx_access; // transfer done
|
||||
|
||||
//IO interface
|
||||
output sclk; // spi clock
|
||||
output mosi; // slave input
|
||||
output ss; // slave select
|
||||
input miso; // slave output
|
||||
|
||||
reg [1:0] spi_state;
|
||||
//###############
|
||||
//# LOCAL WIRES
|
||||
//###############
|
||||
reg fifo_empty_reg;
|
||||
reg load_byte;
|
||||
|
||||
wire [7:0] data_out;
|
||||
wire [15:0] clkphase0;
|
||||
wire period_match;
|
||||
wire phase_match;
|
||||
wire clkout;
|
||||
wire clkchange;
|
||||
wire data_done;
|
||||
wire spi_wait;
|
||||
wire shift;
|
||||
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
@ -178,35 +167,9 @@ module spi_master_io(/*AUTOARG*/
|
||||
.lsbfirst (lsbfirst), // shift direction
|
||||
.shift (shift)); // shift data
|
||||
|
||||
endmodule // spi_slave_io
|
||||
|
||||
endmodule // spi_master_io
|
||||
// Local Variables:
|
||||
// verilog-library-directories:("." "../../common/hdl" "../../emesh/hdl")
|
||||
// End:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// The MIT License (MIT) //
|
||||
// //
|
||||
// Copyright (c) 2015-2016, Adapteva, Inc. //
|
||||
// //
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a //
|
||||
// copy of this software and associated documentation files (the "Software") //
|
||||
// to deal in the Software without restriction, including without limitation //
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
|
||||
// and/or sell copies of the Software, and to permit persons to whom the //
|
||||
// Software is furnished to do so, subject to the following conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included //
|
||||
// in all copies or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS //
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF //
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. //
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY //
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT //
|
||||
// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR //
|
||||
// THE USE OR OTHER DEALINGS IN THE SOFTWARE. //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
@ -1,74 +1,65 @@
|
||||
|
||||
//#############################################################################
|
||||
//# Purpose: SPI master (configurable) #
|
||||
//# Purpose: SPI master Registers #
|
||||
//#############################################################################
|
||||
//# Author: Andreas Olofsson #
|
||||
//# License: MIT (see below) #
|
||||
//# License: MIT (see LICENSE file in OH! repository) #
|
||||
//#############################################################################
|
||||
|
||||
`include "spi_regmap.vh"
|
||||
module spi_master_regs (/*AUTOARG*/
|
||||
// Outputs
|
||||
cpol, cpha, lsbfirst, spi_en, clkdiv_reg, wait_out, access_out,
|
||||
packet_out,
|
||||
// Inputs
|
||||
clk, nreset, hw_en, rx_data, rx_access, spi_state, fifo_prog_full,
|
||||
fifo_wait, access_in, packet_in, wait_in
|
||||
module spi_master_regs # (parameter CLKDIV = 1, // default clkdiv
|
||||
parameter AW = 32, // addresss width
|
||||
parameter PW = 104 // packet width
|
||||
)
|
||||
(
|
||||
//clk,reset, cfg
|
||||
input clk, // core clock
|
||||
input nreset, // async active low reset
|
||||
input hw_en, // block enable pin
|
||||
//io interface
|
||||
input [63:0] rx_data, // rx data
|
||||
input rx_access, // rx access pulse
|
||||
//control
|
||||
output cpol, // clk polarity (default is 0)
|
||||
output cpha, // clk phase shift (default is 0)
|
||||
output lsbfirst, // send lsbfirst
|
||||
output spi_en, // enable transmitter
|
||||
output reg [7:0] clkdiv_reg, // baud rate setting
|
||||
input [1:0] spi_state, // transmit state
|
||||
input fifo_prog_full, // fifo reached half/full
|
||||
input fifo_wait, // tx transfer wait
|
||||
//packet to transmit
|
||||
input access_in, // access from core
|
||||
input [PW-1:0] packet_in, // data to core
|
||||
output wait_out, // pushback from spi master
|
||||
//return packet
|
||||
output reg access_out, // writeback from spi
|
||||
output [PW-1:0] packet_out, // writeback data from spi
|
||||
input wait_in // pushback by core
|
||||
);
|
||||
|
||||
//parameters
|
||||
parameter CLKDIV = 1; // default clkdiv
|
||||
parameter PSIZE = 0; // default is 32 bits
|
||||
parameter AW = 32; // addresss width
|
||||
localparam PW = (2*AW+40); // packet width
|
||||
|
||||
//clk,reset, cfg
|
||||
input clk; // core clock
|
||||
input nreset; // async active low reset
|
||||
input hw_en; // block enable pin
|
||||
|
||||
//io interface
|
||||
input [63:0] rx_data; // rx data
|
||||
input rx_access; // rx access pulse
|
||||
|
||||
//control
|
||||
output cpol; // clk polarity (default is 0)
|
||||
output cpha; // clk phase shift (default is 0)
|
||||
output lsbfirst; // send lsbfirst
|
||||
output spi_en; // enable transmitter
|
||||
output [7:0] clkdiv_reg; // baud rate setting
|
||||
input [1:0] spi_state; // transmit state
|
||||
input fifo_prog_full; // fifo reached half/full
|
||||
input fifo_wait; // tx transfer wait
|
||||
|
||||
//packet to transmit
|
||||
input access_in; // access from core
|
||||
input [PW-1:0] packet_in; // data to core
|
||||
output wait_out; // pushback from spi master
|
||||
|
||||
//return packet
|
||||
output access_out; // writeback from spi
|
||||
output [PW-1:0] packet_out; // writeback data from spi
|
||||
input wait_in; // pushback by core
|
||||
|
||||
//########################################################
|
||||
//# BODY
|
||||
//########################################################
|
||||
|
||||
//###############
|
||||
//# LOCAL WIRES
|
||||
//###############
|
||||
reg [7:0] config_reg;
|
||||
reg [7:0] status_reg;
|
||||
reg [7:0] clkdiv_reg;
|
||||
reg [63:0] rx_reg;
|
||||
reg [AW-1:0] reg_rdata;
|
||||
reg autotran;
|
||||
reg access_out;
|
||||
reg [AW-1:0] dstaddr_out;
|
||||
reg [4:0] ctrlmode_out;
|
||||
reg [1:0] datamode_out;
|
||||
|
||||
wire [31:0] reg_wdata;
|
||||
wire reg_write;
|
||||
wire reg_read;
|
||||
wire config_write;
|
||||
wire status_write;
|
||||
wire clkdiv_write;
|
||||
wire cmd_write;
|
||||
wire tx_write;
|
||||
wire irq_en;
|
||||
wire wait_pulse;
|
||||
integer i;
|
||||
|
||||
wire [31:0] reg_wdata;
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
@ -84,7 +75,8 @@ module spi_master_regs (/*AUTOARG*/
|
||||
//# DECODE
|
||||
//####################################
|
||||
|
||||
packet2emesh #(.AW(AW))
|
||||
packet2emesh #(.AW(AW),
|
||||
.PW(PW))
|
||||
pe2 (/*AUTOINST*/
|
||||
// Outputs
|
||||
.write_in (write_in),
|
||||
@ -183,7 +175,7 @@ module spi_master_regs (/*AUTOARG*/
|
||||
datamode_out[1:0] <= datamode_in[1:0];
|
||||
end
|
||||
|
||||
//create a pulse on register reads
|
||||
//create a single cycle pulse on register read
|
||||
oh_edge2pulse
|
||||
e2pulse (.out (wait_pulse),
|
||||
.clk (clk),
|
||||
@ -192,7 +184,8 @@ module spi_master_regs (/*AUTOARG*/
|
||||
//TODO: fix!
|
||||
assign wait_out = fifo_wait;
|
||||
|
||||
emesh2packet #(.AW(AW))
|
||||
emesh2packet #(.AW(AW),
|
||||
.PW(PW))
|
||||
e2p (.write_out (1'b1),
|
||||
.srcaddr_out ({(AW){1'b0}}),
|
||||
.data_out (reg_rdata[AW-1:0]),
|
||||
|
@ -1,3 +1,10 @@
|
||||
//#############################################################################
|
||||
//# Purpose: SPI Register Map #
|
||||
//#############################################################################
|
||||
//# Author: Andreas Olofsson #
|
||||
//# License: MIT (see LICENSE file in OH! repository) #
|
||||
//#############################################################################
|
||||
|
||||
//8 bit registers [5:0]
|
||||
`ifndef SPI_REGMAP_VH_
|
||||
`define SPI_REGMAP_VH_
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user