diff --git a/EF_SPI.yaml b/EF_SPI.yaml index 1aa72db..2449fde 100644 --- a/EF_SPI.yaml +++ b/EF_SPI.yaml @@ -15,43 +15,31 @@ info: - comm - spi bus: - - APB + - generic type: soft status: verified cell_count: - IP: N/A - APB: N/A + - AHBL: N/A + - WB: N/A width: "0.0" height: "0.0" technology: n/a clock_freq_mhz: - IP: N/A - APB: N/A + - AHBL: N/A + - WB: N/A digital_supply_voltage: n/a analog_supply_voltage: n/a + parameters: - - name: DATA_WIDTH - default: 16 - description: The number of bits of data per transaction - - name: NUM_PORTS - default: 1 - description: Number of data ports - name: CLK_DIVIDER_WIDTH default: 8 description: =Number of bits for the clock divider (used to generate spi clock from main clock) - - name: SAMPLE_PHASE - default: 0 - description: "" ports: - - name: clk - width: 1 - direction: input - description: - - name: resetb - width: 1 - direction: input - description: - name: CPOL width: 1 direction: input @@ -69,11 +57,11 @@ ports: direction: input description: - name: datai - width: NUM_PORTS*DATA_WIDTH + width: 8 direction: input description: - name: datao - width: NUM_PORTS*DATA_WIDTH + width: 8 direction: output description: - name: busy @@ -83,32 +71,20 @@ ports: - name: done width: 1 direction: output - description: - - name: dout - width: NUM_PORTS - direction: input - description: - - name: din - width: NUM_PORTS - direction: output - description: - - name: csb - width: 1 - direction: output - description: - - name: sclk + description: + - name: ss width: 1 - direction: output - description: + direction: input + description: external_interface: - name: dout port: dout - width: NUM_PORTS + width: 1 direction: input description: - name: din port: din - width: NUM_PORTS + width: 1 direction: output description: - name: csb @@ -129,11 +105,12 @@ reset: registers: - name: DATA size: 8 - mode: w + mode: rw fifo: no offset: 0 bit_access: no - write_port: "" + read_port: datao + write_port: datai description: Data transmitted and received - name: CFG size: 2 @@ -141,37 +118,35 @@ registers: fifo: no offset: 8 bit_access: no - write_port: "" description: "" fields: - name: cpol bit_offset: 0 bit_width: 1 - write_port: "" + write_port: CPOL description: "clock polarity" - name: cpha bit_offset: 1 bit_width: 1 - write_port: "" + write_port: CPHA description: "clock phase" - name: STATUS - size: 1 + size: 2 mode: r fifo: no offset: 16 bit_access: no - read_port: "" description: "" fields: - name: done bit_offset: 0 bit_width: 1 - write_port: "" + read_port: done description: "" - name: busy bit_offset: 1 bit_width: 1 - write_port: "" + read_port: busy description: "" - name: CTRL size: 2 @@ -179,18 +154,18 @@ registers: fifo: no offset: 24 bit_access: no - write_port: "" description: "" fields: - name: start bit_offset: 0 bit_width: 1 - write_port: "" + write_port: go description: "self clear field" + auto_clear: True - name: SSn bit_offset: 1 bit_width: 1 - write_port: "" + write_port: ss description: "" - name: PR size: 16 @@ -199,9 +174,9 @@ registers: offset: 32 init: "'h2" bit_access: no - write_port: "" + write_port: clk_divider description: SCK PRESCALER should have value >= 2 flags: - name: Done - port: Done + port: done description: transimation is done diff --git a/hdl/rtl/bus_wrappers/APB_SPI.v b/hdl/rtl/bus_wrappers/APB_SPI.v deleted file mode 100644 index 4cd965d..0000000 --- a/hdl/rtl/bus_wrappers/APB_SPI.v +++ /dev/null @@ -1,161 +0,0 @@ -/* - _ _ ___ ___ ___ ___ - | \| | __| / __| _ \_ _| - | .` |__ \ \__ \ _/| | - |_|\_|___/ |___/_| |___| - Copyright 2020 Mohamed Shalan - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - APB Interface for SPI Master Controller by Lane Brooks (Ubixum) - APB Registers: - [0x00] DATA (W): 0-7: data in - [0x00] DATA (R): 0-7: data out - [0x08] CFG (W): 0:cpol, 1:cpha - [0x10] STATUS (R): 0: done - [0x18] CTRL (RW): 0: Start, 1:S Sn - [0x20] PRE (RW) 0-7: SCK PRESCALER - [0x30] IM (RW): Interrups Mask regsiter - [0x38] IC (RW): Interrups Clear regsiter -*/ - -`timescale 1ns/1ps -`default_nettype none - -`define APB_SPI_REG(name, size, init, name_sel, name_OFF) \ - reg [size-1:0] name; \ - wire name_sel = PENABLE & PWRITE & PREADY & PSEL & (PADDR[7:3] == name_OFF); \ - always @(posedge PCLK or negedge PRESETn) \ - if (~PRESETn) \ - name <= init; \ - else if (name_sel) \ - name <= PWDATA[size-1:0]; - -module EF_SPI_APB( - input wire PCLK, - input wire PRESETn, - - input wire PWRITE, - input wire [31:0] PWDATA, - input wire [31:0] PADDR, - input wire PENABLE, - input wire PSEL, - output wire PREADY, - output wire [31:0] PRDATA, - output wire IRQ, - - input wire MSI, - output wire MSO, - output wire SSn, - output wire SCK -); - - parameter [4:0] DATA_REG_OFF = 5'h0, - CFG_REG_OFF = 5'h1, - STATUS_REG_OFF = 5'h2, - CTRL_REG_OFF = 5'h3, - PRE_REG_OFF = 5'h4, - IM_REG_OFF = 5'h6, - IC_REG_OFF = 5'h7; - - wire go, - cpol, - cpha, - done, - busy, - csb; - - wire [7:0] datai, - datao, - clkdiv; - - `APB_SPI_REG(DATA_REG, 8, 0, DATA_REG_sel, DATA_REG_OFF) - `APB_SPI_REG(CFG_REG, 2, 0, CFG_REG_sel, CFG_REG_OFF) - // `APB_SPI_REG(CTRL_REG, 2, 0, CTRL_REG_sel, CTRL_REG_OFF) - `APB_SPI_REG(PRE_REG, 8, 2, PRE_REG_sel, PRE_REG_OFF) - `APB_SPI_REG(IM_REG, 1, 0, IM_REG_sel, IM_REG_OFF) - // make CTRL_REG[0] self clear register - reg [1:0] CTRL_REG; - wire CTRL_REG_sel = PENABLE & PWRITE & PREADY & PSEL & (PADDR[7:3] == CTRL_REG_OFF); - always @(posedge PCLK or negedge PRESETn) - if (~PRESETn) - CTRL_REG <= 0; - else if (CTRL_REG_sel) - CTRL_REG <= PWDATA[1:0]; - else - CTRL_REG[0] <= 1'b0; - - reg IC_REG; - wire IC_REG_sel = (PENABLE & PWRITE & PREADY & PSEL & (PADDR[7:3] == IC_REG_OFF)); - always @(posedge PCLK, negedge PRESETn) - if(!PRESETn) - IC_REG <= 1'b0; - else if(IC_REG_sel) - IC_REG <= PWDATA[0:0]; - else if(IC_REG) - IC_REG <= 1'b0; - - assign datai = DATA_REG[7:0]; - assign go = CTRL_REG[0]; - assign SSn = ~CTRL_REG[1]; - assign cpol = CFG_REG[0]; - assign cpha = CFG_REG[1]; - assign clkdiv = PRE_REG[7:0]; - - reg DONE; - always @(posedge PCLK, negedge PRESETn) - if(!PRESETn) - DONE <= 1'b0; - else if(done) - DONE <= 1'b1; - else if(go) - DONE <= 1'b0; - else if(IC_REG) - DONE <= 1'b0; - - spi_master #( .DATA_WIDTH(8), - .CLK_DIVIDER_WIDTH(8) - ) - SPI_CTRL ( - .clk(PCLK), - .resetb(PRESETn), - .CPOL(cpol), - .CPHA(cpha), - .clk_divider(clkdiv), - - .go(go), - .datai(datai), - .datao(datao), - .busy(busy), - .done(done), - - .dout(MSI), - .din(MSO), - //.csb(ss), - .sclk(SCK) - ); - - assign PRDATA[31:0] = (PADDR[7:3] == IM_REG_OFF) ? {31'd0, IM_REG} : - (PADDR[7:3] == IC_REG_OFF) ? {31'd0, IC_REG} : - (PADDR[7:3] == CTRL_REG_OFF) ? {30'd0, CTRL_REG} : - (PADDR[7:3] == CFG_REG_OFF) ? {30'd0, CFG_REG} : - (PADDR[7:3] == PRE_REG_OFF) ? {24'd0, PRE_REG} : - (PADDR[7:3] == STATUS_REG_OFF) ? {30'd0,busy, DONE}: - (PADDR[7:3] == DATA_REG_OFF) ? {24'd0, datao} : 32'hDEAD_BEEF; - - assign PREADY = 1'b1; - - assign IRQ = IM_REG[0] & DONE; - -endmodule \ No newline at end of file diff --git a/hdl/rtl/bus_wrappers/EF_SPI_AHBL.pp.v b/hdl/rtl/bus_wrappers/EF_SPI_AHBL.pp.v new file mode 100644 index 0000000..9b47f37 --- /dev/null +++ b/hdl/rtl/bus_wrappers/EF_SPI_AHBL.pp.v @@ -0,0 +1,251 @@ +/* + Copyright 2023 Mohamed Shalan + + Author: Mohamed Shalan (mshalan@efabless.com) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +/* THIS FILE IS GENERATED, DO NOT EDIT */ + +`timescale 1ns/1ps +`default_nettype none + + + +/* + Copyright 2020 AUCOHL + + Author: Mohamed Shalan (mshalan@aucegypt.edu) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module EF_SPI_AHBL #( + parameter + CLK_DIVIDER_WIDTH = 8 +) ( + input wire HCLK, + input wire HRESETn, + input wire HWRITE, + input wire [31:0] HWDATA, + input wire [31:0] HADDR, + input wire [1:0] HTRANS, + input wire HSEL, + input wire HREADY, + output wire HREADYOUT, + output wire [31:0] HRDATA, + output wire IRQ +, + input [1-1:0] dout, + output [1-1:0] din, + output [1-1:0] csb, + output [1-1:0] sclk +); + + localparam DATA_REG_OFFSET = 16'd0; + localparam CFG_REG_OFFSET = 16'd8; + localparam STATUS_REG_OFFSET = 16'd16; + localparam CTRL_REG_OFFSET = 16'd24; + localparam PR_REG_OFFSET = 16'd32; + localparam IM_REG_OFFSET = 16'd3840; + localparam MIS_REG_OFFSET = 16'd3844; + localparam RIS_REG_OFFSET = 16'd3848; + localparam IC_REG_OFFSET = 16'd3852; + + wire clk = HCLK; + wire resetb = HRESETn; + + + reg last_HSEL, last_HWRITE; reg [31:0] last_HADDR; reg [1:0] last_HTRANS; + always@ (posedge HCLK) begin + if(HREADY) begin + last_HSEL <= HSEL; + last_HADDR <= HADDR; + last_HWRITE <= HWRITE; + last_HTRANS <= HTRANS; + end + end + wire ahbl_valid = last_HSEL & last_HTRANS[1]; + wire ahbl_we = last_HWRITE & ahbl_valid; + wire ahbl_re = ~last_HWRITE & ahbl_valid; + + wire [1-1:0] CPOL; + wire [1-1:0] CPHA; + wire [CLK_DIVIDER_WIDTH-1:0] clk_divider; + wire [1-1:0] go; + wire [8-1:0] datai; + wire [8-1:0] datao; + wire [1-1:0] busy; + wire [1-1:0] done; + wire [1-1:0] ss; + + + // Register Definitions + reg [8-1:0] DATA_REG; + wire [8-1:0] DATA_WIRE; + assign DATA_WIRE = datao; + assign datai = DATA_REG; + always @(posedge HCLK or negedge HRESETn) if(~HRESETn) DATA_REG <= 0; + else if(ahbl_we & (last_HADDR[16-1:0]==DATA_REG_OFFSET)) + DATA_REG <= HWDATA[8-1:0]; + + reg [1:0] CFG_REG; + assign CPOL = CFG_REG[0 : 0]; + assign CPHA = CFG_REG[1 : 1]; + always @(posedge HCLK or negedge HRESETn) if(~HRESETn) CFG_REG <= 0; + else if(ahbl_we & (last_HADDR[16-1:0]==CFG_REG_OFFSET)) + CFG_REG <= HWDATA[2-1:0]; + + wire [2-1:0] STATUS_WIRE; + assign STATUS_WIRE[0 : 0] = done; + assign STATUS_WIRE[1 : 1] = busy; + + reg [1:0] CTRL_REG; + assign go = CTRL_REG[0 : 0]; + assign ss = CTRL_REG[1 : 1]; + always @(posedge HCLK or negedge HRESETn) if(~HRESETn) CTRL_REG <= 0; + else if(ahbl_we & (last_HADDR[16-1:0]==CTRL_REG_OFFSET)) + CTRL_REG <= HWDATA[2-1:0]; + else + CTRL_REG <= 2'h2 & CTRL_REG; + + reg [15:0] PR_REG; + assign clk_divider = PR_REG; + always @(posedge HCLK or negedge HRESETn) if(~HRESETn) PR_REG <= 'h2; + else if(ahbl_we & (last_HADDR[16-1:0]==PR_REG_OFFSET)) + PR_REG <= HWDATA[16-1:0]; + + reg [0:0] IM_REG; + reg [0:0] IC_REG; + reg [0:0] RIS_REG; + + wire[1-1:0] MIS_REG = RIS_REG & IM_REG; + always @(posedge HCLK or negedge HRESETn) if(~HRESETn) IM_REG <= 0; + else if(ahbl_we & (last_HADDR[16-1:0]==IM_REG_OFFSET)) + IM_REG <= HWDATA[1-1:0]; + always @(posedge HCLK or negedge HRESETn) if(~HRESETn) IC_REG <= 1'b0; + else if(ahbl_we & (last_HADDR[16-1:0]==IC_REG_OFFSET)) + IC_REG <= HWDATA[1-1:0]; + else IC_REG <= 1'd0; + + wire [0:0] Done = done; + + + integer _i_; + always @(posedge HCLK or negedge HRESETn) if(~HRESETn) RIS_REG <= 0; else begin + for(_i_ = 0; _i_ < 1; _i_ = _i_ + 1) begin + if(IC_REG[_i_]) RIS_REG[_i_] <= 1'b0; else if(Done[_i_ - 0] == 1'b1) RIS_REG[_i_] <= 1'b1; + end + end + + assign IRQ = |MIS_REG; + + EF_SPI #( + .CLK_DIVIDER_WIDTH(CLK_DIVIDER_WIDTH) + ) instance_to_wrap ( + .clk(clk), + .resetb(resetb), + .CPOL(CPOL), + .CPHA(CPHA), + .clk_divider(clk_divider), + .go(go), + .datai(datai), + .datao(datao), + .busy(busy), + .done(done), + .ss(ss), + .dout(dout), + .din(din), + .csb(csb), + .sclk(sclk) + ); + + assign HRDATA = + (last_HADDR[16-1:0] == DATA_REG_OFFSET) ? DATA_WIRE : + (last_HADDR[16-1:0] == CFG_REG_OFFSET) ? CFG_REG : + (last_HADDR[16-1:0] == STATUS_REG_OFFSET) ? STATUS_WIRE : + (last_HADDR[16-1:0] == CTRL_REG_OFFSET) ? CTRL_REG : + (last_HADDR[16-1:0] == PR_REG_OFFSET) ? PR_REG : + (last_HADDR[16-1:0] == IM_REG_OFFSET) ? IM_REG : + (last_HADDR[16-1:0] == MIS_REG_OFFSET) ? MIS_REG : + (last_HADDR[16-1:0] == RIS_REG_OFFSET) ? RIS_REG : + (last_HADDR[16-1:0] == IC_REG_OFFSET) ? IC_REG : + 32'hDEADBEEF; + + assign HREADYOUT = 1'b1; + +endmodule diff --git a/hdl/rtl/bus_wrappers/EF_SPI_AHBL.v b/hdl/rtl/bus_wrappers/EF_SPI_AHBL.v new file mode 100644 index 0000000..71ef2bf --- /dev/null +++ b/hdl/rtl/bus_wrappers/EF_SPI_AHBL.v @@ -0,0 +1,146 @@ +/* + Copyright 2023 Mohamed Shalan + + Author: Mohamed Shalan (mshalan@efabless.com) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +/* THIS FILE IS GENERATED, DO NOT EDIT */ + +`timescale 1ns/1ps +`default_nettype none + +`define AHBL_AW 16 + +`include "ahbl_wrapper.vh" + +module EF_SPI_AHBL #( + parameter + CLK_DIVIDER_WIDTH = 8 +) ( + `AHBL_SLAVE_PORTS, + input [1-1:0] dout, + output [1-1:0] din, + output [1-1:0] csb, + output [1-1:0] sclk +); + + localparam DATA_REG_OFFSET = `AHBL_AW'd0; + localparam CFG_REG_OFFSET = `AHBL_AW'd8; + localparam STATUS_REG_OFFSET = `AHBL_AW'd16; + localparam CTRL_REG_OFFSET = `AHBL_AW'd24; + localparam PR_REG_OFFSET = `AHBL_AW'd32; + localparam IM_REG_OFFSET = `AHBL_AW'd3840; + localparam MIS_REG_OFFSET = `AHBL_AW'd3844; + localparam RIS_REG_OFFSET = `AHBL_AW'd3848; + localparam IC_REG_OFFSET = `AHBL_AW'd3852; + + wire clk = HCLK; + wire resetb = HRESETn; + + + `AHBL_CTRL_SIGNALS + + wire [1-1:0] CPOL; + wire [1-1:0] CPHA; + wire [CLK_DIVIDER_WIDTH-1:0] clk_divider; + wire [1-1:0] go; + wire [8-1:0] datai; + wire [8-1:0] datao; + wire [1-1:0] busy; + wire [1-1:0] done; + wire [1-1:0] ss; + + + // Register Definitions + reg [8-1:0] DATA_REG; + wire [8-1:0] DATA_WIRE; + assign DATA_WIRE = datao; + assign datai = DATA_REG; + `AHBL_REG(DATA_REG, 0, 8) + + reg [1:0] CFG_REG; + assign CPOL = CFG_REG[0 : 0]; + assign CPHA = CFG_REG[1 : 1]; + `AHBL_REG(CFG_REG, 0, 2) + + wire [2-1:0] STATUS_WIRE; + assign STATUS_WIRE[0 : 0] = done; + assign STATUS_WIRE[1 : 1] = busy; + + reg [1:0] CTRL_REG; + assign go = CTRL_REG[0 : 0]; + assign ss = CTRL_REG[1 : 1]; + `AHBL_REG_AC(CTRL_REG, 0, 2, 2'h2) + + reg [15:0] PR_REG; + assign clk_divider = PR_REG; + `AHBL_REG(PR_REG, 'h2, 16) + + reg [0:0] IM_REG; + reg [0:0] IC_REG; + reg [0:0] RIS_REG; + + `AHBL_MIS_REG(1) + `AHBL_REG(IM_REG, 0, 1) + `AHBL_IC_REG(1) + + wire [0:0] Done = done; + + + integer _i_; + `AHBL_BLOCK(RIS_REG, 0) else begin + for(_i_ = 0; _i_ < 1; _i_ = _i_ + 1) begin + if(IC_REG[_i_]) RIS_REG[_i_] <= 1'b0; else if(Done[_i_ - 0] == 1'b1) RIS_REG[_i_] <= 1'b1; + end + end + + assign IRQ = |MIS_REG; + + EF_SPI #( + .CLK_DIVIDER_WIDTH(CLK_DIVIDER_WIDTH) + ) instance_to_wrap ( + .clk(clk), + .resetb(resetb), + .CPOL(CPOL), + .CPHA(CPHA), + .clk_divider(clk_divider), + .go(go), + .datai(datai), + .datao(datao), + .busy(busy), + .done(done), + .ss(ss), + .dout(dout), + .din(din), + .csb(csb), + .sclk(sclk) + ); + + assign HRDATA = + (last_HADDR[`AHBL_AW-1:0] == DATA_REG_OFFSET) ? DATA_WIRE : + (last_HADDR[`AHBL_AW-1:0] == CFG_REG_OFFSET) ? CFG_REG : + (last_HADDR[`AHBL_AW-1:0] == STATUS_REG_OFFSET) ? STATUS_WIRE : + (last_HADDR[`AHBL_AW-1:0] == CTRL_REG_OFFSET) ? CTRL_REG : + (last_HADDR[`AHBL_AW-1:0] == PR_REG_OFFSET) ? PR_REG : + (last_HADDR[`AHBL_AW-1:0] == IM_REG_OFFSET) ? IM_REG : + (last_HADDR[`AHBL_AW-1:0] == MIS_REG_OFFSET) ? MIS_REG : + (last_HADDR[`AHBL_AW-1:0] == RIS_REG_OFFSET) ? RIS_REG : + (last_HADDR[`AHBL_AW-1:0] == IC_REG_OFFSET) ? IC_REG : + 32'hDEADBEEF; + + assign HREADYOUT = 1'b1; + +endmodule diff --git a/hdl/rtl/bus_wrappers/EF_SPI_APB.pp.v b/hdl/rtl/bus_wrappers/EF_SPI_APB.pp.v new file mode 100644 index 0000000..67e9a9f --- /dev/null +++ b/hdl/rtl/bus_wrappers/EF_SPI_APB.pp.v @@ -0,0 +1,231 @@ +/* + Copyright 2023 Mohamed Shalan + + Author: Mohamed Shalan (mshalan@efabless.com) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +/* THIS FILE IS GENERATED, DO NOT EDIT */ + +`timescale 1ns/1ps +`default_nettype none + + + +/* + Copyright 2020 AUCOHL + + Author: Mohamed Shalan (mshalan@aucegypt.edu) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module EF_SPI_APB #( + parameter + CLK_DIVIDER_WIDTH = 8 +) ( + input wire PCLK, + input wire PRESETn, + input wire PWRITE, + input wire [31:0] PWDATA, + input wire [31:0] PADDR, + input wire PENABLE, + input wire PSEL, + output wire PREADY, + output wire [31:0] PRDATA, + output wire IRQ +, + input [1-1:0] dout, + output [1-1:0] din, + output [1-1:0] csb, + output [1-1:0] sclk +); + + localparam DATA_REG_OFFSET = 16'd0; + localparam CFG_REG_OFFSET = 16'd8; + localparam STATUS_REG_OFFSET = 16'd16; + localparam CTRL_REG_OFFSET = 16'd24; + localparam PR_REG_OFFSET = 16'd32; + localparam IM_REG_OFFSET = 16'd3840; + localparam MIS_REG_OFFSET = 16'd3844; + localparam RIS_REG_OFFSET = 16'd3848; + localparam IC_REG_OFFSET = 16'd3852; + + wire clk = PCLK; + wire resetb = PRESETn; + + + wire apb_valid = PSEL & PENABLE; + wire apb_we = PWRITE & apb_valid; + wire apb_re = ~PWRITE & apb_valid; + + wire [1-1:0] CPOL; + wire [1-1:0] CPHA; + wire [CLK_DIVIDER_WIDTH-1:0] clk_divider; + wire [1-1:0] go; + wire [8-1:0] datai; + wire [8-1:0] datao; + wire [1-1:0] busy; + wire [1-1:0] done; + wire [1-1:0] ss; + + + // Register Definitions + reg [8-1:0] DATA_REG; + wire [8-1:0] DATA_WIRE; + assign DATA_WIRE = datao; + assign datai = DATA_REG; + always @(posedge PCLK or negedge PRESETn) if(~PRESETn) DATA_REG <= 0; + else if(apb_we & (PADDR[16-1:0]==DATA_REG_OFFSET)) + DATA_REG <= PWDATA[8-1:0]; + + reg [1:0] CFG_REG; + assign CPOL = CFG_REG[0 : 0]; + assign CPHA = CFG_REG[1 : 1]; + always @(posedge PCLK or negedge PRESETn) if(~PRESETn) CFG_REG <= 0; + else if(apb_we & (PADDR[16-1:0]==CFG_REG_OFFSET)) + CFG_REG <= PWDATA[2-1:0]; + + wire [2-1:0] STATUS_WIRE; + assign STATUS_WIRE[0 : 0] = done; + assign STATUS_WIRE[1 : 1] = busy; + + reg [1:0] CTRL_REG; + assign go = CTRL_REG[0 : 0]; + assign ss = CTRL_REG[1 : 1]; + always @(posedge PCLK or negedge PRESETn) if(~PRESETn) CTRL_REG <= 0; + else if(apb_we & (PADDR[16-1:0]==CTRL_REG_OFFSET)) + CTRL_REG <= PWDATA[2-1:0]; + else + CTRL_REG <= 2'h2 & CTRL_REG; + + reg [15:0] PR_REG; + assign clk_divider = PR_REG; + always @(posedge PCLK or negedge PRESETn) if(~PRESETn) PR_REG <= 'h2; + else if(apb_we & (PADDR[16-1:0]==PR_REG_OFFSET)) + PR_REG <= PWDATA[16-1:0]; + + reg [0:0] IM_REG; + reg [0:0] IC_REG; + reg [0:0] RIS_REG; + + wire[1-1:0] MIS_REG = RIS_REG & IM_REG; + always @(posedge PCLK or negedge PRESETn) if(~PRESETn) IM_REG <= 0; + else if(apb_we & (PADDR[16-1:0]==IM_REG_OFFSET)) + IM_REG <= PWDATA[1-1:0]; + always @(posedge PCLK or negedge PRESETn) if(~PRESETn) IC_REG <= 1'b0; + else if(apb_we & (PADDR[16-1:0]==IC_REG_OFFSET)) + IC_REG <= PWDATA[1-1:0]; + else + IC_REG <= 1'd0; + + wire [0:0] Done = done; + + + integer _i_; + always @(posedge PCLK or negedge PRESETn) if(~PRESETn) RIS_REG <= 0; else begin + for(_i_ = 0; _i_ < 1; _i_ = _i_ + 1) begin + if(IC_REG[_i_]) RIS_REG[_i_] <= 1'b0; else if(Done[_i_ - 0] == 1'b1) RIS_REG[_i_] <= 1'b1; + end + end + + assign IRQ = |MIS_REG; + + EF_SPI #( + .CLK_DIVIDER_WIDTH(CLK_DIVIDER_WIDTH) + ) instance_to_wrap ( + .clk(clk), + .resetb(resetb), + .CPOL(CPOL), + .CPHA(CPHA), + .clk_divider(clk_divider), + .go(go), + .datai(datai), + .datao(datao), + .busy(busy), + .done(done), + .ss(ss), + .dout(dout), + .din(din), + .csb(csb), + .sclk(sclk) + ); + + assign PRDATA = + (PADDR[16-1:0] == DATA_REG_OFFSET) ? DATA_WIRE : + (PADDR[16-1:0] == CFG_REG_OFFSET) ? CFG_REG : + (PADDR[16-1:0] == STATUS_REG_OFFSET) ? STATUS_WIRE : + (PADDR[16-1:0] == CTRL_REG_OFFSET) ? CTRL_REG : + (PADDR[16-1:0] == PR_REG_OFFSET) ? PR_REG : + (PADDR[16-1:0] == IM_REG_OFFSET) ? IM_REG : + (PADDR[16-1:0] == MIS_REG_OFFSET) ? MIS_REG : + (PADDR[16-1:0] == RIS_REG_OFFSET) ? RIS_REG : + (PADDR[16-1:0] == IC_REG_OFFSET) ? IC_REG : + 32'hDEADBEEF; + + assign PREADY = 1'b1; + +endmodule diff --git a/hdl/rtl/bus_wrappers/EF_SPI_APB.v b/hdl/rtl/bus_wrappers/EF_SPI_APB.v new file mode 100644 index 0000000..e720bd6 --- /dev/null +++ b/hdl/rtl/bus_wrappers/EF_SPI_APB.v @@ -0,0 +1,146 @@ +/* + Copyright 2023 Mohamed Shalan + + Author: Mohamed Shalan (mshalan@efabless.com) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +/* THIS FILE IS GENERATED, DO NOT EDIT */ + +`timescale 1ns/1ps +`default_nettype none + +`define APB_AW 16 + +`include "apb_wrapper.vh" + +module EF_SPI_APB #( + parameter + CLK_DIVIDER_WIDTH = 8 +) ( + `APB_SLAVE_PORTS, + input [1-1:0] dout, + output [1-1:0] din, + output [1-1:0] csb, + output [1-1:0] sclk +); + + localparam DATA_REG_OFFSET = `APB_AW'd0; + localparam CFG_REG_OFFSET = `APB_AW'd8; + localparam STATUS_REG_OFFSET = `APB_AW'd16; + localparam CTRL_REG_OFFSET = `APB_AW'd24; + localparam PR_REG_OFFSET = `APB_AW'd32; + localparam IM_REG_OFFSET = `APB_AW'd3840; + localparam MIS_REG_OFFSET = `APB_AW'd3844; + localparam RIS_REG_OFFSET = `APB_AW'd3848; + localparam IC_REG_OFFSET = `APB_AW'd3852; + + wire clk = PCLK; + wire resetb = PRESETn; + + + `APB_CTRL_SIGNALS + + wire [1-1:0] CPOL; + wire [1-1:0] CPHA; + wire [CLK_DIVIDER_WIDTH-1:0] clk_divider; + wire [1-1:0] go; + wire [8-1:0] datai; + wire [8-1:0] datao; + wire [1-1:0] busy; + wire [1-1:0] done; + wire [1-1:0] ss; + + + // Register Definitions + reg [8-1:0] DATA_REG; + wire [8-1:0] DATA_WIRE; + assign DATA_WIRE = datao; + assign datai = DATA_REG; + `APB_REG(DATA_REG, 0, 8) + + reg [1:0] CFG_REG; + assign CPOL = CFG_REG[0 : 0]; + assign CPHA = CFG_REG[1 : 1]; + `APB_REG(CFG_REG, 0, 2) + + wire [2-1:0] STATUS_WIRE; + assign STATUS_WIRE[0 : 0] = done; + assign STATUS_WIRE[1 : 1] = busy; + + reg [1:0] CTRL_REG; + assign go = CTRL_REG[0 : 0]; + assign ss = CTRL_REG[1 : 1]; + `APB_REG_AC(CTRL_REG, 0, 2, 2'h2) + + reg [15:0] PR_REG; + assign clk_divider = PR_REG; + `APB_REG(PR_REG, 'h2, 16) + + reg [0:0] IM_REG; + reg [0:0] IC_REG; + reg [0:0] RIS_REG; + + `APB_MIS_REG(1) + `APB_REG(IM_REG, 0, 1) + `APB_IC_REG(1) + + wire [0:0] Done = done; + + + integer _i_; + `APB_BLOCK(RIS_REG, 0) else begin + for(_i_ = 0; _i_ < 1; _i_ = _i_ + 1) begin + if(IC_REG[_i_]) RIS_REG[_i_] <= 1'b0; else if(Done[_i_ - 0] == 1'b1) RIS_REG[_i_] <= 1'b1; + end + end + + assign IRQ = |MIS_REG; + + EF_SPI #( + .CLK_DIVIDER_WIDTH(CLK_DIVIDER_WIDTH) + ) instance_to_wrap ( + .clk(clk), + .resetb(resetb), + .CPOL(CPOL), + .CPHA(CPHA), + .clk_divider(clk_divider), + .go(go), + .datai(datai), + .datao(datao), + .busy(busy), + .done(done), + .ss(ss), + .dout(dout), + .din(din), + .csb(csb), + .sclk(sclk) + ); + + assign PRDATA = + (PADDR[`APB_AW-1:0] == DATA_REG_OFFSET) ? DATA_WIRE : + (PADDR[`APB_AW-1:0] == CFG_REG_OFFSET) ? CFG_REG : + (PADDR[`APB_AW-1:0] == STATUS_REG_OFFSET) ? STATUS_WIRE : + (PADDR[`APB_AW-1:0] == CTRL_REG_OFFSET) ? CTRL_REG : + (PADDR[`APB_AW-1:0] == PR_REG_OFFSET) ? PR_REG : + (PADDR[`APB_AW-1:0] == IM_REG_OFFSET) ? IM_REG : + (PADDR[`APB_AW-1:0] == MIS_REG_OFFSET) ? MIS_REG : + (PADDR[`APB_AW-1:0] == RIS_REG_OFFSET) ? RIS_REG : + (PADDR[`APB_AW-1:0] == IC_REG_OFFSET) ? IC_REG : + 32'hDEADBEEF; + + assign PREADY = 1'b1; + +endmodule diff --git a/hdl/rtl/bus_wrappers/EF_SPI_WB.pp.v b/hdl/rtl/bus_wrappers/EF_SPI_WB.pp.v new file mode 100644 index 0000000..12ad100 --- /dev/null +++ b/hdl/rtl/bus_wrappers/EF_SPI_WB.pp.v @@ -0,0 +1,219 @@ +/* + Copyright 2023 Mohamed Shalan + + Author: Mohamed Shalan (mshalan@efabless.com) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +/* THIS FILE IS GENERATED, DO NOT EDIT */ + +`timescale 1ns/1ps +`default_nettype none + + + +/* + Copyright 2020 AUCOHL + + Author: Mohamed Shalan (mshalan@aucegypt.edu) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module EF_SPI_WB #( + parameter + CLK_DIVIDER_WIDTH = 8 +) ( + input wire ext_clk, + input wire clk_i, + input wire rst_i, + input wire [31:0] adr_i, + input wire [31:0] dat_i, + output wire [31:0] dat_o, + input wire [3:0] sel_i, + input wire cyc_i, + input wire stb_i, + output reg ack_o, + input wire we_i, + output wire IRQ, + input [1-1:0] dout, + output [1-1:0] din, + output [1-1:0] csb, + output [1-1:0] sclk +); + + localparam DATA_REG_OFFSET = 16'd0; + localparam CFG_REG_OFFSET = 16'd8; + localparam STATUS_REG_OFFSET = 16'd16; + localparam CTRL_REG_OFFSET = 16'd24; + localparam PR_REG_OFFSET = 16'd32; + localparam IM_REG_OFFSET = 16'd3840; + localparam MIS_REG_OFFSET = 16'd3844; + localparam RIS_REG_OFFSET = 16'd3848; + localparam IC_REG_OFFSET = 16'd3852; + + wire clk = clk_i; + wire resetb = (~rst_i); + + + wire wb_valid = cyc_i & stb_i; + wire wb_we = we_i & wb_valid; + wire wb_re = ~we_i & wb_valid; + wire[3:0] wb_byte_sel = sel_i & {4{wb_we}}; + + wire [1-1:0] CPOL; + wire [1-1:0] CPHA; + wire [CLK_DIVIDER_WIDTH-1:0] clk_divider; + wire [1-1:0] go; + wire [8-1:0] datai; + wire [8-1:0] datao; + wire [1-1:0] busy; + wire [1-1:0] done; + wire [1-1:0] ss; + + + // Register Definitions + reg [8-1:0] DATA_REG; + wire [8-1:0] DATA_WIRE; + assign DATA_WIRE = datao; + assign datai = DATA_REG; + always @(posedge clk_i or posedge rst_i) if(rst_i) DATA_REG <= 0; else if(wb_we & (adr_i[16-1:0]==DATA_REG_OFFSET)) DATA_REG <= dat_i[8-1:0]; + + reg [1:0] CFG_REG; + assign CPOL = CFG_REG[0 : 0]; + assign CPHA = CFG_REG[1 : 1]; + always @(posedge clk_i or posedge rst_i) if(rst_i) CFG_REG <= 0; else if(wb_we & (adr_i[16-1:0]==CFG_REG_OFFSET)) CFG_REG <= dat_i[2-1:0]; + + wire [2-1:0] STATUS_WIRE; + assign STATUS_WIRE[0 : 0] = done; + assign STATUS_WIRE[1 : 1] = busy; + + reg [1:0] CTRL_REG; + assign go = CTRL_REG[0 : 0]; + assign ss = CTRL_REG[1 : 1]; + always @(posedge clk_i or posedge rst_i) if(rst_i) CTRL_REG <= 0; else if(wb_we & (adr_i[16-1:0]==CTRL_REG_OFFSET)) CTRL_REG <= dat_i[2-1:0]; else CTRL_REG <= 2'h2 & CTRL_REG; + + reg [15:0] PR_REG; + assign clk_divider = PR_REG; + always @(posedge clk_i or posedge rst_i) if(rst_i) PR_REG <= 'h2; else if(wb_we & (adr_i[16-1:0]==PR_REG_OFFSET)) PR_REG <= dat_i[16-1:0]; + + reg [0:0] IM_REG; + reg [0:0] IC_REG; + reg [0:0] RIS_REG; + + wire[1-1:0] MIS_REG = RIS_REG & IM_REG; + always @(posedge clk_i or posedge rst_i) if(rst_i) IM_REG <= 0; else if(wb_we & (adr_i[16-1:0]==IM_REG_OFFSET)) IM_REG <= dat_i[1-1:0]; + always @(posedge clk_i or posedge rst_i) if(rst_i) IC_REG <= 1'b0; + else if(wb_we & (adr_i[16-1:0]==IC_REG_OFFSET)) + IC_REG <= dat_i[1-1:0]; + else + IC_REG <= 1'd0; + + wire [0:0] Done = done; + + + integer _i_; + always @(posedge clk_i or posedge rst_i) if(rst_i) RIS_REG <= 0; else begin + for(_i_ = 0; _i_ < 1; _i_ = _i_ + 1) begin + if(IC_REG[_i_]) RIS_REG[_i_] <= 1'b0; else if(Done[_i_ - 0] == 1'b1) RIS_REG[_i_] <= 1'b1; + end + end + + assign IRQ = |MIS_REG; + + EF_SPI #( + .CLK_DIVIDER_WIDTH(CLK_DIVIDER_WIDTH) + ) instance_to_wrap ( + .clk(clk), + .resetb(resetb), + .CPOL(CPOL), + .CPHA(CPHA), + .clk_divider(clk_divider), + .go(go), + .datai(datai), + .datao(datao), + .busy(busy), + .done(done), + .ss(ss), + .dout(dout), + .din(din), + .csb(csb), + .sclk(sclk) + ); + + assign dat_o = + (adr_i[16-1:0] == DATA_REG_OFFSET) ? DATA_WIRE : + (adr_i[16-1:0] == CFG_REG_OFFSET) ? CFG_REG : + (adr_i[16-1:0] == STATUS_REG_OFFSET) ? STATUS_WIRE : + (adr_i[16-1:0] == CTRL_REG_OFFSET) ? CTRL_REG : + (adr_i[16-1:0] == PR_REG_OFFSET) ? PR_REG : + (adr_i[16-1:0] == IM_REG_OFFSET) ? IM_REG : + (adr_i[16-1:0] == MIS_REG_OFFSET) ? MIS_REG : + (adr_i[16-1:0] == RIS_REG_OFFSET) ? RIS_REG : + (adr_i[16-1:0] == IC_REG_OFFSET) ? IC_REG : + 32'hDEADBEEF; + + always @ (posedge clk_i or posedge rst_i) + if(rst_i) + ack_o <= 1'b0; + else if(wb_valid & ~ack_o) + ack_o <= 1'b1; + else + ack_o <= 1'b0; +endmodule diff --git a/hdl/rtl/bus_wrappers/EF_SPI_WB.v b/hdl/rtl/bus_wrappers/EF_SPI_WB.v new file mode 100644 index 0000000..023a4e1 --- /dev/null +++ b/hdl/rtl/bus_wrappers/EF_SPI_WB.v @@ -0,0 +1,151 @@ +/* + Copyright 2023 Mohamed Shalan + + Author: Mohamed Shalan (mshalan@efabless.com) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +/* THIS FILE IS GENERATED, DO NOT EDIT */ + +`timescale 1ns/1ps +`default_nettype none + +`define WB_AW 16 + +`include "wb_wrapper.vh" + +module EF_SPI_WB #( + parameter + CLK_DIVIDER_WIDTH = 8 +) ( + `WB_SLAVE_PORTS, + input [1-1:0] dout, + output [1-1:0] din, + output [1-1:0] csb, + output [1-1:0] sclk +); + + localparam DATA_REG_OFFSET = `WB_AW'd0; + localparam CFG_REG_OFFSET = `WB_AW'd8; + localparam STATUS_REG_OFFSET = `WB_AW'd16; + localparam CTRL_REG_OFFSET = `WB_AW'd24; + localparam PR_REG_OFFSET = `WB_AW'd32; + localparam IM_REG_OFFSET = `WB_AW'd3840; + localparam MIS_REG_OFFSET = `WB_AW'd3844; + localparam RIS_REG_OFFSET = `WB_AW'd3848; + localparam IC_REG_OFFSET = `WB_AW'd3852; + + wire clk = clk_i; + wire resetb = (~rst_i); + + + `WB_CTRL_SIGNALS + + wire [1-1:0] CPOL; + wire [1-1:0] CPHA; + wire [CLK_DIVIDER_WIDTH-1:0] clk_divider; + wire [1-1:0] go; + wire [8-1:0] datai; + wire [8-1:0] datao; + wire [1-1:0] busy; + wire [1-1:0] done; + wire [1-1:0] ss; + + + // Register Definitions + reg [8-1:0] DATA_REG; + wire [8-1:0] DATA_WIRE; + assign DATA_WIRE = datao; + assign datai = DATA_REG; + `WB_REG(DATA_REG, 0, 8) + + reg [1:0] CFG_REG; + assign CPOL = CFG_REG[0 : 0]; + assign CPHA = CFG_REG[1 : 1]; + `WB_REG(CFG_REG, 0, 2) + + wire [2-1:0] STATUS_WIRE; + assign STATUS_WIRE[0 : 0] = done; + assign STATUS_WIRE[1 : 1] = busy; + + reg [1:0] CTRL_REG; + assign go = CTRL_REG[0 : 0]; + assign ss = CTRL_REG[1 : 1]; + `WB_REG_AC(CTRL_REG, 0, 2, 2'h2) + + reg [15:0] PR_REG; + assign clk_divider = PR_REG; + `WB_REG(PR_REG, 'h2, 16) + + reg [0:0] IM_REG; + reg [0:0] IC_REG; + reg [0:0] RIS_REG; + + `WB_MIS_REG(1) + `WB_REG(IM_REG, 0, 1) + `WB_IC_REG(1) + + wire [0:0] Done = done; + + + integer _i_; + `WB_BLOCK(RIS_REG, 0) else begin + for(_i_ = 0; _i_ < 1; _i_ = _i_ + 1) begin + if(IC_REG[_i_]) RIS_REG[_i_] <= 1'b0; else if(Done[_i_ - 0] == 1'b1) RIS_REG[_i_] <= 1'b1; + end + end + + assign IRQ = |MIS_REG; + + EF_SPI #( + .CLK_DIVIDER_WIDTH(CLK_DIVIDER_WIDTH) + ) instance_to_wrap ( + .clk(clk), + .resetb(resetb), + .CPOL(CPOL), + .CPHA(CPHA), + .clk_divider(clk_divider), + .go(go), + .datai(datai), + .datao(datao), + .busy(busy), + .done(done), + .ss(ss), + .dout(dout), + .din(din), + .csb(csb), + .sclk(sclk) + ); + + assign dat_o = + (adr_i[`WB_AW-1:0] == DATA_REG_OFFSET) ? DATA_WIRE : + (adr_i[`WB_AW-1:0] == CFG_REG_OFFSET) ? CFG_REG : + (adr_i[`WB_AW-1:0] == STATUS_REG_OFFSET) ? STATUS_WIRE : + (adr_i[`WB_AW-1:0] == CTRL_REG_OFFSET) ? CTRL_REG : + (adr_i[`WB_AW-1:0] == PR_REG_OFFSET) ? PR_REG : + (adr_i[`WB_AW-1:0] == IM_REG_OFFSET) ? IM_REG : + (adr_i[`WB_AW-1:0] == MIS_REG_OFFSET) ? MIS_REG : + (adr_i[`WB_AW-1:0] == RIS_REG_OFFSET) ? RIS_REG : + (adr_i[`WB_AW-1:0] == IC_REG_OFFSET) ? IC_REG : + 32'hDEADBEEF; + + always @ (posedge clk_i or posedge rst_i) + if(rst_i) + ack_o <= 1'b0; + else if(wb_valid & ~ack_o) + ack_o <= 1'b1; + else + ack_o <= 1'b0; +endmodule diff --git a/hdl/rtl/spi_master.v b/hdl/rtl/spi_master.v index 7523dfa..6bd2889 100644 --- a/hdl/rtl/spi_master.v +++ b/hdl/rtl/spi_master.v @@ -47,7 +47,49 @@ `timescale 1ns/1ps `default_nettype wire +// wrapper for passing the spi master module + module EF_SPI #(parameter CLK_DIVIDER_WIDTH=8) + (input clk, + input resetb, + input CPOL, + input CPHA, + input [CLK_DIVIDER_WIDTH-1:0] clk_divider, + + input go, + input [7:0] datai, + output [7:0] datao, + output busy, + output done, + input dout, + output din, + output csb, + input ss, + output sclk + ); + spi_master#( + .DATA_WIDTH(8), + .CLK_DIVIDER_WIDTH(CLK_DIVIDER_WIDTH), + .NUM_PORTS(1), + .SAMPLE_PHASE(0) + ) spi_master( + .clk(clk), + .resetb(resetb), + .CPOL(CPOL), + .CPHA(CPHA), + .clk_divider(clk_divider), + .go(go), + .datai(datai), + .datao(datao), + .busy(busy), + .done(done), + .dout(dout), + .din(din), + // .csb(csb), + .sclk(sclk) + ); + assign csb = ~ss; +endmodule module spi_master #(parameter DATA_WIDTH=16, diff --git a/verify/uvm-python/Makefile b/verify/uvm-python/Makefile index 5bc3fa7..101f9f0 100644 --- a/verify/uvm-python/Makefile +++ b/verify/uvm-python/Makefile @@ -1,14 +1,29 @@ PLUSARGS += "+UVM_VERBOSITY=UVM_MEDUIM" TOPLEVEL := top MODULE ?= top_module -AHB_FILES ?= -APB_FILES ?= $(PWD)/../../hdl/rtl/bus_wrappers/APB_SPI.v -WB_FILES ?= +AHB_FILES ?= $(PWD)/../../hdl/rtl/bus_wrappers/EF_SPI_AHBL.pp.v +APB_FILES ?= $(PWD)/../../hdl/rtl/bus_wrappers/EF_SPI_APB.pp.v +WB_FILES ?=$(PWD)/../../hdl/rtl/bus_wrappers/EF_SPI_WB.pp.v HDL_FILES ?= $(PWD)/../../hdl/rtl/spi_master.v VERILOG_SOURCES ?= $(PWD)/top.v $(AHB_FILES) $(APB_FILES) $(WB_FILES) $(HDL_FILES) -RTL_MACROS += "" # Add macros needed -BUS_TYPE = APB # only APB is supported -RTL_MACROS += -DBUS_TYPE_APB +RTL_MACROS += "" +BUS_TYPE ?= APB +ifeq ($(BUS_TYPE),APB) + RTL_MACROS += -DBUS_TYPE_APB + DESIGN_NAME = EF_SPI_APB + export CLK_MAKEFILE = PCLK + export RST_MAKEFILE = PRESETn +else ifeq ($(BUS_TYPE),AHB) + RTL_MACROS += -DBUS_TYPE_AHB + DESIGN_NAME = EF_SPI_AHBL + export CLK_MAKEFILE = HCLK + export RST_MAKEFILE = HRESETn +else ifeq ($(BUS_TYPE),WISHBONE) + RTL_MACROS += -DBUS_TYPE_WISHBONE + DESIGN_NAME = EF_SPI_WB + export CLK_MAKEFILE = clk_i + export RST_MAKEFILE = rst_i +endif # RTL_MACROS ?= "-DSKIP_WAVE_DUMP" YAML_FILE = $(PWD)/../../EF_SPI.yaml # TODO: update yaml file path @@ -25,9 +40,6 @@ SIM_PATH := $(PWD)/sim/$(SIM_TAG) # Check and clone EF_UVM repository at the beginning of the Makefile execution ## netlist Gen -DESIGN_NAME = EF_SPI_APB -export CLK_MAKEFILE = PCLK -export RST_MAKEFILE = PRESETn GL_MACROS += -DGL -DFUNCTIONAL $(RTL_MACROS) -DUNIT_DELAY=\#1 PRE_SYS_FILES = $(AHB_FILES) $(APB_FILES) $(WB_FILES) $(HDL_FILES) PDK_DIR = $(HOME)/.volare/volare/sky130/versions/bdc9412b3e468c102d01b7cf6337be06ec6e9c9a/sky130A/ diff --git a/verify/uvm-python/spi_ref_model/spi_ref_model.py b/verify/uvm-python/spi_ref_model/spi_ref_model.py index 5040327..b1cd79d 100644 --- a/verify/uvm-python/spi_ref_model/spi_ref_model.py +++ b/verify/uvm-python/spi_ref_model/spi_ref_model.py @@ -85,7 +85,8 @@ def write_bus(self, tr): if tr.addr == self.regs.reg_name_to_address["STATUS"]: pass # don't change the data as the status register isnt calculated in the ref model for now else: - td.data = data + pass + # td.data = data self.bus_bus_export.write(td) # this is output to the scoreboard self.update_interrupt_regs() diff --git a/verify/uvm-python/spi_seq_lib/spi_MOSI_MISO_seq.py b/verify/uvm-python/spi_seq_lib/spi_MOSI_MISO_seq.py index 6b4f9df..94bee04 100644 --- a/verify/uvm-python/spi_seq_lib/spi_MOSI_MISO_seq.py +++ b/verify/uvm-python/spi_seq_lib/spi_MOSI_MISO_seq.py @@ -5,7 +5,13 @@ from EF_UVM.bus_env.bus_seq_lib.bus_seq_base import bus_seq_base from cocotb.triggers import Timer from uvm.macros.uvm_sequence_defines import uvm_do_with, uvm_do -from uvm.base.uvm_object_globals import UVM_ALL_ON, UVM_NOPACK, UVM_HIGH, UVM_MEDIUM +from uvm.base.uvm_object_globals import ( + UVM_ALL_ON, + UVM_NOPACK, + UVM_HIGH, + UVM_MEDIUM, + UVM_LOW, +) from uvm.macros import uvm_component_utils, uvm_fatal, uvm_info import random @@ -46,6 +52,8 @@ async def body(self): await self.send_req( is_write=True, reg="CTRL", data_condition=lambda data: data == 0b11 ) # go + await self.send_nop() + await self.send_nop() while True: await self.send_req(is_write=False, reg="STATUS") # pop non needed response in the fifo @@ -53,7 +61,7 @@ async def body(self): rsp = [] await self.get_response(rsp) rsp = rsp[0] - uvm_info(self.get_full_name(), f"RSP: {rsp}", UVM_MEDIUM) + uvm_info(self.get_full_name(), f"RSP: {rsp}", UVM_LOW) if rsp.addr == self.regs.reg_name_to_address["STATUS"]: break if rsp.data & 0b10 == 0b0: # not busy diff --git a/verify/uvm-python/spi_seq_lib/spi_send_MISO_seq.py b/verify/uvm-python/spi_seq_lib/spi_send_MISO_seq.py index 2bb9e82..ae1563a 100644 --- a/verify/uvm-python/spi_seq_lib/spi_send_MISO_seq.py +++ b/verify/uvm-python/spi_seq_lib/spi_send_MISO_seq.py @@ -36,7 +36,6 @@ async def body(self): is_write=True, reg="CTRL", data_condition=lambda data: data == 0b11 ) # go for _ in range(self.num_data): - # wait until not busy while True: await self.send_req(is_write=False, reg="STATUS") @@ -45,16 +44,19 @@ async def body(self): rsp = [] await self.get_response(rsp) rsp = rsp[0] - uvm_info(self.get_full_name(), f"RSP: {rsp}", UVM_MEDIUM) + # uvm_info(self.get_full_name(), f"RSP: {rsp}", UVM_MEDIUM) if rsp.addr == self.regs.reg_name_to_address["STATUS"]: break if rsp.data & 0b10 == 0b0: # not busy break + uvm_info(self.get_full_name(), f"RSP: {rsp}", UVM_MEDIUM) + if random.random() > 0.1: # 90% probability of reading await self.send_req(is_write=False, reg="DATA") await self.send_req( is_write=True, reg="CTRL", data_condition=lambda data: data == 0b11 ) # go + await self.send_req( is_write=True, reg="CTRL", data_condition=lambda data: data == 0b00 ) # csb disable diff --git a/verify/uvm-python/top.v b/verify/uvm-python/top.v index 65b33ea..289a77b 100644 --- a/verify/uvm-python/top.v +++ b/verify/uvm-python/top.v @@ -5,20 +5,44 @@ module top(); wire RESETn = 1; wire irq; // TODO: Add any IP signals here - wire [31:0] PADDR; - wire PWRITE; - wire PSEL; - wire PENABLE; - wire [31:0] PWDATA; - wire [31:0] PRDATA; - wire PREADY; + wire MSI; wire MSO; wire SSn; wire SCK; // TODO: initialize the ABP wrapper here // for example - EF_SPI_APB dut(.PCLK(CLK), .PRESETn(RESETn), .PADDR(PADDR), .PWRITE(PWRITE), .PSEL(PSEL), .PENABLE(PENABLE), .PWDATA(PWDATA), .PRDATA(PRDATA), .PREADY(PREADY), .MSI(MSI), .MSO(MSO), .SSn(SSn), .SCK(SCK), .IRQ(irq)); + `ifdef BUS_TYPE_APB + wire [31:0] PADDR; + wire PWRITE; + wire PSEL; + wire PENABLE; + wire [31:0] PWDATA; + wire [31:0] PRDATA; + wire PREADY; + EF_SPI_APB dut(.PCLK(CLK), .PRESETn(RESETn), .PADDR(PADDR), .PWRITE(PWRITE), .PSEL(PSEL), .PENABLE(PENABLE), .PWDATA(PWDATA), .PRDATA(PRDATA), .PREADY(PREADY), .din(MSO), .dout(MSI), .csb(SSn), .sclk(SCK), .IRQ(irq)); + `endif // BUS_TYPE_APB + `ifdef BUS_TYPE_AHB + wire [31:0] HADDR; + wire HWRITE; + wire HSEL = 0; + wire HREADYOUT; + wire [1:0] HTRANS=0; + wire [31:0] HWDATA; + wire [31:0] HRDATA; + wire HREADY; + EF_SPI_AHBL dut(.HCLK(CLK), .HRESETn(RESETn), .HADDR(HADDR), .HWRITE(HWRITE), .HSEL(HSEL), .HTRANS(HTRANS), .HWDATA(HWDATA), .HRDATA(HRDATA), .HREADY(HREADY),.HREADYOUT(HREADYOUT), .din(MSO), .dout(MSI), .csb(SSn), .sclk(SCK), .IRQ(irq)); + `endif // BUS_TYPE_AHB + `ifdef BUS_TYPE_WISHBONE + wire [31:0] adr_i; + wire [31:0] dat_i; + wire [31:0] dat_o; + wire [3:0] sel_i; + wire cyc_i; + wire stb_i; + reg ack_o; + EF_SPI_WB dut(.clk_i(CLK), .rst_i(~RESETn), .adr_i(adr_i), .dat_i(dat_i), .dat_o(dat_o), .sel_i(sel_i), .cyc_i(cyc_i), .stb_i(stb_i), .ack_o(ack_o),.we_i(we_i), .din(MSO), .dout(MSI), .csb(SSn), .sclk(SCK), .IRQ(irq)); + `endif // BUS_TYPE_WISHBONE // monitor inside signals `ifndef SKIP_WAVE_DUMP initial begin