blob: 183ce55580f4c44a732a8bfe7d3860320573d8a2 [file] [log] [blame]
/*
Sonar on Chip top level module based on user project example
Files:
defines.v - macroodefinitions (come vith Caravel)
*/
`include "defines.v"
`define BUS_WIDTH 16
module SonarOnChip
(
`ifdef USE_POWER_PINS
inout wire vdda1, // User area 1 3.3V supply
inout wire vdda2, // User area 2 3.3V supply
inout wire vssa1, // User area 1 analog ground
inout wire vssa2, // User area 2 analog ground
inout wire vccd1, // User area 1 1.8V supply
inout wire vccd2, // User area 2 1.8v supply
inout wire vssd1, // User area 1 digital ground
inout wire vssd2, // User area 2 digital ground
`endif
// Wishbone Slave ports (WB MI A)
input wire wb_clk_i,
input wire wb_rst_i,
input wire wb_valid_i,
input wire [3:0] wbs_adr_i,
input wire [`BUS_WIDTH-1:0] wbs_dat_i,
input wire wbs_strb_i,
output wbs_ack_o,
output [`BUS_WIDTH-1:0] wbs_dat_o,
/* Design specific ports*/
/* 4.8 MHz clock input */
input wire ce_pdm,
/* PCM pace signal */
input wire ce_pcm,
/* External microphone PDM data */
input wire pdm_data_i,
/* Master clear */
input wire mclear,
/* compare otupt signal*/
output wire cmp
);
/*----------------------------- Register map begins ---------------------*/
localparam CONTROL_ADDR = 'd0;
localparam A0_ADDR = 'd1;
localparam A1_ADDR = 'd2;
localparam A2_ADDR = 'd3;
localparam B1_ADDR = 'd4;
localparam B2_ADDR = 'd5;
localparam AMP_ADDR = 'd6;
localparam THRESHOLD_ADDR = 'd7;
localparam TIMER_ADDR = 'd8;
localparam PCM_ADDR = 'd9;
localparam PCM_LOAD_ADDR = 'd10;
localparam FB0_ADDR = 'd11;
localparam FB1_ADDR = 'd12;
/*----------------------------- Register Map ends ---------------------*/
/* clock and reset signals*/
wire clk;
wire rst;
wire we_pcm;
/* Compare module wires*/
wire [`BUS_WIDTH-1:0] maf_o;
wire compare_out;
/* PCM inputs from GPIO, will come from PDM */
wire [`BUS_WIDTH-1:0] pcm_reg_i;
/* ABS output signal*/
wire [`BUS_WIDTH-1:0] pcm_abs;
/* Multiplier output */
wire [`BUS_WIDTH-1:0] mul_o;
/** Wishbone Slave Interface **/
reg wbs_done;
wire wb_valid;
wire [3:0] wstrb;
reg [7:0] control;
reg [7:0] amp;
reg signed [`BUS_WIDTH-1:0] pcm;
reg signed [`BUS_WIDTH-1:0] pcm_load;
reg [`BUS_WIDTH-1:0] timer;
//---- IIR COEFF ---- //
reg signed [`BUS_WIDTH-1:0] a0;
reg signed [`BUS_WIDTH-1:0] a1;
reg signed [`BUS_WIDTH-1:0] a2;
reg signed [`BUS_WIDTH-1:0] b1;
reg signed [`BUS_WIDTH-1:0] b2;
//---- FIR COEFF ---- //
reg signed [`BUS_WIDTH-1:0] fb0;
reg signed [`BUS_WIDTH-1:0] fb1;
reg [`BUS_WIDTH-1:0] threshold;
wire timer_we;
wire srlatchQ;
wire srlatchQbar;
reg [`BUS_WIDTH-1:0] rdata;
wire [11:0] cic_out;
wire [`BUS_WIDTH-1:0] fir_out;
wire [`BUS_WIDTH-1:0] fir_in;
wire [`BUS_WIDTH-1:0] mul_i;
wire [`BUS_WIDTH-1:0] iir_data;
assign wbs_ack_o = wbs_done;
assign wbs_dat_o = rdata;
assign clk = wb_clk_i;
assign rst = wb_rst_i;
/* register mapping and slave interface */
always@(posedge clk) begin
if(rst) begin
wbs_done <= 0;
a0 <= 16'h0000;
a1 <= 16'h0000;
a2 <= 16'h0000;
b1 <= 16'h0000;
b2 <= 16'h0000;
fb0 <= 0;
fb1 <= 0;
fb0 <= 16'h0FFF;
fb1 <= 16'h7FFF;
amp <= 8'h00;
threshold <= 0;
control <= 0;
threshold <= 16'h0400;
control <= 16'h04;
pcm_load <= 16'h0000;
rdata <= 16'h0000;
end
else begin
wbs_done <= 0;
if (wb_valid_i) begin
case(wbs_adr_i)
CONTROL_ADDR:
begin
rdata <= control;
if(wbs_strb_i)
control <= wbs_dat_i;
end
A0_ADDR:
begin
rdata <= a0;
if(wbs_strb_i)
a0 <= wbs_dat_i;
end
A1_ADDR:
begin
rdata <= a1;
if(wbs_strb_i)
a1 <= wbs_dat_i;
end
A2_ADDR:
begin
rdata <= a2;
if(wbs_strb_i)
a2 <= wbs_dat_i;
end
B1_ADDR:
begin
rdata <= b1;
if(wbs_strb_i)
b1 <= wbs_dat_i;
end
B2_ADDR:
begin
rdata <= b2;
if(wbs_strb_i)
b2 <= wbs_dat_i;
end
FB0_ADDR:
begin
rdata <= fb0;
if(wbs_strb_i)
fb0 <= wbs_dat_i;
end
FB1_ADDR:
begin
rdata <= fb1;
if(wbs_strb_i)
fb1 <= wbs_dat_i;
end
PCM_ADDR:
begin
rdata <= pcm;
end
TIMER_ADDR:
begin
rdata <= timer;
end
PCM_LOAD_ADDR:
begin
rdata <= pcm_load;
if(wbs_strb_i)
pcm_load <= wbs_dat_i;
end
AMP_ADDR:
begin
rdata <= amp;
if(wbs_strb_i)
amp <= wbs_dat_i;
end
THRESHOLD_ADDR:
begin
rdata <= threshold;
if(wbs_strb_i)
threshold <= wbs_dat_i;
end
default: rdata <= 0;
endcase
wbs_done <= 1;
end
end
end
/* timer register block */
/*-----------------------------------------------------------------------------*/
always @(posedge clk)
begin
if (rst)
timer <= 0;
else if (mclear)
timer <= 0;
else if (timer_we)
timer <= timer + 1'b1;
end
assign timer_we = we_pcm & (srlatchQbar);
/*-----------------------------------------------------------------------------*/
/* select wheater the PCM clock is derived from main clock or the PCM
datapath can be clocked manually*/
assign we_pcm = ce_pcm;
/*-------------------------Structural modelling ----------------------------*/
/*------------------------ PDM starts -----------------------------------*/
cic cicmodule(clk, rst, ce_pdm, pdm_data_i, cic_out);
/*------------------------ PDM ends -----------------------------------*/
/*------------------------ FIR start -----------------------------------*/
/* extend the 12 bit signal from PDM demodulator to 16 bit*/
assign fir_in = {{4{cic_out[11]}}, cic_out };
// FIR fir_filter(clk, rst, we_pcm, fir_in, fb0, fb1, fir_out);
/*------------------------ FIR ends -----------------------------------*/
/*------------------------ PCM starts -----------------------------------*/
assign pcm_reg_i = control[3] ? pcm_load :fir_out;
/* pcm register block */
always@(posedge clk) begin
if(rst)
pcm <= 0;
else if (we_pcm)
pcm <= pcm_reg_i;
end
/*------------------------ PCM ends -----------------------------------*/
/*------------------------ MUL starts -----------------------------------*/
assign mul_i = control[2] ? pcm : iir_data;
multiplier mul(mul_i, amp, mul_o);
/*------------------------ MUL ends -----------------------------------*/
/*------------------------ ABS starts -----------------------------------*/
Abs abs(mul_o, pcm_abs);
/*------------------------ ABS ends -----------------------------------*/
/*------------------------ IIR starts -----------------------------------*/
/*IIR_Filter u_Filter(
.clk(clk),
.rst(rst),
.en(we_pcm),
.X(pcm),
.a0(a0),
.a1(a1),
.a2(a2),
.b1(b1),
.b2(b2),
.Y(iir_data)
);
*/
/*------------------------ IIR ends -----------------------------------*/
/*------------------------ MAMOV starts ---------------------------------*/
//MAF_FILTER maf(clk, rst, we_pcm, pcm_abs, maf_o);
/*------------------------ MAMOV ends ---------------------------------*/
/*------------------------ COMP starts ----------------------------------*/
comparator comp(maf_o, threshold, compare_out);
SR_latch sr(clk, rst, mclear, compare_out, srlatchQ, srlatchQbar);
assign cmp = srlatchQ;
/*------------------------ COMP ends ----------------------------------*/
Filters filt( .clk(clk),
.rst(rst),
.en(we_pcm),
.X_fir(fir_in),
.b0_fir(fb0),
.b1_fir(fb1),
.Y_fir(fir_out),
.X_iir(pcm),
.a0_iir(a0),
.a1_iir(a1),
.a2_iir(a2),
.b1_iir(b1),
.b2_iir(b2),
.Y_iir(iir_data),
.X_maf(pcm_abs),
.Y_maf(maf_o)
);
endmodule
// Module Name: Abs
// Luis Osses Gutierrez
module Abs
#( parameter n=16)(
input signed [n-1:0] data_in,
output [n-1:0] data_out);
assign data_out = ~data_in[n-1] ? data_in : ~data_in;
endmodule
// Module Name: Comparator
//maximiliano cerda cid
module comparator #(parameter n=16) (data_i,threshold,compare_o);
input wire [n-1:0] data_i, threshold; //maf filter output and treshold value
output wire compare_o; //output of the compare block
//reg compare_o;
assign compare_o = (data_i > threshold) ? 1'b1:1'b0;
endmodule
//////////////////////////////////////////////////////////////////////////////////
// Module Name: MULTIPLICADOR POR CONSTANTE.
// Luis Osses Gutierrez
//////////////////////////////////////////////////////////////////////////////////
module multiplier #(parameter n =16) (data_i, amplify, multiplier_o);
input wire [n-1:0] data_i;
input wire [7:0] amplify;
output wire [n-1:0] multiplier_o;
assign multiplier_o = data_i <<< amplify;
endmodule
/*
SR type letch
*/
module SR_latch(
input clk,
input rst,
input r,
input s,
output reg q,
output reg qbar);
always@(posedge clk) begin
if(rst) begin
q <= 0;
qbar <= 1;
end
else if(s) begin
q <= 1;
qbar <= 0;
end
else if(r) begin
q <= 0;
qbar <= 1;
end
else if(s == 0 & r == 0) begin
q <= q;
qbar <= qbar;
end
end
endmodule
// ---------------------------------------------------- //
// DEMODULATOR FILTER RSS
// Mauricio Montanares, Luis Osses, Max Cerda 2021
// ---------------------------------------------------- //
//This file is completly based on the paper:
// FPGA-BASED REAL-TIME ACOUSTIC CAMERA USING PDM MEMS MICROPHONES WITH A CUSTOM DEMODULATION FILTER
`define OverSample 32
// =========== Top module START =========== //
module cic #(parameter N =- 2)(
input clk, rst, we,
input data_in,
output wire signed [11:0] data_out2
);
integer i;
wire signed [6:0] sum1;
wire signed [1:0] data_1_in;
reg [1:0] ff1[`OverSample];
wire [1:0] ff1_last;
reg [6:0] ff1out;
wire [6:0] dinext1;
wire [6:0] ffext1;
wire signed [11:0] sum2;
reg [6:0] ff2[`OverSample];
wire [6:0] ff2_last;
reg [11:0] ff2out;
wire [11:0] dinext2;
wire [11:0] ffext2;
/* input 2'complement extension */
assign data_1_in = (data_in == 1'b0) ? 2'b11 : 2'b01;
assign dinext1 = {{6{data_1_in[1]}},data_1_in};
assign ff1_last = ff1[`OverSample-1];
assign ffext1 = {{5{ff1_last[1]}}, ff1_last };
assign sum1 = dinext1-ffext1;
assign dinext2 = {{5{ff1out[6]}},ff1out};
assign ff2_last =ff2[`OverSample-1];
assign ffext2 = {{5{ff2_last[6]}}, ff2_last };
assign sum2 = dinext2 - ffext2;
assign data_out2 = ff2out;
always @(posedge clk) begin
if (rst) begin
ff1out <=0;
ff2out <=0;
for(i = 0; i<`OverSample; i=i+1 ) begin
ff1[i] <= 0;
ff2[i] <= 0;
end
end
else if (we) begin
ff1[0] <= data_1_in;
ff2[0] <= ff1out;
for(i = 1; i<`OverSample; i=i+1 ) begin
ff1[i] <= ff1[i-1];
ff2[i] <= ff2[i-1];
end
/* integrator */
ff1out <= ff1out + sum1;
ff2out <= ff2out + sum2;
end
end
endmodule
// ---------------------------------------------------- //
// FILTERS
// ---------------------------------------------------- //
// phase state: FIR 0-4 | IIR 5-10 | MAF 11-15
`define USE_POWER_PINS
module Filters #(parameter N = 16)
(
input clk,
input rst,
input en,
// --- FIR in/outs begin --- //
input signed [N-1:0] X_fir,
input signed [N-1:0] b0_fir,
input signed [N-1:0] b1_fir,
output signed [N-1:0] Y_fir,
// --- FIR in/outs end --- //
// --- IIR in/outs begin --- //
input signed [N-1:0] X_iir,
input signed [N-1:0] a0_iir,
input signed [N-1:0] a1_iir,
input signed [N-1:0] a2_iir,
input signed [N-1:0] b1_iir,
input signed [N-1:0] b2_iir,
output signed [N-1:0] Y_iir,
// --- IIR in/outs end --- //
// --- MAF in/outs begin --- //
input [N-1:0] X_maf,
output [N-1:0] Y_maf
// --- MAF in/outs end --- //
);
//circuit architecture
reg signed [N-1:0] mux_coeff;
reg signed [N-1:0] mux_xy;
wire signed [2*N-1:0] product;
wire [N-1:0] aritmetic_shift;
reg signed [N-1:0] add1;
reg signed [N-1:0] result;
//fir REGs
reg signed [N-1:0] X1_fir, X2_fir, X3_fir, Yt_fir;
//iir REGs
reg signed [N-1:0] X1_iir, X2_iir;
reg signed [N-1:0] Yt_iir, Y1_iir, Y2_iir;
//maf REGs
reg [N-1:0] X1_maf, X2_maf, X3_maf, Yt_maf;
//out REGs
assign Y_fir = Yt_fir;
assign Y_iir = Yt_iir;
assign Y_maf = (Yt_maf >> 2);
// ------- fir, iir and maf samples flow start ------- //
always@(posedge clk) begin
if(rst) begin
//output regs
Yt_fir <= 0;
Yt_iir <= 0;
Yt_maf <= 0;
//fir
X1_fir <= 0;
X2_fir <= 0;
X3_fir <= 0;
//iir
Y1_iir <= 0;
Y2_iir <= 0;
X1_iir <= 0;
X2_iir <= 0;
//maf
X1_maf <= 0;
X2_maf <= 0;
X3_maf <= 0;
end
else if(en == 1) begin
//fir
X1_fir <= X_fir;
X2_fir <= X1_fir;
X3_fir <= X2_fir;
//iir
Y1_iir <= Yt_iir;
Y2_iir <= Y1_iir;
X1_iir <= X_iir;
X2_iir <= X1_iir;
//maf
X1_maf <= X_maf;
X2_maf <= X1_maf;
X3_maf <= X2_maf;
end
else if(phase == phase4)
Yt_fir <= result;
else if(phase == phase10)
Yt_iir <= result;
else if(phase == phase15)
Yt_maf <= result;
end
// ------- fir, iir and maf samples flow end ------- //
// ================== FSMs start ================== //
reg [4:0] phase; //state
reg [4:0] next_phase; //next_state
parameter phase0 = 0; parameter phase1 = 1;
parameter phase2 = 2; parameter phase3 = 3;
parameter phase4 = 4; parameter phase5 = 5;
parameter phase6 = 6; parameter phase7 = 7;
parameter phase8 = 8; parameter phase9 = 9;
parameter phase10 = 10; parameter phase11 = 11;
parameter phase12 = 12; parameter phase13 = 13;
parameter phase14 = 14;
parameter phase15 = 15;
parameter phase16 = 16;
always @(posedge clk) begin
if (rst)
phase <= phase0;
else if(en == 1 )
phase <= phase0;
else
phase <= next_phase;
end
// ------- MUX's coeffs - Samples FIR/IIR start ------- //
always @(phase or en or aritmetic_shift or X1_maf or X2_maf or X3_maf) begin
case(phase)
//fir Yt = X*b0 + X1*b1 + X2*b1 + X3*b0
phase0 : begin
mux_coeff = b0_fir;
mux_xy = X_fir;
add1 = aritmetic_shift;
next_phase = phase1;
end
phase1 : begin
mux_coeff = b1_fir;
mux_xy = X1_fir;
add1 = aritmetic_shift;
next_phase = phase2;
end
phase2 : begin
mux_coeff = b1_fir;
mux_xy = X2_fir;
add1 = aritmetic_shift;
next_phase = phase3;
end
phase3 : begin
mux_coeff = b0_fir;
mux_xy = X3_fir;
add1 = aritmetic_shift;
next_phase = phase4;
end
phase4 : begin
next_phase = phase5;
end
//iir Y <= X*a0 + X1*a1 + X2*a2 - Y1*b1 - Y2*b2;
phase5 : begin
mux_coeff = a0_iir;
mux_xy = X_iir;
add1 = aritmetic_shift;
next_phase = phase6;
end
phase6 : begin
mux_coeff = a1_iir;
mux_xy = X1_iir;
add1 = aritmetic_shift;
next_phase = phase7;
end
phase7 : begin
mux_coeff = a2_iir;
mux_xy = X2_iir;
add1 = aritmetic_shift;
next_phase = phase8;
end
phase8 : begin
mux_coeff = b1_iir;
mux_xy = -Y1_iir;
add1 = aritmetic_shift;
next_phase = phase9;
end
phase9 : begin
mux_coeff = b2_iir;
mux_xy = -Y2_iir;
add1 = aritmetic_shift;
next_phase = phase10;
end
phase10 : begin
next_phase = phase11;
end
//MAF
phase11 : begin
add1 = X_maf;
next_phase = phase12;
end
phase12 : begin
add1 = X1_maf;
next_phase = phase13;
end
phase13 : begin
add1 = X2_maf;
next_phase = phase14;
end
phase14 : begin
add1 = X3_maf;
next_phase = phase15;
end
phase15 : begin
next_phase = phase16;
end
default : begin
add1 = aritmetic_shift;
end
endcase
end
// ------- MUX's coeffs - Samples FIR/IIR end ------- //
// ================== FSMs end ================== //
// ------- Math operations begin ------- //
assign product = mux_coeff * mux_xy;
assign aritmetic_shift = product >>> 15;
// ------- Math operations end ------- //
// ------ Acumulacion start -------- //
always @(posedge clk) begin
if(rst ==1'b1)
begin
result <= 0;
end
else if (en == 1)
result <= 0;
else if (phase == phase4)
result <= 0;
else if (phase == phase10)
result <= 0;
else
result <= result + add1; //acumulacion
end
// ------ Acumulacion end -------- //
endmodule