Skip to content

Instantly share code, notes, and snippets.

@ruilvo
Created July 20, 2023 14:20
Show Gist options
  • Select an option

  • Save ruilvo/adbbf3f729a55dd149963ab1e4ed2556 to your computer and use it in GitHub Desktop.

Select an option

Save ruilvo/adbbf3f729a55dd149963ab1e4ed2556 to your computer and use it in GitHub Desktop.
Verilog SONAR
module peak_detect(
//-----------------------------------------------
// Global signals
input DIN_RDY, // data in is ready AKA 48kHz clock
input starttx, //so we know when we start counting
input endtx,
input clock, // master clock, active in posedge
input reset, // master reset, synchronous, active high
input corr_rdy, // New correlation available
input [41:0] corrin, // new correlation input
output reg [15:0] pktimeoutput //time between start_tx and pk
);
//Counter that counts samples that arrived since the tranmission started
reg [15:0] contador;
always @ (posedge clock) begin
if (reset) contador <= 0;
else begin
if (starttx || endtx) contador <= 0;
else begin
if (DIN_RDY) contador <= contador + 1;
else contador <= contador;
end
end
end
reg [15:0] pktimetmp;
reg [41:0] maxcorrun; // read "max corr until now"
//Peak detector
always @ (posedge clock) begin
if (reset) begin
pktimetmp <= 0;
maxcorrun <= 0;
end
else begin
if (starttx) begin //On starttx reset the values
pktimetmp <= 0;
maxcorrun <= 0;
end
else begin
if (corrin > maxcorrun) begin
pktimetmp <= contador;
maxcorrun <= corrin;
end
else begin
pktimetmp <= pktimetmp;
maxcorrun <= maxcorrun;
end
end
end
end
//Peak detector output
always @ (posedge clock) begin
if (reset) pktimeoutput <= 0;
else begin
if (starttx) pktimeoutput <= pktimetmp;
else pktimeoutput <= pktimeoutput;
end
end
endmodule
module sonar_rx(
//-----------------------------------------------
// Global signals
input clock, // master clock, active in posedge
input reset, // master reset, synchronous, active high
input [9:0] Nsamples, // Number of samples of the reference signal
//-----------------------------------------------
// Audio data in:
input signed [15:0] audioin, // audio data in
input DIN_RDY, // data in is ready
//-----------------------------------------------
// Raw correlation output (unsigned, absolute value)
output reg signed [41:0] corrout, // data out, correlation output
output reg corr_rdy, //we have a new correlation available
input signed [31:0] ref_sig,
input signed [31:0] ref_sigm1,
output reg [8:0] refaddr,
output reg [8:0] refaddrm1
);
//-----------------------------------------------------------------
// Instantiate the circular buffer, 1K samples, 4 data samples per read:
wire [7:0] readaddr;
wire signed [71:0] audio4out; // 4 audio samples, 18 bits per sample
RAM_CB_1k RAM_CB_1k_1
(
.clock( clock ),
.reset( reset ),
// Write port, internal addressing:
.din( {2'b00, audioin} ), // input audio stream: zero the two MSbits
.wen( DIN_RDY ), // input data enable (this is the write enable to the memory)
// Read port, 256 data, 4 audio samples per read
.addrin( readaddr ), // read address: each memory read outputs 4 data samples
.dout( audio4out ) // 4 data samples, 16 bit signed
);
// 4 data samples read from the circular buffer:
wire signed [15:0] audio0, audio1, audio2, audio3;
// Split data read into separate samples
// Remove the two MSbits, we'll use only the lower 16 LSBits
assign audio0 = audio4out[71-2:54]; // this is the most recent sample
assign audio1 = audio4out[53-2:36];
assign audio2 = audio4out[35-2:18];
assign audio3 = audio4out[17-2: 0]; // this is the oldest sample
// accumulator for the correlation function:
reg signed [41:0] correlation = 42'd0;
// This is the memory holding the reference signal, two samples per memory location.
// With some adjustments, this memory could be the same as the RAM memory
// used for the TX channel (see register array 'datamemory' in module sonar_tx.v).
//
// However, to share this memory between the two processes we must be able to read
// the memory for the receive process while the transmission is running.
//
// The tx data memory is presently organized as a 32bit x 512, holding two 16-bit samples
// in each memory location. This memory may be written by the serial interface, two samples
// per write operation and pre-loaded at compile time with a data file created by the
// Matlab script "create_simdata.m".
/*
//################################################ TO BE FIXED ################################
// This parameter must be defined in the testbench
parameter REF_IN_FILENAME = "*** FILENAME NOT VALID ***";
// In this simulation model, we use a second memory with the same organization of the memory
// present in the tx module. This memory is not loadable via the serial interface and can only
// be pre-loaded with the data from the file REF_IN_FILENAME
reg signed [31:0] refsignal[0:511];
// Load the memory with the reference signal:
integer i;
initial begin
$display("Loading reference signal from file %s:", REF_IN_FILENAME );
for(i=0; i<512; i=i+1)
refsignal[i] = 0;
$readmemh( REF_IN_FILENAME, refsignal );
end
assign ref23 = refsignal[refaddrm1];
assign ref01 = refsignal[refaddr];
// Registers to read two 32-bit words (two samples each)
wire [31:0] ref01, ref23;
// The four data samples read from the reference signal
// These must be signed for the implementation of the multiplication:
wire signed [15:0] ref0, ref1, ref2, ref3;
// addresses to the memory with the referecne signal
reg [8:0] refaddr, // refaddr is decremented by two
refaddrm1; // this is refaddr minus 1, also decremented by two.
//########################################### /TO BE FIXED ######################################
*/
//######################################### NEW AND FIXED REF MEMORY ACCESS
// addresses to the memory with the referecne signal
//reg [8:0] refaddr, // refaddr is decremented by two
// refaddrm1; // this is refaddr minus 1, also decremented by two.
// Registers to read two 32-bit words (two samples each)
//wire [31:0] ref01, ref23;
// The four data samples read from the reference signal
// These must be signed for the implementation of the multiplication:
wire signed [15:0] ref0, ref1, ref2, ref3;
// read the reference signal:
//assign ref23 = ref_sigm1;
//assign ref01 = ref_sig;
//assign refaddr_rx = refaddr;
//assign refaddrm1_rx = refaddrm1;
assign ref0 = ref_sig[15:0];
assign ref1 = ref_sig[31:16];
assign ref2 = ref_sigm1[15:0];
assign ref3 = ref_sigm1[31:16];
//##################################### /NEW AND FIXED REF MEMORY ACCESS #####################
reg busy;
//http://www.asic-world.com/tidbits/verilog_fsm.html <<--- Como implementar uma maquina de estados em condições
parameter IDLE = 2'b00;
parameter CORR = 2'b10;
parameter START = 2'b11;
reg [1:0] state;
wire [1:0] next_state;
assign next_state = fsm_function(state, DIN_RDY, busy);
function [1:0] fsm_function(input [1:0] state,
input DIN_RDY,
input busy);
case(state)
IDLE: if(DIN_RDY==1'b1) fsm_function = START; else fsm_function = IDLE;
START: if(DIN_RDY==1'b1) fsm_function = START; else fsm_function = CORR;
CORR: if(busy) fsm_function = CORR; else fsm_function = IDLE;
default: fsm_function = IDLE;
endcase
endfunction
always @ (posedge clock) begin
if (reset) state <= IDLE;
else state <= next_state;
end
wire [9:0] counter_max = (Nsamples >> 2)+2;
reg [9:0] counter;
assign readaddr = counter; // read address for the circular buffer related to the counter
//And do something
always @ (posedge clock) begin
if (reset) begin
busy <= 0;
counter <= 0;
correlation <= 42'd0;
corr_rdy <= 0;
refaddr <= (Nsamples >> 1);
refaddrm1 <= (Nsamples >> 1)-1;
end
else begin
case (state)
IDLE: begin
counter <= 0;
corr_rdy <= 0;
refaddr <= (Nsamples >> 1);
refaddrm1 <= (Nsamples >> 1)-1;
end
START: begin
//Load last correlation
corrout <= correlation[41] ? -correlation : correlation;
corr_rdy <= 1;
//This make it keep on this state
busy <= 1'b1;
//Increment the adress for the audio memory
counter <= counter +1;
//Reset correlation
//correlation <= ref0 * audio0 + ref1 * audio1 + ref2 * audio2 + ref3 * audio3;
// decrement the addresses of the reference memory:
refaddr <= refaddr - 2;
refaddrm1 <= refaddrm1 - 2;
correlation <= 42'd0;
end
CORR: begin
//$display("CORR");
if (counter>=counter_max) busy <= 1'b0; //This makes next state be IDLE
else begin
//update correlation value
correlation <= correlation + ref0 * audio0 + ref1 * audio1 + ref2 * audio2 + ref3 * audio3;
corr_rdy <= 0;
//This make it keep on this state
busy <= 1'b1;
//Increment the adress for the audio memory
counter <= counter +1;
// decrement the addresses of the reference memory:
refaddr <= refaddr - 2;
refaddrm1 <= refaddrm1 - 2;
if (counter>=(counter_max-2)) busy <= 1'b0;
end
end
//TODO: check default and etc
endcase
end
end
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment