diff --git a/README.md b/README.md index db6c232..83bddbf 100644 --- a/README.md +++ b/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" 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 diff --git a/docs/chip_constants.md b/docs/chip_constants.md index 3efd9df..34f8446 100644 --- a/docs/chip_constants.md +++ b/docs/chip_constants.md @@ -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 | diff --git a/docs/tapeout_checklist.md b/docs/tapeout_checklist.md index eb6b789..1764fd3 100644 --- a/docs/tapeout_checklist.md +++ b/docs/tapeout_checklist.md @@ -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,11 +55,16 @@ | >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 | |--------------------------------------------|--------------------------------| | All paths constrained? | | @@ -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? | | + diff --git a/scripts/build.sh b/scripts/build.sh index a1e098d..aa85d28 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -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 .\ diff --git a/src/common/dv/dv_driver.v b/src/common/dv/dv_driver.v index 95551d0..14903fa 100644 --- a/src/common/dv/dv_driver.v +++ b/src/common/dv/dv_driver.v @@ -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; - + wire [N-1:0] mem_wait_out; /*AUTOWIRE*/ + //########################################### //STIMULUS //########################################### @@ -126,6 +118,7 @@ module dv_driver (/*AUTOARG*/ for(j=0;j + .en (en[N-1:0])); + + //Or gated clocks together + assign clkout = |(eclk[N-1:0]); + +endmodule // oh_clockmux + + diff --git a/src/common/hdl/oh_csa32.v b/src/common/hdl/oh_csa32.v index e1af48f..22b4189 100644 --- a/src/common/hdl/oh_csa32.v +++ b/src/common/hdl/oh_csa32.v @@ -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]) | diff --git a/src/common/hdl/oh_dsync.v b/src/common/hdl/oh_dsync.v index e2cef14..045f03b 100644 --- a/src/common/hdl/oh_dsync.v +++ b/src/common/hdl/oh_dsync.v @@ -5,55 +5,39 @@ //# 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 clk, // clock + input nreset, // clock + input din, // input data + output dout // synchronized data ); generate if(ASIC) - begin - asic_dsync #(.DW(DW)) - asic_dsync(.clk(clk), - .nreset(nreset), - .din(din[DW-1:0]), - .dout(dout[DW-1:0])); + begin : g0 + asic_dsync asic_dsync (.clk(clk), + .nreset(nreset), + .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) - always @ (posedge clk or negedge nreset) - if(!nreset) - sync_pipe[0][DW-1:0] <= 'b0; - else - sync_pipe[0][DW-1:0] <= din[DW-1:0]; + begin : g0 + reg [PS:0] sync_pipe; + always @ (posedge clk or negedge nreset) + if(!nreset) + sync_pipe[PS:0] <= 1'b0; 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 - + endmodule // oh_dsync diff --git a/src/common/hdl/oh_fifo_async.v b/src/common/hdl/oh_fifo_async.v index 5303bc8..6e95450 100644 --- a/src/common/hdl/oh_fifo_async.v +++ b/src/common/hdl/oh_fifo_async.v @@ -5,25 +5,25 @@ //# License: MIT (see LICENSE file in OH! repository) # //############################################################################# -module oh_fifo_async # (parameter DW = 104, //FIFO width - parameter DEPTH = 32, //FIFO depth (entries) - parameter TARGET = "GENERIC",//XILINX,ALTERA,GENERIC,ASIC +module oh_fifo_async # (parameter DW = 104, // FIFO width + parameter DEPTH = 32, // FIFO depth (entries) + parameter TARGET = "GENERIC",// XILINX,ALTERA,GENERIC,ASIC parameter PROG_FULL = (DEPTH/2),// program full threshold parameter AW = $clog2(DEPTH) // binary read count width ) -( - input nreset, // async reset - input wr_clk, // write clock - input wr_en, // write fifo - input [DW-1:0] din, // data to write - input rd_clk, // read clock - input rd_en, // read fifo - output [DW-1:0] dout, // output data (next cycle) - output full, // fifo is full - output prog_full, // fifo reaches full threshold - output empty, // fifo is empty - output [AW-1:0] rd_count // # of valid entries in fifo - ); + ( + input nreset, // async reset + input wr_clk, // write clock + input wr_en, // write fifo + input [DW-1:0] din, // data to write + input rd_clk, // read clock + input rd_en, // read fifo + output [DW-1:0] dout, // output data (next cycle) + output full, // fifo is full + output prog_full, // fifo reaches full threshold + output empty, // fifo is empty + output [AW-1:0] rd_count // # of valid entries in fifo + ); //local wires wire [AW-1:0] wr_count; // valid entries in fifo @@ -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 diff --git a/src/common/hdl/oh_fifo_cdc.v b/src/common/hdl/oh_fifo_cdc.v index 606894b..6fbc5b7 100644 --- a/src/common/hdl/oh_fifo_cdc.v +++ b/src/common/hdl/oh_fifo_cdc.v @@ -7,16 +7,16 @@ 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 - input clk_in, // write clock + input nreset, // shared domain async active low reset + input clk_in, // write clock input access_in, // write access 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,9 +24,9 @@ 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; assign rd_en = ~empty & ~wait_in; diff --git a/src/common/hdl/oh_fifo_generic.v b/src/common/hdl/oh_fifo_generic.v index 31df506..e56072e 100644 --- a/src/common/hdl/oh_fifo_generic.v +++ b/src/common/hdl/oh_fifo_generic.v @@ -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,13 +67,15 @@ module oh_fifo_generic #(parameter DW = 104, // FIFO width //# Reset synchronizers //########################### - oh_rsync wr_rsync (.nrst_out (wr_nreset), - .clk (wr_clk), - .nrst_in (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), - .clk (rd_clk), - .nrst_in (nreset)); + oh_rsync #(.ASIC(ASIC)) + rd_rsync (.nrst_out (rd_nreset), + .clk (rd_clk), + .nrst_in (nreset)); //########################### //#write side address counter @@ -99,11 +104,10 @@ 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]), - .clk (rd_clk), - .nreset(rd_nreset), - .din (wr_addr_gray[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])); //########################### //#read side address counter @@ -125,12 +129,11 @@ 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]), - .clk (wr_clk), - .nreset (wr_nreset), - .din (rd_addr_gray[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])); + //convert back to binary (for ease of use, rd_count) oh_gray2bin #(.DW(AW+1)) rd_g2b (.out (rd_addr_sync[AW:0]), diff --git a/src/common/hdl/oh_fifo_sync.v b/src/common/hdl/oh_fifo_sync.v index 48fdff4..52eb2f3 100644 --- a/src/common/hdl/oh_fifo_sync.v +++ b/src/common/hdl/oh_fifo_sync.v @@ -11,21 +11,22 @@ module oh_fifo_sync #(parameter DW = 104, //FIFO width parameter AW = $clog2(DEPTH) //rd_count width ) ( - input clk, // clock - input nreset, // active high async reset - input [DW-1:0] din, // data to write - input wr_en, // write fifo - input rd_en, // read fifo - output [DW-1:0] dout, // output data (next cycle) - 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 + input clk, // clock + input nreset, // active high async reset + input [DW-1:0] din, // data to write + input wr_en, // write fifo + input rd_en, // read fifo + output [DW-1:0] dout, // output data (next cycle) + output full, // fifo full + output prog_full, // fifo is almost full + output empty, // fifo is empty + 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; + reg [AW-1:0] wr_addr; + reg [AW-1:0] rd_addr; + wire fifo_read; + wire fifo_write; assign empty = (rd_count[AW-1:0] == 0); assign prog_full = (rd_count[AW-1:0] >= PROG_FULL); diff --git a/src/common/hdl/oh_iddr.v b/src/common/hdl/oh_iddr.v index c47eee6..f304cb2 100644 --- a/src/common/hdl/oh_iddr.v +++ b/src/common/hdl/oh_iddr.v @@ -8,18 +8,16 @@ 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 + 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 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) diff --git a/src/common/hdl/oh_lat0.v b/src/common/hdl/oh_lat0.v index 13fe5f5..eeea8df 100644 --- a/src/common/hdl/oh_lat0.v +++ b/src/common/hdl/oh_lat0.v @@ -7,11 +7,10 @@ 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) + input [DW-1:0] in, // input data + 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]; diff --git a/src/common/hdl/oh_lat1.v b/src/common/hdl/oh_lat1.v index 74e2a83..331ed0f 100644 --- a/src/common/hdl/oh_lat1.v +++ b/src/common/hdl/oh_lat1.v @@ -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; - always @ (clk or in) - if (clk) - out[DW-1:0] <= in[DW-1:0]; - + 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_reg[DW-1:0] <= in[DW-1:0]; + assign out[DW-1:0] = out_reg[DW-1:0]; + end + endgenerate + endmodule // oh_lat1 - - diff --git a/src/common/hdl/oh_memory_dp.v b/src/common/hdl/oh_memory_dp.v index c0906f2..c919280 100644 --- a/src/common/hdl/oh_memory_dp.v +++ b/src/common/hdl/oh_memory_dp.v @@ -39,40 +39,38 @@ 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 - .rd_dout (rd_dout[DW-1:0]), - .rd_clk (rd_clk), - .rd_en (rd_en), - .rd_addr (rd_addr[AW-1:0]), - //write port - .wr_en (wr_en), - .wr_clk (wr_clk), - .wr_addr (wr_addr[AW-1:0]), - .wr_wem (wr_wem[DW-1:0]), - .wr_din (wr_din[DW-1:0])); + memory_dp (//read port + .rd_dout (rd_dout[DW-1:0]), + .rd_clk (rd_clk), + .rd_en (rd_en), + .rd_addr (rd_addr[AW-1:0]), + //write port + .wr_en (wr_en), + .wr_clk (wr_clk), + .wr_addr (wr_addr[AW-1:0]), + .wr_wem (wr_wem[DW-1:0]), + .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 - .rd_dout (rd_dout[DW-1:0]), - .rd_clk (rd_clk), - .rd_en (rd_en), - .rd_addr (rd_addr[AW-1:0]), - //write port - .wr_en (wr_en), - .wr_clk (wr_clk), - .wr_addr (wr_addr[AW-1:0]), - .wr_wem (wr_wem[DW-1:0]), - .wr_din (wr_din[DW-1:0])); + memory_dp (//read port + .rd_dout (rd_dout[DW-1:0]), + .rd_clk (rd_clk), + .rd_en (rd_en), + .rd_addr (rd_addr[AW-1:0]), + //write port + .wr_en (wr_en), + .wr_clk (wr_clk), + .wr_addr (wr_addr[AW-1:0]), + .wr_wem (wr_wem[DW-1:0]), + .wr_din (wr_din[DW-1:0])); end // else: !if(ASIC) - endgenerate - - + endgenerate endmodule // oh_memory_dp diff --git a/src/common/hdl/oh_memory_ram.v b/src/common/hdl/oh_memory_ram.v index 9553ced..10a387f 100644 --- a/src/common/hdl/oh_memory_ram.v +++ b/src/common/hdl/oh_memory_ram.v @@ -5,26 +5,24 @@ //# License: MIT (see LICENSE file in OH! repository) # //############################################################################# -module oh_memory_ram # (parameter DW = 104, //memory width - parameter DEPTH = 32 //memory depth +module oh_memory_ram # (parameter DW = 104, //memory width + 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 + input rd_clk,// rd clock + input rd_en, // memory access + input [AW-1:0] rd_addr, // address + output reg [DW-1:0] rd_dout, // data output // write-port - input wr_clk,// wr clock - input wr_en, // memory access - input [AW-1:0] wr_addr, // address - input [DW-1:0] wr_wem, // write enable vector - input [DW-1:0] wr_din // data input + input wr_clk,// wr clock + input wr_en, // memory access + input [AW-1:0] wr_addr, // address + input [DW-1:0] wr_wem, // write enable vector + 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 diff --git a/src/common/hdl/oh_memory_sp.v b/src/common/hdl/oh_memory_sp.v index 0e6dce7..f3161c1 100644 --- a/src/common/hdl/oh_memory_sp.v +++ b/src/common/hdl/oh_memory_sp.v @@ -1,15 +1,16 @@ //############################################################################# -//# Function: Sinle Port Memory # +//# Function: Single Port Memory # //############################################################################# //# Author: Andreas Olofsson # -//# License: MIT (see LICENSE file in OH! repository) # +//# License: MIT (see LICENSE file in OH! repository) # //############################################################################# -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 +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 width + parameter AW = $clog2(DEPTH) // address bus width ) (// memory interface (single port) input clk, // clock @@ -34,51 +35,51 @@ 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 - .dout (dout[DW-1:0]), - // Inputs - .clk (clk), - .en (en), - .we (we), - .wem (wem[DW-1:0]), - .addr (addr[AW-1:0]), - .din (din[DW-1:0]), - .vdd (vdd), - .vddm (vddm), - .vss (vss), - .shutdown (shutdown), - .memconfig (memconfig[MCW-1:0]), - .memrepair (memrepair[MCW-1:0]), - .bist_en (bist_en), - .bist_we (bist_we), - .bist_wem (bist_wem[DW-1:0]), - .bist_addr (bist_addr[AW-1:0]), - .bist_din (bist_din[DW-1:0])); + sram_sp (// Outputs + .dout (dout[DW-1:0]), + // Inputs + .clk (clk), + .en (en), + .we (we), + .wem (wem[DW-1:0]), + .addr (addr[AW-1:0]), + .din (din[DW-1:0]), + .vdd (vdd), + .vddm (vddm), + .vss (vss), + .shutdown (shutdown), + .memconfig (memconfig[MCW-1:0]), + .memrepair (memrepair[MCW-1:0]), + .bist_en (bist_en), + .bist_we (bist_we), + .bist_wem (bist_wem[DW-1:0]), + .bist_addr (bist_addr[AW-1:0]), + .bist_din (bist_din[DW-1:0])); end else - begin + begin : g0 oh_memory_ram #(.DW(DW), .DEPTH(DEPTH)) - oh_memory_ram (//read port - .rd_dout (dout[DW-1:0]), - .rd_clk (clk), - .rd_addr (addr[AW-1:0]), - .rd_en (en & ~we), - //write port - .wr_clk (clk), - .wr_en (en & we), - .wr_addr (addr[AW-1:0]), - .wr_wem (wem[DW-1:0]), - .wr_din (din[DW-1:0])); + sram_sp (//read port + .rd_dout (dout[DW-1:0]), + .rd_clk (clk), + .rd_addr (addr[AW-1:0]), + .rd_en (en & ~we), + //write port + .wr_clk (clk), + .wr_en (en & we), + .wr_addr (addr[AW-1:0]), + .wr_wem (wem[DW-1:0]), + .wr_din (din[DW-1:0])); end endgenerate diff --git a/src/common/hdl/oh_par2ser.v b/src/common/hdl/oh_par2ser.v index f66da34..2cbe7be 100644 --- a/src/common/hdl/oh_par2ser.v +++ b/src/common/hdl/oh_par2ser.v @@ -5,8 +5,9 @@ //# License: MIT (see LICENSE in OH! repositpory) # //############################################################################# -module oh_par2ser #(parameter PW = 64, // parallel packet width - parameter SW = 1 // serial packet width +module oh_par2ser #(parameter PW = 64, // parallel packet width + parameter SW = 1, // serial packet width + parameter CW = $clog2(PW/SW) // serialization factor ) ( input clk, // sampling clock @@ -23,12 +24,12 @@ 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; diff --git a/src/common/hdl/oh_pulse2pulse.v b/src/common/hdl/oh_pulse2pulse.v index 604273d..2019167 100644 --- a/src/common/hdl/oh_pulse2pulse.v +++ b/src/common/hdl/oh_pulse2pulse.v @@ -28,10 +28,10 @@ module oh_pulse2pulse ( toggle_reg <= toggle; //metastability synchronizer - oh_dsync #(1) sync(.dout (toggle_sync), - .din (toggle), - .nreset (nrstout), - .clk (clkout)); + oh_dsync sync(.dout (toggle_sync), + .din (toggle), + .nreset (nrstout), + .clk (clkout)); //toogle to pulse always @ (posedge clkout) diff --git a/src/common/hdl/oh_pwr_gate.v b/src/common/hdl/oh_pwr_gate.v index 7b096a2..3b941d6 100644 --- a/src/common/hdl/oh_pwr_gate.v +++ b/src/common/hdl/oh_pwr_gate.v @@ -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)); diff --git a/src/common/hdl/oh_pwr_isolate.v b/src/common/hdl/oh_pwr_isolate.v index 7c9312f..4f3cbf1 100644 --- a/src/common/hdl/oh_pwr_isolate.v +++ b/src/common/hdl/oh_pwr_isolate.v @@ -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 diff --git a/src/common/hdl/oh_rsync.v b/src/common/hdl/oh_rsync.v index f60f82b..3667165 100644 --- a/src/common/hdl/oh_rsync.v +++ b/src/common/hdl/oh_rsync.v @@ -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 ); - - 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]; - + 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 diff --git a/src/common/hdl/oh_ser2par.v b/src/common/hdl/oh_ser2par.v index ebad2a6..97afd59 100644 --- a/src/common/hdl/oh_ser2par.v +++ b/src/common/hdl/oh_ser2par.v @@ -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 - input lsbfirst, // lsb first order - input shift // shift the shifter + input clk, // sampling clock + input [SW-1:0] din, // serial 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; diff --git a/src/common/hdl/oh_standby.v b/src/common/hdl/oh_standby.v index bef77db..54158cf 100644 --- a/src/common/hdl/oh_standby.v +++ b/src/common/hdl/oh_standby.v @@ -5,41 +5,52 @@ //# 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 idle, //core is in idle - output clkout //clock output + input clkin, //clock input + 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 ); //Wire declarations reg [PD-1:0] wakeup_pipe; reg idle_reg; - - // detect an idle state change (wake up on any) - always @ (posedge clk ) - idle_reg <= idle; - assign state_change = (idle ^ idle_reg); - - always @ (posedge clk) - wakeup_pipe[PD-1:0] <= {wakeup_pipe[PD-2:0],(state_change | wakeup)}; + wire state_change; + wire clk_en; + wire [N-1:0] wakeup_pulse; + wire wakeup_now; - //block enable signal - assign clk_en = ~nreset | //always on during reset - wakeup | //immediate wakeup - state_change | //incoming transition + // 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])); + + assign wakeup_now = |(wakeup_pulse[N-1:0]); + + // 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), - .en(clk_en), - .nrst(nreset), - .se(1'b0)); - + // Clock gating cell + oh_clockgate #(.PROJ(PROJ), + .ASIC(ASIC)) + oh_clockgate (.eclk(clkout), + .clk(clkin), + .en(clk_en), + .te(1'b0)); + endmodule // oh_standby diff --git a/src/common/hdl/oh_tristate.v b/src/common/hdl/oh_tristate.v new file mode 100644 index 0000000..279eeae --- /dev/null +++ b/src/common/hdl/oh_tristate.v @@ -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 diff --git a/src/edma/hdl/edma.v b/src/edma/hdl/edma.v index f7fafee..45087ca 100644 --- a/src/edma/hdl/edma.v +++ b/src/edma/hdl/edma.v @@ -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 - ); - - //##################################################################### - //# 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 +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 + ); - // 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*/ - + /*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), diff --git a/src/edma/hdl/edma_ctrl.v b/src/edma/hdl/edma_ctrl.v index 8e1c765..b891a83 100644 --- a/src/edma/hdl/edma_ctrl.v +++ b/src/edma/hdl/edma_ctrl.v @@ -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,7 +54,10 @@ 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 diff --git a/src/edma/hdl/edma_dp.v b/src/edma/hdl/edma_dp.v index d053be4..3b86a07 100644 --- a/src/edma/hdl/edma_dp.v +++ b/src/edma/hdl/edma_dp.v @@ -13,8 +13,8 @@ module edma_dp (/*AUTOARG*/ packet_in, wait_in ); - parameter AW = 8; // divider counter width - localparam PW = 2*AW+40; // emesh packet width + parameter AW = 8; // divider counter 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 diff --git a/src/edma/hdl/edma_regs.v b/src/edma/hdl/edma_regs.v index df7baae..0a930a5 100644 --- a/src/edma/hdl/edma_regs.v +++ b/src/edma/hdl/edma_regs.v @@ -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 diff --git a/src/elink/hdl/etx_cfg.v b/src/elink/hdl/etx_cfg.v index 4d63fbd..1371543 100644 --- a/src/elink/hdl/etx_cfg.v +++ b/src/elink/hdl/etx_cfg.v @@ -143,11 +143,10 @@ module etx_cfg (/*AUTOARG*/ //########################### //Synchronize to make easy regular - oh_dsync #(.DW(16)) - dsync (.dout (tx_status_sync[15:0]), - .clk (clk), - .nreset (1'b1), - .din (tx_status[15:0])); + oh_dsync isync[15:0] (.dout (tx_status_sync[15:0]), + .clk (clk), + .nreset (1'b1), + .din (tx_status[15:0])); always @ (posedge clk) if (tx_status_write) diff --git a/src/emesh/hdl/ememory.v b/src/emesh/hdl/ememory.v index a49fa74..7274123 100644 --- a/src/emesh/hdl/ememory.v +++ b/src/emesh/hdl/ememory.v @@ -1,77 +1,75 @@ -module ememory(/*AUTOARG*/ - // Outputs - wait_out, access_out, packet_out, - // Inputs - clk, nreset, coreid, access_in, packet_in, wait_in - ); - - 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 - - //Basic Interface - input clk; - input nreset; - input [IDW-1:0] coreid; +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 + ) - //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 + (// 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 + ); + + //derived parameters + localparam DW = AW; //always the same + parameter MAW = $clog2(DEPTH); + //############### + //# LOCAL WIRES + //############## + wire [MAW-1:0] addr; wire [63:0] din; wire [63:0] dout; 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), + .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]), + .srcaddr_in (srcaddr_in[AW-1:0]), + .data_in (data_in[AW-1:0]), + // Inputs + .packet_in (packet_in[PW-1:0])); - packet2emesh #(.AW(AW)) - p2e ( - .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]) - ); //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 diff --git a/src/emesh/hdl/emesh2packet.v b/src/emesh/hdl/emesh2packet.v index 59f32e6..ee3abf6 100644 --- a/src/emesh/hdl/emesh2packet.v +++ b/src/emesh/hdl/emesh2packet.v @@ -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, + //Output packet + output [PW-1:0] packet_out + ); - //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; + // ---- 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) - //Output packet - output [PW-1:0] packet_out; - 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 diff --git a/src/emesh/hdl/emesh_readback.v b/src/emesh/hdl/emesh_readback.v index 7a23d6b..b16e372 100644 --- a/src/emesh/hdl/emesh_readback.v +++ b/src/emesh/hdl/emesh_readback.v @@ -4,8 +4,8 @@ module emesh_readback (/*AUTOARG*/ // Inputs nreset, clk, access_in, packet_in, read_data, wait_in ); - parameter AW = 32; // address width - localparam PW = 2*AW+40; // packet width + parameter AW = 32; // address 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 diff --git a/src/emesh/hdl/packet2emesh.v b/src/emesh/hdl/packet2emesh.v index 3f56b60..9d74723 100644 --- a/src/emesh/hdl/packet2emesh.v +++ b/src/emesh/hdl/packet2emesh.v @@ -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 - ); - - 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; +//############################################################################# +//# 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 + ); + // ---- 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 diff --git a/src/etrace/hdl/etrace.v b/src/etrace/hdl/etrace.v index 62d93d6..753d276 100644 --- a/src/etrace/hdl/etrace.v +++ b/src/etrace/hdl/etrace.v @@ -164,15 +164,12 @@ module etrace (/*AUTOARG*/ //# SYNC CFG SIGNALS TO SAMPLE CLK //################################# - dsync #(.DW(1)) - - dsync(// Outputs - .dout (trace_enable), - // Inputs - .clk (trace_clk), - .din (mi_trace_enable) - ); - + dsync dsync(// Outputs + .dout (trace_enable), + // Inputs + .clk (trace_clk), + .din (mi_trace_enable)); + //########################### //# TIME KEEPER //########################### diff --git a/src/gpio/README.md b/src/gpio/README.md index 48c30c7..642f3fb 100644 --- a/src/gpio/README.md +++ b/src/gpio/README.md @@ -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) | diff --git a/src/gpio/driver/README.md b/src/gpio/driver/gpiolib/README.md similarity index 100% rename from src/gpio/driver/README.md rename to src/gpio/driver/gpiolib/README.md diff --git a/src/gpio/driver/gpio-epiphany.h b/src/gpio/driver/gpiolib/gpio-epiphany.h similarity index 100% rename from src/gpio/driver/gpio-epiphany.h rename to src/gpio/driver/gpiolib/gpio-epiphany.h diff --git a/src/gpio/driver/gpio-generic.h b/src/gpio/driver/gpiolib/gpio-generic.h similarity index 100% rename from src/gpio/driver/gpio-generic.h rename to src/gpio/driver/gpiolib/gpio-generic.h diff --git a/src/gpio/driver/gpio-simple.h b/src/gpio/driver/gpiolib/gpio-simple.h similarity index 100% rename from src/gpio/driver/gpio-simple.h rename to src/gpio/driver/gpiolib/gpio-simple.h diff --git a/src/gpio/driver/gpio.h b/src/gpio/driver/gpiolib/gpio.h similarity index 100% rename from src/gpio/driver/gpio.h rename to src/gpio/driver/gpiolib/gpio.h diff --git a/src/gpio/driver/gpio_example.c b/src/gpio/driver/gpiolib/gpio_example.c similarity index 100% rename from src/gpio/driver/gpio_example.c rename to src/gpio/driver/gpiolib/gpio_example.c diff --git a/src/gpio/driver/test.c b/src/gpio/driver/gpiolib/test.c similarity index 100% rename from src/gpio/driver/test.c rename to src/gpio/driver/gpiolib/test.c diff --git a/src/gpio/driver/linux/Documentation/devicetree/bindings/gpio/gpio-oh.txt b/src/gpio/driver/linux/Documentation/devicetree/bindings/gpio/gpio-oh.txt new file mode 100644 index 0000000..291bbc2 --- /dev/null +++ b/src/gpio/driver/linux/Documentation/devicetree/bindings/gpio/gpio-oh.txt @@ -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>; +}; diff --git a/src/gpio/driver/linux/Kbuild b/src/gpio/driver/linux/Kbuild new file mode 100644 index 0000000..c981446 --- /dev/null +++ b/src/gpio/driver/linux/Kbuild @@ -0,0 +1 @@ +obj-m := gpio-oh.o diff --git a/src/gpio/driver/linux/Makefile b/src/gpio/driver/linux/Makefile new file mode 100644 index 0000000..e86c498 --- /dev/null +++ b/src/gpio/driver/linux/Makefile @@ -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 diff --git a/src/gpio/driver/linux/README.md b/src/gpio/driver/linux/README.md new file mode 100644 index 0000000..aa4de9a --- /dev/null +++ b/src/gpio/driver/linux/README.md @@ -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 diff --git a/src/gpio/driver/linux/gpio-oh.c b/src/gpio/driver/linux/gpio-oh.c new file mode 100644 index 0000000..31b576d --- /dev/null +++ b/src/gpio/driver/linux/gpio-oh.c @@ -0,0 +1,503 @@ +/* + * Open Hardware GPIO device driver + * + * Copyright (C) 2016 Parallella Foundation + * Written by Ola Jeppsson + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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 "); +MODULE_DESCRIPTION("OH GPIO driver"); +MODULE_VERSION("0.1"); +MODULE_LICENSE("GPL"); diff --git a/src/gpio/fpga/bit2bin.bif b/src/gpio/fpga/bit2bin.bif new file mode 100644 index 0000000..df3de64 --- /dev/null +++ b/src/gpio/fpga/bit2bin.bif @@ -0,0 +1,6 @@ +the_ROM_image: +{ + [bootloader]dummy.elf + ./system.runs/impl_1/system_wrapper.bit +} + diff --git a/src/gpio/fpga/build.sh b/src/gpio/fpga/build.sh new file mode 100755 index 0000000..da2dc34 --- /dev/null +++ b/src/gpio/fpga/build.sh @@ -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 + diff --git a/src/gpio/fpga/dummy.elf b/src/gpio/fpga/dummy.elf new file mode 100644 index 0000000..6d0b3e0 Binary files /dev/null and b/src/gpio/fpga/dummy.elf differ diff --git a/src/gpio/fpga/ip_params.tcl b/src/gpio/fpga/ip_params.tcl new file mode 100644 index 0000000..0340451 --- /dev/null +++ b/src/gpio/fpga/ip_params.tcl @@ -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 [] + diff --git a/src/gpio/fpga/package.tcl b/src/gpio/fpga/package.tcl new file mode 100644 index 0000000..5128e86 --- /dev/null +++ b/src/gpio/fpga/package.tcl @@ -0,0 +1,3 @@ +#STEP1: DEFINE KEY PARAMETERS +source ./ip_params.tcl +source ../../common/fpga/create_ip.tcl diff --git a/src/gpio/fpga/run.tcl b/src/gpio/fpga/run.tcl new file mode 100644 index 0000000..0bbddc9 --- /dev/null +++ b/src/gpio/fpga/run.tcl @@ -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 diff --git a/src/gpio/fpga/run_params.tcl b/src/gpio/fpga/run_params.tcl new file mode 100644 index 0000000..f49db27 --- /dev/null +++ b/src/gpio/fpga/run_params.tcl @@ -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 \ + ] diff --git a/src/gpio/fpga/system_bd.tcl b/src/gpio/fpga/system_bd.tcl new file mode 100644 index 0000000..a6a5f1b --- /dev/null +++ b/src/gpio/fpga/system_bd.tcl @@ -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 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 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 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 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 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 ." + 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 "" + + diff --git a/src/gpio/fpga/system_params.tcl b/src/gpio/fpga/system_params.tcl new file mode 100644 index 0000000..f1312c6 --- /dev/null +++ b/src/gpio/fpga/system_params.tcl @@ -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 \ + ] + diff --git a/src/gpio/hdl/axi_gpio.v b/src/gpio/hdl/axi_gpio.v new file mode 100644 index 0000000..c7810bb --- /dev/null +++ b/src/gpio/hdl/axi_gpio.v @@ -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: diff --git a/src/gpio/hdl/gpio.v b/src/gpio/hdl/gpio.v index a2ccd01..434f57b 100644 --- a/src/gpio/hdl/gpio.v +++ b/src/gpio/hdl/gpio.v @@ -7,41 +7,36 @@ //############################################################################# `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 - input clk, // clock - input access_in, // register access - input [PW-1:0] packet_in, // data/address - output wait_out, // pushback from mesh - 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) - input [N-1:0] gpio_in, // data from IO pins - output gpio_irq // OR of GPIO_ILAT register + input nreset, // asynchronous active low reset + input clk, // clock + input access_in, // register access + input [PW-1:0] packet_in, // data/address + output wait_out, // pushback from mesh + output access_out, // register access + output [PW-1:0] packet_out, // data/address + input wait_in, // pushback from mesh + 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 ); //################################ //# 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,7 +46,20 @@ 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) wire [4:0] ctrlmode_in; // From p2e of packet2emesh.v @@ -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,10 +103,10 @@ 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 | - outclr_write | - outset_write | - outxor_write; + assign out_write = outreg_write | + outclr_write | + outset_write | + outxor_write; //################################ //# GPIO_DIR @@ -113,11 +122,10 @@ module gpio #( //# GPIO_IN //################################ - oh_dsync #(.DW(N)) - dsync (.dout (gpio_in_sync[N-1:0]), - .clk (clk), - .nreset (nreset), - .din (gpio_in[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])); always @ (posedge clk) gpio_in_old[N-1:0] <= gpio_in_sync[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]; //################################ @@ -202,17 +210,18 @@ 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; + case(dstaddr_in[6:3]) + `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), diff --git a/src/gpio/hdl/parallella_gpio.v b/src/gpio/hdl/parallella_gpio.v new file mode 100644 index 0000000..f9e32c7 --- /dev/null +++ b/src/gpio/hdl/parallella_gpio.v @@ -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: diff --git a/src/mio/driver/hello-mio/Makefile b/src/mio/driver/hello-mio/Makefile new file mode 100644 index 0000000..ff1b44f --- /dev/null +++ b/src/mio/driver/hello-mio/Makefile @@ -0,0 +1,8 @@ +CFLAGS ?= -g + +all: hello-mio + +clean: + rm -f hello-mio + +.PHONY: all clean diff --git a/src/mio/driver/hello-mio/README.md b/src/mio/driver/hello-mio/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/mio/driver/hello-mio/hello-mio.c b/src/mio/driver/hello-mio/hello-mio.c new file mode 100644 index 0000000..7642856 --- /dev/null +++ b/src/mio/driver/hello-mio/hello-mio.c @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/src/mio/driver/linux-uio/README.md b/src/mio/driver/linux-uio/README.md new file mode 100644 index 0000000..4eb7fe9 --- /dev/null +++ b/src/mio/driver/linux-uio/README.md @@ -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 diff --git a/src/mio/driver/linux-uio/uio.ko b/src/mio/driver/linux-uio/uio.ko new file mode 100644 index 0000000..7402075 Binary files /dev/null and b/src/mio/driver/linux-uio/uio.ko differ diff --git a/src/mio/driver/linux-uio/uio_pdrv_genirq.ko b/src/mio/driver/linux-uio/uio_pdrv_genirq.ko new file mode 100644 index 0000000..97ea822 Binary files /dev/null and b/src/mio/driver/linux-uio/uio_pdrv_genirq.ko differ diff --git a/src/mio/driver/linux-uio/zynq-parallella-oh-mio.dtb b/src/mio/driver/linux-uio/zynq-parallella-oh-mio.dtb new file mode 100644 index 0000000..4a75b5c Binary files /dev/null and b/src/mio/driver/linux-uio/zynq-parallella-oh-mio.dtb differ diff --git a/src/mio/driver/linux-uio/zynq-parallella-oh-mio.dts b/src/mio/driver/linux-uio/zynq-parallella-oh-mio.dts new file mode 100644 index 0000000..82c0d32 --- /dev/null +++ b/src/mio/driver/linux-uio/zynq-parallella-oh-mio.dts @@ -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"; +}; diff --git a/src/mio/hdl/mio.v b/src/mio/hdl/mio.v index 0227932..cf6dc91 100644 --- a/src/mio/hdl/mio.v +++ b/src/mio/hdl/mio.v @@ -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*/ diff --git a/src/mio/hdl/mio_dp.v b/src/mio/hdl/mio_dp.v index 5df8d1e..4550114 100644 --- a/src/mio/hdl/mio_dp.v +++ b/src/mio/hdl/mio_dp.v @@ -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), diff --git a/src/mio/hdl/mio_if.v b/src/mio/hdl/mio_if.v index ba16c27..31e598f 100644 --- a/src/mio/hdl/mio_if.v +++ b/src/mio/hdl/mio_if.v @@ -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]), diff --git a/src/mio/hdl/mio_regs.v b/src/mio/hdl/mio_regs.v index 5b98487..7eba20d 100644 --- a/src/mio/hdl/mio_regs.v +++ b/src/mio/hdl/mio_regs.v @@ -1,71 +1,80 @@ -`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 - ); +//############################################################################# +//# Function: MIO Configuration Registers # +//# (See README.md for complete documentation) # +//############################################################################# +//# Author: Andreas Olofsson # +//# License: MIT (see LICENSE file in this repository) # +//############################################################################# - // 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 +`include "mio_regmap.vh" +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 + ); + 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; - - // 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 - //###################################################################### + //############## + //# LOCAL WIRES + //############## + 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) wire [4:0] ctrlmode_in; // From p2e of packet2emesh.v @@ -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 //############################### diff --git a/src/mio/hdl/mrx_io.v b/src/mio/hdl/mrx_io.v index 8600eb7..c27510d 100644 --- a/src/mio/hdl/mrx_io.v +++ b/src/mio/hdl/mrx_io.v @@ -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) //######################################## diff --git a/src/mio/hdl/mrx_protocol.v b/src/mio/hdl/mrx_protocol.v index 64cd008..2d6d864 100644 --- a/src/mio/hdl/mrx_protocol.v +++ b/src/mio/hdl/mrx_protocol.v @@ -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 diff --git a/src/mio/hdl/mtx_io.v b/src/mio/hdl/mtx_io.v index dc4c5ba..41910fb 100644 --- a/src/mio/hdl/mtx_io.v +++ b/src/mio/hdl/mtx_io.v @@ -35,21 +35,26 @@ 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), - .clk (io_clk), - .nrst_in (nreset)); + oh_rsync #(.ASIC(ASIC)) + oh_rsync(.nrst_out (io_nreset), + .clk (io_clk), + .nrst_in (nreset)); //######################################## //# ACCESS (SDR) diff --git a/src/pic/dv/dut_pic.v b/src/pic/dv/dut_pic.v index c57f5ae..8ec5912 100644 --- a/src/pic/dv/dut_pic.v +++ b/src/pic/dv/dut_pic.v @@ -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 - .clk (clk1), - .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)); + 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])); endmodule diff --git a/src/pic/hdl/pic.v b/src/pic/hdl/pic.v index f8f1e58..962d083 100644 --- a/src/pic/hdl/pic.v +++ b/src/pic/hdl/pic.v @@ -1,90 +1,83 @@ +//############################################################################# +//# 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; - - //Basic Interface - input clk; //main clock - input nreset; //active low async reset +/*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 +*/ - //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; + 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 ic_write_imask; - wire ic_write_ipend; - wire ic_write_ilat; - wire ic_write_ilatset; - wire ic_write_ilatclr; - wire ic_write_iret; + 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; + wire ic_write_ilatset; + wire ic_write_ilatclr; + wire ic_write_iret; //########################### //ACCESS DECODE @@ -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] ; + ic_irq_shadow[IW-1:0] <= ext_irq[IW-1:0] ; - assign ic_event[IRQW-1:0] = ext_irq[IRQW-1:0] & ~ic_irq_shadow[IRQW-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=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;k0;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 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 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 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 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 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 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 ." + 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 "" + + diff --git a/src/spi/fpga/system_params.tcl b/src/spi/fpga/system_params.tcl new file mode 100644 index 0000000..3f042e9 --- /dev/null +++ b/src/spi/fpga/system_params.tcl @@ -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 \ + ] + diff --git a/src/spi/hdl/axi_spi.v b/src/spi/hdl/axi_spi.v new file mode 100644 index 0000000..2122cfb --- /dev/null +++ b/src/spi/hdl/axi_spi.v @@ -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: diff --git a/src/spi/hdl/parallella_spi.v b/src/spi/hdl/parallella_spi.v new file mode 100644 index 0000000..46e14fc --- /dev/null +++ b/src/spi/hdl/parallella_spi.v @@ -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: diff --git a/src/spi/hdl/spi.v b/src/spi/hdl/spi.v index 830e837..356faa4 100644 --- a/src/spi/hdl/spi.v +++ b/src/spi/hdl/spi.v @@ -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. // -// // -////////////////////////////////////////////////////////////////////////////// diff --git a/src/spi/hdl/spi_master.v b/src/spi/hdl/spi_master.v index 12a07e0..36a3b83 100644 --- a/src/spi/hdl/spi_master.v +++ b/src/spi/hdl/spi_master.v @@ -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 - ); - - //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 +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 + ); - //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. // -// // -////////////////////////////////////////////////////////////////////////////// diff --git a/src/spi/hdl/spi_master_fifo.v b/src/spi/hdl/spi_master_fifo.v index 54bff48..49c9e07 100644 --- a/src/spi/hdl/spi_master_fifo.v +++ b/src/spi/hdl/spi_master_fifo.v @@ -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 - //##################################################################### +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 + // Incoming interface + 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 + ); - //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 - - //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 - - // Incoming interface - 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 - - //################################## - //# 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), @@ -112,7 +114,7 @@ module spi_master_fifo (/*AUTOARG*/ //################################### oh_fifo_sync #(.DEPTH(DEPTH), - .DW(SW)) + .DW(SW)) fifo(// Outputs .dout (fifo_dout[7:0]), .full (fifo_full), diff --git a/src/spi/hdl/spi_master_io.v b/src/spi/hdl/spi_master_io.v index c86423d..3fb2678 100644 --- a/src/spi/hdl/spi_master_io.v +++ b/src/spi/hdl/spi_master_io.v @@ -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. // -// // -/////////////////////////////////////////////////////////////////////////////// - diff --git a/src/spi/hdl/spi_master_regs.v b/src/spi/hdl/spi_master_regs.v index 2f86a03..458b211 100644 --- a/src/spi/hdl/spi_master_regs.v +++ b/src/spi/hdl/spi_master_regs.v @@ -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 - ); - - //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 - //######################################################## +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 + ); + //############### + //# 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; - - integer i; - 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; + /*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]), diff --git a/src/spi/hdl/spi_regmap.vh b/src/spi/hdl/spi_regmap.vh index 667c824..3709031 100644 --- a/src/spi/hdl/spi_regmap.vh +++ b/src/spi/hdl/spi_regmap.vh @@ -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_ diff --git a/src/spi/hdl/spi_slave.v b/src/spi/hdl/spi_slave.v index d481ab2..26bf49e 100644 --- a/src/spi/hdl/spi_slave.v +++ b/src/spi/hdl/spi_slave.v @@ -1,50 +1,40 @@ //############################################################################# -//# Purpose: SPI slave module # +//# Purpose: SPI slave # //############################################################################# //# Author: Andreas Olofsson # -//# License: MIT (see below) # +//# License: MIT (see LICENSE file in OH! repository) # //############################################################################# -module spi_slave(/*AUTOARG*/ - // Outputs - spi_regs, spi_irq, miso, access_out, packet_out, wait_out, - // Inputs - clk, nreset, hw_en, sclk, mosi, ss, wait_in, access_in, packet_in - ); - - //parameters - parameter UREGS = 13; // total spi slave 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; // block enbale pin - output [511:0] spi_regs; // all registers for control - output spi_irq; // interrupt +module spi_slave #( parameter UREGS = 13, // number of spi slave 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, // block enbale pin + output [511:0] spi_regs, // all registers for control + output spi_irq, // interrupt + //IO interface + input sclk, // spi clock + input mosi, // slave input + input ss, // slave select + output miso, // slave output + // read request to core + output access_out, // valid transaction + output [PW-1:0] packet_out, // data to core (from spi port) + input wait_in, // pushback from core (not implemented) + // return from core + input access_in, // read response from core + input [PW-1:0] packet_in, // read response packet from core + output wait_out // pushback (not used) + ); - //IO interface - input sclk; // spi clock - input mosi; // slave input - input ss; // slave select - output miso; // slave output - - - // read request to core - output access_out; // valid transaction - output [PW-1:0] packet_out; // data to core (from spi port) - input wait_in; // pushback from core (not implemented) - - // return from core - input access_in; // read response from core - input [PW-1:0] packet_in; // read response packet from core - output wait_out; // pushback (not used) - + //############### + //# LOCAL WIRES + //############### /*AUTOINPUT*/ - - // End of automatics - /*AUTOWIRE*/ // Beginning of automatic wires (for undeclared instantiated-module outputs) wire cpha; // From spi_slave_regs of spi_slave_regs.v @@ -60,6 +50,7 @@ module spi_slave(/*AUTOARG*/ // End of automatics spi_slave_regs #(.AW(AW), + .PW(PW), .UREGS(UREGS)) spi_slave_regs (/*AUTOINST*/ // Outputs @@ -84,7 +75,7 @@ module spi_slave(/*AUTOARG*/ .packet_in (packet_in[PW-1:0])); - spi_slave_io #(.AW(AW)) + spi_slave_io #(.PW(PW)) spi_slave_io (/*AUTOINST*/ // Outputs .miso (miso), @@ -109,28 +100,3 @@ module spi_slave(/*AUTOARG*/ endmodule // spi_slave - -////////////////////////////////////////////////////////////////////////////// -// 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. // -// // -////////////////////////////////////////////////////////////////////////////// diff --git a/src/spi/hdl/spi_slave_io.v b/src/spi/hdl/spi_slave_io.v index 997a635..cc4e694 100644 --- a/src/spi/hdl/spi_slave_io.v +++ b/src/spi/hdl/spi_slave_io.v @@ -1,84 +1,74 @@ //############################################################################# -//# Purpose: SPI slave IO and statemachine # +//# Purpose: SPI slave IO state-machine # //############################################################################# //# Author: Andreas Olofsson # -//# License: MIT (see below) # +//# License: MIT (see LICENSE file in OH! repository) # //############################################################################# `include "spi_regmap.vh" -module spi_slave_io(/*AUTOARG*/ - // Outputs - miso, spi_clk, spi_write, spi_addr, spi_wdata, spi_rdata, - access_out, packet_out, - // Inputs - sclk, mosi, ss, spi_en, cpol, cpha, lsbfirst, clk, nreset, wait_in - ); +module spi_slave_io #( parameter PW = 104 // packet width + ) + ( + //IO interface + input sclk, // slave clock + input mosi, // slave input + input ss, // slave select + output miso, // slave output + //Control + input spi_en, // spi enable + input cpol, // cpol + input cpha, // cpha + input lsbfirst, // lsbfirst + //register file interface + output spi_clk, // spi clock for regfile + output spi_write, // regfile write + output [5:0] spi_addr, // regfile addres + output [7:0] spi_wdata, // data for regfile + output [7:0] spi_rdata, // data for regfile + //core interface (synced to core clk) + input clk, // core clock + input nreset, // async active low reset + output reg access_out, // read or write core command + output [PW-1:0] packet_out, // packet + input wait_in // temporary pushback + ); - //################################# - //# INTERFACE - //################################# - - //parameters - parameter SREGS = 16; // total regs (16/32/64) - parameter AW = 32; // address width - localparam PW = (2*AW+40); // packet width + //############### + //# LOCAL WIRES + //############### + reg [1:0] spi_state; + reg [7:0] bit_count; + reg [7:0] command_reg; + reg fetch_command; + wire [7:0] rx_data; + wire [63:0] tx_data; + wire rx_shift; + wire tx_load; + wire tx_shift; + wire tx_wait; + wire ss_sync; + wire ss_pulse; + wire spi_fetch; + wire byte_done; - //IO interface - input sclk; // slave clock - input mosi; // slave input - input ss; // slave select - output miso; // slave output - - //Control - input spi_en; // spi enable - input cpol; // cpol - input cpha; // cpha - input lsbfirst; // lsbfirst - //register file interface - output spi_clk; // spi clock for regfile - output spi_write; // regfile write - output [5:0] spi_addr; // regfile addres - output [7:0] spi_wdata; // data for regfile - output [7:0] spi_rdata; // data for regfile - - //core interface (synced to core clk) - input clk; // core clock - input nreset; // async active low reset - output access_out; // read or write core command - output [PW-1:0] packet_out; // packet - input wait_in; // temporary pushback - - //################################# - //# BODY - //################################# - - reg [1:0] spi_state; - reg [7:0] bit_count; - reg [7:0] command_reg; - reg access_out; - reg fetch_command; - - wire [7:0] rx_data; - wire [63:0] tx_data; - //################################# //# STATE MACHINE - //################################# + //################################# -`define SPI_IDLE 2'b00 // when ss is high -`define SPI_CMD 2'b01 // 8 cycles for command/addr -`define SPI_DATA 2'b10 // stay in datamode until done +`define SPI_IDLE_STATE 2'b00 // when ss is high +`define SPI_CMD_STATE 2'b01 // 8 cycles for command/addr +`define SPI_DATA_STATE 2'b10 // stay in datamode until done //state machine always @ (posedge sclk or posedge ss) if(ss) - spi_state[1:0] <= `SPI_IDLE; + spi_state[1:0] <= `SPI_IDLE_STATE; else case (spi_state[1:0]) - `SPI_IDLE : spi_state[1:0] <= `SPI_CMD; - `SPI_CMD : spi_state[1:0] <= byte_done ? `SPI_DATA : `SPI_CMD; - `SPI_DATA : spi_state[1:0] <= `SPI_DATA; + `SPI_IDLE_STATE : spi_state[1:0] <= `SPI_CMD_STATE; + `SPI_CMD_STATE : spi_state[1:0] <= byte_done ? `SPI_DATA_STATE : `SPI_CMD_STATE; + `SPI_DATA_STATE : spi_state[1:0] <= `SPI_DATA_STATE; endcase // case (spi_state[1:0]) //bit counter @@ -88,7 +78,7 @@ module spi_slave_io(/*AUTOARG*/ else bit_count[7:0] <= bit_count[7:0] + 1'b1; - assign byte_done = (spi_state[1:0]!=`SPI_IDLE) & + assign byte_done = (spi_state[1:0]!=`SPI_IDLE_STATE) & (bit_count[2:0]==3'b000); // command/address register @@ -96,7 +86,7 @@ module spi_slave_io(/*AUTOARG*/ always @ (negedge sclk or negedge nreset) if(!nreset) command_reg[7:0] <= 'b0; - else if((spi_state[1:0]==`SPI_CMD) & byte_done) + else if((spi_state[1:0]==`SPI_CMD_STATE) & byte_done) command_reg[7:0] <= rx_data[7:0]; else if(byte_done) command_reg[7:0] <= {command_reg[7:6], @@ -136,7 +126,7 @@ module spi_slave_io(/*AUTOARG*/ //# TX SHIFT REGISTER //################################# - assign tx_load = byte_done; // & (spi_state[1:0]==`SPI_CMD); + assign tx_load = byte_done; // & (spi_state[1:0]==`SPI_CMD_STATE); assign tx_shift = ~ss & spi_en; oh_par2ser #(.PW(8), @@ -166,7 +156,7 @@ module spi_slave_io(/*AUTOARG*/ byte_done & ~ss & (command_reg[7:6]==`SPI_WR) & - (spi_state[1:0]==`SPI_DATA); + (spi_state[1:0]==`SPI_DATA_STATE); assign spi_wdata[7:0] = rx_data[7:0]; diff --git a/src/spi/hdl/spi_slave_regs.v b/src/spi/hdl/spi_slave_regs.v index 89ad484..34684e0 100644 --- a/src/spi/hdl/spi_slave_regs.v +++ b/src/spi/hdl/spi_slave_regs.v @@ -1,65 +1,58 @@ //############################################################################# -//# Purpose: SPI slave port register file # +//# Purpose: SPI slave register file # //############################################################################# //# Author: Andreas Olofsson # -//# License: MIT (see below) # +//# License: MIT (see LICENSE file in OH! repository) # //############################################################################# `include "spi_regmap.vh" -module spi_slave_regs (/*AUTOARG*/ - // Outputs - spi_rdata, spi_en, cpol, cpha, lsbfirst, irq_en, spi_regs, - wait_out, - // Inputs - clk, nreset, hw_en, spi_clk, spi_wdata, spi_write, spi_addr, - access_out, access_in, packet_in - ); - - //parameters - parameter UREGS = 13; // number of user regs (max 48) - parameter CHIPID = 0; // reset chipid value - parameter AW = 32; // address width - localparam PW = (2*AW+40); // packet width - localparam SREGS = UREGS+32; // total regs - +module spi_slave_regs #( parameter UREGS = 13, // # of user regs (max 48) + parameter SREGS = UREGS+32,// total regs + parameter AW = 32, // address width + parameter PW = 104 // packet width + ) + ( // clk, rest, chipid - input clk; // core clock - input nreset; // asych active low - input hw_en; // block enable pin - + input clk, // core clock + input nreset, // asych active low + input hw_en, // block enable pin // sclk io domain - input spi_clk; // slave clock - input [7:0] spi_wdata; // slave write data in (for write) - input spi_write; // slave write - input [5:0] spi_addr; // slave write addr (64 regs) - output [7:0] spi_rdata; // slave read data - + input spi_clk, // slave clock + input [7:0] spi_wdata, // slave write data in (for write) + input spi_write, // slave write + input [5:0] spi_addr, // slave write addr (64 regs) + output [7:0] spi_rdata, // slave read data // cfg bits - output spi_en; // enable spi - output cpol; // clk polarity (default is 0) - output cpha; // clk phase shift (default is 0) - output lsbfirst; // send lsbfirst - output irq_en; // interrupt enable - output [511:0] spi_regs; // all regs concatenated for easy read - + output spi_en, // enable spi + output cpol, // clk polarity (default is 0) + output cpha, // clk phase shift (default is 0) + output lsbfirst, // send lsbfirst + output irq_en, // interrupt enable + output reg [511:0] spi_regs, // all regs concatenated for easy read // split transaction for core clock domain - input access_out; // signal used to clear status - input access_in; - input [PW-1:0] packet_in; // writeback data - output wait_out; // 0 - - //regs + input access_out, // signal used to clear status + input access_in, + input [PW-1:0] packet_in, // writeback data + output wait_out + ); + + //############### + //# LOCAL WIRES + //############### reg [7:0] spi_config; reg [7:0] spi_status; reg [7:0] spi_cmd; reg [7:0] spi_psize; - reg [63:0] core_regs; reg [7:0] user_regs[UREGS-1:0]; - reg [511:0] spi_regs; - wire [63:0] core_data; + wire [63:0] core_data; + wire config_write; + wire user_write; + wire status_write; + wire valid; + + integer i; - /*AUTOWIRE*/ // Beginning of automatic wires (for undeclared instantiated-module outputs) wire [4:0] ctrlmode_in; // From pe2 of packet2emesh.v @@ -74,16 +67,17 @@ module spi_slave_regs (/*AUTOARG*/ //# SPI DECODE //##################################### - assign spi_config_write = spi_write & (spi_addr[5:0]==`SPI_CONFIG); - assign spi_status_write = spi_write & (spi_addr[5:0]==`SPI_STATUS); - assign spi_user_write = spi_write & (spi_addr[5]); + assign config_write = spi_write & (spi_addr[5:0]==`SPI_CONFIG); + assign status_write = spi_write & (spi_addr[5:0]==`SPI_STATUS); + assign user_write = spi_write & (spi_addr[5]); //##################################### //# CORE DECODE //##################################### assign wait_out = 1'b0; - packet2emesh #(.AW(AW)) + packet2emesh #(.AW(AW), + .PW(PW)) pe2 (/*AUTOINST*/ // Outputs .write_in (write_in), @@ -104,7 +98,7 @@ module spi_slave_regs (/*AUTOARG*/ always @ (negedge spi_clk or negedge nreset) if(!nreset) spi_config[7:0] <= 'b0; - else if(spi_config_write) + else if(config_write) spi_config[7:0] <= spi_wdata[7:0]; assign spi_en = hw_en & ~spi_config[0]; // disable spi (for security) @@ -138,7 +132,7 @@ module spi_slave_regs (/*AUTOARG*/ //##################################### always @ (negedge spi_clk) - if(spi_user_write) + if(user_write) user_regs[spi_addr[4:0]] <= spi_wdata[7:0]; //##################################### @@ -166,32 +160,6 @@ module spi_slave_regs (/*AUTOARG*/ assign spi_rdata[7:0] = spi_regs[8*spi_addr[5:0]+:8]; endmodule // spi_slave_regs - // 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. // -// // -////////////////////////////////////////////////////////////////////////////// diff --git a/src/xilibs/hdl/BUF.v b/src/xilibs/dv/BUF.v similarity index 100% rename from src/xilibs/hdl/BUF.v rename to src/xilibs/dv/BUF.v diff --git a/src/xilibs/hdl/BUFG.v b/src/xilibs/dv/BUFG.v similarity index 100% rename from src/xilibs/hdl/BUFG.v rename to src/xilibs/dv/BUFG.v diff --git a/src/xilibs/hdl/BUFIO.v b/src/xilibs/dv/BUFIO.v similarity index 100% rename from src/xilibs/hdl/BUFIO.v rename to src/xilibs/dv/BUFIO.v diff --git a/src/xilibs/hdl/BUFR.v b/src/xilibs/dv/BUFR.v similarity index 100% rename from src/xilibs/hdl/BUFR.v rename to src/xilibs/dv/BUFR.v diff --git a/src/xilibs/hdl/CLKDIV.v b/src/xilibs/dv/CLKDIV.v similarity index 100% rename from src/xilibs/hdl/CLKDIV.v rename to src/xilibs/dv/CLKDIV.v diff --git a/src/xilibs/hdl/IBUF.v b/src/xilibs/dv/IBUF.v similarity index 100% rename from src/xilibs/hdl/IBUF.v rename to src/xilibs/dv/IBUF.v diff --git a/src/xilibs/hdl/IBUFDS.v b/src/xilibs/dv/IBUFDS.v similarity index 100% rename from src/xilibs/hdl/IBUFDS.v rename to src/xilibs/dv/IBUFDS.v diff --git a/src/xilibs/hdl/IBUFDS_DIFF_OUT.v b/src/xilibs/dv/IBUFDS_DIFF_OUT.v similarity index 100% rename from src/xilibs/hdl/IBUFDS_DIFF_OUT.v rename to src/xilibs/dv/IBUFDS_DIFF_OUT.v diff --git a/src/xilibs/hdl/IBUFDS_GTE2.v b/src/xilibs/dv/IBUFDS_GTE2.v similarity index 100% rename from src/xilibs/hdl/IBUFDS_GTE2.v rename to src/xilibs/dv/IBUFDS_GTE2.v diff --git a/src/xilibs/hdl/IBUFDS_IBUFDISABLE.v b/src/xilibs/dv/IBUFDS_IBUFDISABLE.v similarity index 100% rename from src/xilibs/hdl/IBUFDS_IBUFDISABLE.v rename to src/xilibs/dv/IBUFDS_IBUFDISABLE.v diff --git a/src/xilibs/hdl/IBUFDS_IBUFDISABLE_INT.v b/src/xilibs/dv/IBUFDS_IBUFDISABLE_INT.v similarity index 100% rename from src/xilibs/hdl/IBUFDS_IBUFDISABLE_INT.v rename to src/xilibs/dv/IBUFDS_IBUFDISABLE_INT.v diff --git a/src/xilibs/hdl/IBUFDS_INTERMDISABLE.v b/src/xilibs/dv/IBUFDS_INTERMDISABLE.v similarity index 100% rename from src/xilibs/hdl/IBUFDS_INTERMDISABLE.v rename to src/xilibs/dv/IBUFDS_INTERMDISABLE.v diff --git a/src/xilibs/hdl/IBUFDS_INTERMDISABLE_INT.v b/src/xilibs/dv/IBUFDS_INTERMDISABLE_INT.v similarity index 100% rename from src/xilibs/hdl/IBUFDS_INTERMDISABLE_INT.v rename to src/xilibs/dv/IBUFDS_INTERMDISABLE_INT.v diff --git a/src/xilibs/hdl/IBUFE3.v b/src/xilibs/dv/IBUFE3.v similarity index 100% rename from src/xilibs/hdl/IBUFE3.v rename to src/xilibs/dv/IBUFE3.v diff --git a/src/xilibs/hdl/IBUFGDS.v b/src/xilibs/dv/IBUFGDS.v similarity index 100% rename from src/xilibs/hdl/IBUFGDS.v rename to src/xilibs/dv/IBUFGDS.v diff --git a/src/xilibs/hdl/IBUF_IBUFDISABLE.v b/src/xilibs/dv/IBUF_IBUFDISABLE.v similarity index 100% rename from src/xilibs/hdl/IBUF_IBUFDISABLE.v rename to src/xilibs/dv/IBUF_IBUFDISABLE.v diff --git a/src/xilibs/hdl/IBUF_INTERMDISABLE.v b/src/xilibs/dv/IBUF_INTERMDISABLE.v similarity index 100% rename from src/xilibs/hdl/IBUF_INTERMDISABLE.v rename to src/xilibs/dv/IBUF_INTERMDISABLE.v diff --git a/src/xilibs/hdl/IDDR.v b/src/xilibs/dv/IDDR.v similarity index 100% rename from src/xilibs/hdl/IDDR.v rename to src/xilibs/dv/IDDR.v diff --git a/src/xilibs/hdl/IDELAYCTRL.v b/src/xilibs/dv/IDELAYCTRL.v similarity index 100% rename from src/xilibs/hdl/IDELAYCTRL.v rename to src/xilibs/dv/IDELAYCTRL.v diff --git a/src/xilibs/hdl/IDELAYE2.v b/src/xilibs/dv/IDELAYE2.v similarity index 100% rename from src/xilibs/hdl/IDELAYE2.v rename to src/xilibs/dv/IDELAYE2.v diff --git a/src/xilibs/hdl/IDELAYE2_FINEDELAY.v b/src/xilibs/dv/IDELAYE2_FINEDELAY.v similarity index 100% rename from src/xilibs/hdl/IDELAYE2_FINEDELAY.v rename to src/xilibs/dv/IDELAYE2_FINEDELAY.v diff --git a/src/xilibs/hdl/IDELAYE3.v b/src/xilibs/dv/IDELAYE3.v similarity index 100% rename from src/xilibs/hdl/IDELAYE3.v rename to src/xilibs/dv/IDELAYE3.v diff --git a/src/xilibs/hdl/IOBUF.v b/src/xilibs/dv/IOBUF.v similarity index 100% rename from src/xilibs/hdl/IOBUF.v rename to src/xilibs/dv/IOBUF.v diff --git a/src/xilibs/hdl/IOBUFDS.v b/src/xilibs/dv/IOBUFDS.v similarity index 100% rename from src/xilibs/hdl/IOBUFDS.v rename to src/xilibs/dv/IOBUFDS.v diff --git a/src/xilibs/hdl/IOBUFDSE3.v b/src/xilibs/dv/IOBUFDSE3.v similarity index 100% rename from src/xilibs/hdl/IOBUFDSE3.v rename to src/xilibs/dv/IOBUFDSE3.v diff --git a/src/xilibs/hdl/IOBUFDS_DCIEN.v b/src/xilibs/dv/IOBUFDS_DCIEN.v similarity index 100% rename from src/xilibs/hdl/IOBUFDS_DCIEN.v rename to src/xilibs/dv/IOBUFDS_DCIEN.v diff --git a/src/xilibs/hdl/IOBUFDS_DIFF_OUT_INTERMDISABLE.v b/src/xilibs/dv/IOBUFDS_DIFF_OUT_INTERMDISABLE.v similarity index 100% rename from src/xilibs/hdl/IOBUFDS_DIFF_OUT_INTERMDISABLE.v rename to src/xilibs/dv/IOBUFDS_DIFF_OUT_INTERMDISABLE.v diff --git a/src/xilibs/hdl/IOBUF_INTERMDISABLE.v b/src/xilibs/dv/IOBUF_INTERMDISABLE.v similarity index 100% rename from src/xilibs/hdl/IOBUF_INTERMDISABLE.v rename to src/xilibs/dv/IOBUF_INTERMDISABLE.v diff --git a/src/xilibs/hdl/ISERDESE2.v b/src/xilibs/dv/ISERDESE2.v similarity index 100% rename from src/xilibs/hdl/ISERDESE2.v rename to src/xilibs/dv/ISERDESE2.v diff --git a/src/xilibs/hdl/MMCME2_ADV.v b/src/xilibs/dv/MMCME2_ADV.v similarity index 100% rename from src/xilibs/hdl/MMCME2_ADV.v rename to src/xilibs/dv/MMCME2_ADV.v diff --git a/src/xilibs/hdl/OBUF.v b/src/xilibs/dv/OBUF.v similarity index 100% rename from src/xilibs/hdl/OBUF.v rename to src/xilibs/dv/OBUF.v diff --git a/src/xilibs/hdl/OBUFDS.v b/src/xilibs/dv/OBUFDS.v similarity index 100% rename from src/xilibs/hdl/OBUFDS.v rename to src/xilibs/dv/OBUFDS.v diff --git a/src/xilibs/hdl/OBUFDS_GTE3_ADV.v b/src/xilibs/dv/OBUFDS_GTE3_ADV.v similarity index 100% rename from src/xilibs/hdl/OBUFDS_GTE3_ADV.v rename to src/xilibs/dv/OBUFDS_GTE3_ADV.v diff --git a/src/xilibs/hdl/OBUFT.v b/src/xilibs/dv/OBUFT.v similarity index 100% rename from src/xilibs/hdl/OBUFT.v rename to src/xilibs/dv/OBUFT.v diff --git a/src/xilibs/hdl/OBUFTDS.v b/src/xilibs/dv/OBUFTDS.v similarity index 100% rename from src/xilibs/hdl/OBUFTDS.v rename to src/xilibs/dv/OBUFTDS.v diff --git a/src/xilibs/hdl/OBUFTDS_DCIEN.v b/src/xilibs/dv/OBUFTDS_DCIEN.v similarity index 100% rename from src/xilibs/hdl/OBUFTDS_DCIEN.v rename to src/xilibs/dv/OBUFTDS_DCIEN.v diff --git a/src/xilibs/hdl/ODDR.v b/src/xilibs/dv/ODDR.v similarity index 100% rename from src/xilibs/hdl/ODDR.v rename to src/xilibs/dv/ODDR.v diff --git a/src/xilibs/hdl/ODELAYE2.v b/src/xilibs/dv/ODELAYE2.v similarity index 100% rename from src/xilibs/hdl/ODELAYE2.v rename to src/xilibs/dv/ODELAYE2.v diff --git a/src/xilibs/hdl/OSERDESE2.v b/src/xilibs/dv/OSERDESE2.v similarity index 100% rename from src/xilibs/hdl/OSERDESE2.v rename to src/xilibs/dv/OSERDESE2.v diff --git a/src/xilibs/hdl/PLLE2_ADV.v b/src/xilibs/dv/PLLE2_ADV.v similarity index 100% rename from src/xilibs/hdl/PLLE2_ADV.v rename to src/xilibs/dv/PLLE2_ADV.v diff --git a/src/xilibs/hdl/PLLE2_BASE.v b/src/xilibs/dv/PLLE2_BASE.v similarity index 100% rename from src/xilibs/hdl/PLLE2_BASE.v rename to src/xilibs/dv/PLLE2_BASE.v diff --git a/src/xilibs/hdl/RAM32X1D.v b/src/xilibs/dv/RAM32X1D.v similarity index 100% rename from src/xilibs/hdl/RAM32X1D.v rename to src/xilibs/dv/RAM32X1D.v diff --git a/src/xilibs/hdl/fifo_async_104x32.v b/src/xilibs/dv/fifo_async_104x32.v similarity index 100% rename from src/xilibs/hdl/fifo_async_104x32.v rename to src/xilibs/dv/fifo_async_104x32.v diff --git a/src/xilibs/hdl/fifo_generator_vlog_beh.v b/src/xilibs/dv/fifo_generator_vlog_beh.v similarity index 100% rename from src/xilibs/hdl/fifo_generator_vlog_beh.v rename to src/xilibs/dv/fifo_generator_vlog_beh.v