blob: 308d66b2694835ebea3960f699384258cb7401cb [file] [log] [blame]
// SPDX-FileCopyrightText: 2020 Efabless Corporation
//
// 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.
// SPDX-License-Identifier: Apache-2.0
`default_nettype none
/*
*-------------------------------------------------------------
*
* user_proj_example
*
* This is an example of a (trivially simple) user project,
* showing how the user project can connect to the logic
* analyzer, the wishbone bus, and the I/O pads.
*
* This project generates an integer count, which is output
* on the user area GPIO pads (digital output only). The
* wishbone connection allows the project to be controlled
* (start and stop) from the management SoC program.
*
* See the testbenches in directory "mprj_counter" for the
* example programs that drive this user project. The three
* testbenches are "io_ports", "la_test1", and "la_test2".
*
*-------------------------------------------------------------
*/
`define MAX_SOC 8
`define BUS_WIDTH 16
module user_proj_example #(
parameter BITS = 32
)(
`ifdef USE_POWER_PINS
inout vccd1, // User area 1 1.8V supply
inout vssd1, // User area 1 digital ground
`endif
// Wishbone Slave ports (WB MI A)
input wb_clk_i,
input wb_rst_i,
input wbs_stb_i,
input wbs_cyc_i,
input wbs_we_i,
input [3:0] wbs_sel_i,
input [31:0] wbs_dat_i,
input [31:0] wbs_adr_i,
output wbs_ack_o,
output [31:0] wbs_dat_o,
// Logic Analyzer Signals
input [127:0] la_data_in,
output [127:0] la_data_out,
input [127:0] la_oenb,
// IOs
input [`MPRJ_IO_PADS-1:0] io_in,
output [`MPRJ_IO_PADS-1:0] io_out,
output [`MPRJ_IO_PADS-1:0] io_oeb,
// IRQ
output [2:0] irq
);
localparam STATUS_ADDR = 'd0;
localparam PRE_ADDR = 'd1;
reg [2*`BUS_WIDTH-1:0] status;
reg [2*`BUS_WIDTH-1:0] rdata;
reg [2*`BUS_WIDTH-1:0] prescaler;
reg wbs_done;
wire wb_valid;
wire [3:0] wstrb;
wire [`MAX_SOC-1:0] cmp;
wire mclear;
wire mclk;
wire ce_pcm;
wire ce_pdm;
wire addr_valid;
reg [`MAX_SOC-1:0] valid_i;
wire strb_i;
wire [3:0] adr_i;
wire [`BUS_WIDTH-1:0] dat_i;
wire [10:0] addr;
wire [`BUS_WIDTH-1:0] dat_o[`MAX_SOC];
wire ack_o[`MAX_SOC];
reg [`BUS_WIDTH-1:0] wbs_dat;
reg wbs_ack;
assign dat_i = {wbs_dat_i[31], wbs_dat_i[14:0]};
assign addr = ((wbs_adr_i[11:0] >> 2) - 11'd2);
assign adr_i = addr[3:0];
assign strb_i = wstrb[0];
assign wb_valid = wbs_cyc_i && wbs_stb_i;
assign wstrb = wbs_sel_i & {4{wbs_we_i}};
assign addr_valid = (wbs_adr_i[31:28] == 3) ? 1 : 0;
assign irq[0] = ((|status) | (|prescaler[25:24]) );
/*clear send from CARAVEL*/
assign mclear = la_data_in[0];
/* assign 4.5 MHz clock on GPIO0*/
assign io_out[0] = mclk;
assign io_oeb[0] = 1'b0;
assign io_oeb[1] = 1'b1;
assign io_oeb[2] = 1'b1;
assign io_oeb[3] = 1'b1;
assign io_oeb[4] = 1'b1;
assign io_oeb[5] = 1'b1;
assign io_oeb[6] = 1'b1;
assign io_oeb[7] = 1'b1;
assign io_oeb[8] = 1'b1;
always@(addr or wb_valid or addr_valid) begin
if (wb_valid && addr_valid) begin
case(addr[10:4])
'd0 : begin valid_i[0] = 1'b1; end
'd1 : begin valid_i[1] = 1'b1; end
'd2 : begin valid_i[2] = 1'b1; end
'd3 : begin valid_i[3] = 1'b1; end
'd4 : begin valid_i[3] = 1'b1; end
'd5 : begin valid_i[4] = 1'b1; end
'd6 : begin valid_i[5] = 1'b1; end
'd7 : begin valid_i[6] = 1'b1; end
'd8 : begin valid_i[7] = 1'b1; end
default: begin valid_i = 0 ; end
endcase
end
else
valid_i <= 0;
end
always@(valid_i or dat_o[0] or ack_o[0] or dat_o[1] or dat_o[2] or dat_o[3] or ack_o[1] or ack_o[2] or ack_o[3]
or dat_o[4] or ack_o[4] or dat_o[5] or dat_o[6] or dat_o[7] or dat_o[8] or ack_o[5] or ack_o[6] or ack_o[7] )
begin
case(valid_i)
'h1 : begin
wbs_dat = dat_o[0];
wbs_ack = ack_o[0];
end
'h2 : begin
wbs_dat = dat_o[1];
wbs_ack = ack_o[1];
end
'h4 : begin
wbs_dat = dat_o[2];
wbs_ack = ack_o[2];
end
'h8 : begin
wbs_dat = dat_o[3];
wbs_ack = ack_o[3];
end
'h10 : begin
wbs_dat = dat_o[4];
wbs_ack = ack_o[4];
end
'h20 : begin
wbs_dat = dat_o[5];
wbs_ack = ack_o[5];
end
'h40 : begin
wbs_dat = dat_o[6];
wbs_ack = ack_o[6];
end
'h80 : begin
wbs_dat = dat_o[7];
wbs_ack = ack_o[7];
end
default: begin
wbs_dat = 0;
wbs_ack = 0;
end
endcase
end
assign wbs_dat_o = (valid_i != 0) ? {{16{wbs_dat[15]}},wbs_dat} : rdata;
assign wbs_ack_o = (valid_i != 0) ? wbs_ack : wbs_done;
always@(posedge wb_clk_i) begin
if(wb_rst_i) begin
wbs_done <= 0;
status <= 0;
prescaler <= 49;
rdata <= 0;
end
else begin
wbs_done <= 0;
if (wb_valid && addr_valid) begin
case(wbs_adr_i[7:2])
STATUS_ADDR:
begin
rdata <= status;
end
PRE_ADDR:
begin
rdata <= prescaler;
if(strb_i)
prescaler[9:0] <= wbs_dat_i[9:0];
end
default: ;
endcase
wbs_done <= 1;
end
else begin
end
end
end
/* write status register */
always@(posedge wb_clk_i) begin
if(wb_rst_i) begin
status <= 0;
end
else
status <= cmp;
end
/* ---------------------- STRUCTURAL DESIGN BEGINS ----------------------- */
micclk mic(
.clk(wb_clk_i),
.rst(wb_rst_i),
.mclk(mclk),
.ce_pdm(ce_pdm)
);
pcm_clk pcmclk(
.clk(wb_clk_i),
.rst(wb_rst_i),
.prescaler(prescaler[9:0]),
.ce_pcm(ce_pcm)
);
SonarOnChip soc1(
.wb_clk_i(wb_clk_i),
.wb_rst_i(wb_rst_i),
.wb_valid_i(valid_i[0]),
.wbs_adr_i(adr_i),
.wbs_dat_i(dat_i),
.wbs_strb_i(strb_i),
.wbs_ack_o(ack_o[0]),
.wbs_dat_o(dat_o[0]),
.ce_pdm(ce_pdm),
.ce_pcm(ce_pcm),
.pdm_data_i(io_in[1]),
.mclear(mclear),
.cmp(cmp[0])
);
SonarOnChip soc2(
.wb_clk_i(wb_clk_i),
.wb_rst_i(wb_rst_i),
.wb_valid_i(valid_i[1]),
.wbs_adr_i(adr_i),
.wbs_dat_i(dat_i),
.wbs_strb_i(strb_i),
.wbs_ack_o(ack_o[1]),
.wbs_dat_o(dat_o[1]),
.ce_pdm(ce_pdm),
.ce_pcm(ce_pcm),
.pdm_data_i(io_in[2]),
.mclear(mclear),
.cmp(cmp[1])
);
SonarOnChip soc3(
.wb_clk_i(wb_clk_i),
.wb_rst_i(wb_rst_i),
.wb_valid_i(valid_i[2]),
.wbs_adr_i(adr_i),
.wbs_dat_i(dat_i),
.wbs_strb_i(strb_i),
.wbs_ack_o(ack_o[2]),
.wbs_dat_o(dat_o[2]),
.ce_pdm(ce_pdm),
.ce_pcm(ce_pcm),
.pdm_data_i(io_in[3]),
.mclear(mclear),
.cmp(cmp[2])
);
SonarOnChip soc4(
.wb_clk_i(wb_clk_i),
.wb_rst_i(wb_rst_i),
.wb_valid_i(valid_i[3]),
.wbs_adr_i(adr_i),
.wbs_dat_i(dat_i),
.wbs_strb_i(strb_i),
.wbs_ack_o(ack_o[3]),
.wbs_dat_o(dat_o[3]),
.ce_pdm(ce_pdm),
.ce_pcm(ce_pcm),
.pdm_data_i(io_in[4]),
.mclear(mclear),
.cmp(cmp[3])
);
SonarOnChip soc5(
.wb_clk_i(wb_clk_i),
.wb_rst_i(wb_rst_i),
.wb_valid_i(valid_i[4]),
.wbs_adr_i(adr_i),
.wbs_dat_i(dat_i),
.wbs_strb_i(strb_i),
.wbs_ack_o(ack_o[4]),
.wbs_dat_o(dat_o[4]),
.ce_pdm(ce_pdm),
.ce_pcm(ce_pcm),
.pdm_data_i(io_in[5]),
.mclear(mclear),
.cmp(cmp[4])
);
SonarOnChip soc6(
.wb_clk_i(wb_clk_i),
.wb_rst_i(wb_rst_i),
.wb_valid_i(valid_i[5]),
.wbs_adr_i(adr_i),
.wbs_dat_i(dat_i),
.wbs_strb_i(strb_i),
.wbs_ack_o(ack_o[5]),
.wbs_dat_o(dat_o[5]),
.ce_pdm(ce_pdm),
.ce_pcm(ce_pcm),
.pdm_data_i(io_in[6]),
.mclear(mclear),
.cmp(cmp[5])
);
SonarOnChip soc7(
.wb_clk_i(wb_clk_i),
.wb_rst_i(wb_rst_i),
.wb_valid_i(valid_i[6]),
.wbs_adr_i(adr_i),
.wbs_dat_i(dat_i),
.wbs_strb_i(strb_i),
.wbs_ack_o(ack_o[6]),
.wbs_dat_o(dat_o[6]),
.ce_pdm(ce_pdm),
.ce_pcm(ce_pcm),
.pdm_data_i(io_in[7]),
.mclear(mclear),
.cmp(cmp[6])
);
SonarOnChip soc8(
.wb_clk_i(wb_clk_i),
.wb_rst_i(wb_rst_i),
.wb_valid_i(valid_i[7]),
.wbs_adr_i(adr_i),
.wbs_dat_i(dat_i),
.wbs_strb_i(strb_i),
.wbs_ack_o(ack_o[7]),
.wbs_dat_o(dat_o[7]),
.ce_pdm(ce_pdm),
.ce_pcm(ce_pcm),
.pdm_data_i(io_in[8]),
.mclear(mclear),
.cmp(cmp[7])
);
endmodule
/* ---------------------- CLOCK DIVIDERS ------------------------- */
/*
with 8 MHz cristal
PLL feedback divider = 18
18 *8 = 144
main clock
PLL 1 divider = 6
144/6 = 24
second clock
144/3 = 48
*/
module micclk(clk, rst, mclk, ce_pdm);
input clk, rst;
output mclk;
output ce_pdm;
reg tmp1, tmp2;
assign mclk = ~(tmp1 | tmp2);
reg [3:0] cnt1, cnt2;
/* delay one cycle vs. MIC Clk*/
assign ce_pdm = cnt1==4'b001 ? 1 : 0;
always @(posedge clk)
begin
if (rst) begin
cnt1 <= 0;
tmp1 <= 0;
end
else
cnt1 <= cnt1 + 1;
if (cnt1 >= 2)
tmp1 <= 1'b1;
if (cnt1 == 4) begin
cnt1 <= 0;
tmp1 <= 0;
end
end
always @(negedge clk)
begin
if (rst) begin
cnt2 <= 0;
tmp2 <= 0;
end
else
cnt2 <= cnt2 + 1;
if (cnt2 >= 2)
tmp2 <= 1'b1;
if (cnt2 == 4) begin
cnt2 <= 0;
tmp2 <= 0;
end
end
endmodule
module pcm_clk(clk, rst, prescaler, ce_pcm);
input clk, rst;
input [9:0] prescaler;
output reg ce_pcm;
reg [9:0] count;
always@(posedge clk) begin
if(rst)begin
ce_pcm <=0;
count <= 0;
end
else if(count == prescaler) begin
ce_pcm <= 1;
count <=0;
end
else begin
count <= count + 1;
ce_pcm <= 0;
end
end
endmodule
`default_nettype wire