mirror of
https://github.com/trcwm/Speech256.git
synced 2025-06-07 16:48:32 +02:00
Added 2nd order sigma-delta DAC. Added changes suggested by Clifford Wolf.
This commit is contained in:
parent
45afdd3500
commit
a2432a5e55
@ -75,16 +75,6 @@ set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[3]
|
|||||||
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[4]
|
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[4]
|
||||||
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[5]
|
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[5]
|
||||||
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to UART_TXD
|
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to UART_TXD
|
||||||
set_global_assignment -name PIN_FILE Speech256_de0.pin
|
|
||||||
set_global_assignment -name VERILOG_FILE speech256_de0.v
|
|
||||||
set_global_assignment -name VERILOG_FILE ../../verilog/controller/xlat.v
|
|
||||||
set_global_assignment -name VERILOG_FILE ../../verilog/controller/ctrlrom.v
|
|
||||||
set_global_assignment -name VERILOG_FILE ../../verilog/controller/controller.v
|
|
||||||
set_global_assignment -name VERILOG_FILE ../../verilog/filter/filter.v
|
|
||||||
set_global_assignment -name VERILOG_FILE ../../verilog/pwmdac/pwmdac.v
|
|
||||||
set_global_assignment -name VERILOG_FILE ../../verilog/source/source.v
|
|
||||||
set_global_assignment -name VERILOG_FILE ../../verilog/spmul/spmul.v
|
|
||||||
set_global_assignment -name VERILOG_FILE ../../verilog/speech256_top/speech256_top.v
|
|
||||||
set_location_assignment PIN_B1 -to LEDG[9]
|
set_location_assignment PIN_B1 -to LEDG[9]
|
||||||
set_location_assignment PIN_B2 -to LEDG[8]
|
set_location_assignment PIN_B2 -to LEDG[8]
|
||||||
set_location_assignment PIN_C2 -to LEDG[7]
|
set_location_assignment PIN_C2 -to LEDG[7]
|
||||||
@ -337,4 +327,15 @@ set_location_assignment PIN_C3 -to DRAM_ADDR[3]
|
|||||||
set_location_assignment PIN_B3 -to DRAM_ADDR[2]
|
set_location_assignment PIN_B3 -to DRAM_ADDR[2]
|
||||||
set_location_assignment PIN_A3 -to DRAM_ADDR[1]
|
set_location_assignment PIN_A3 -to DRAM_ADDR[1]
|
||||||
set_location_assignment PIN_C4 -to DRAM_ADDR[0]
|
set_location_assignment PIN_C4 -to DRAM_ADDR[0]
|
||||||
|
set_global_assignment -name PIN_FILE Speech256_de0.pin
|
||||||
|
set_global_assignment -name VERILOG_FILE speech256_de0.v
|
||||||
|
set_global_assignment -name VERILOG_FILE ../../verilog/controller/xlat.v
|
||||||
|
set_global_assignment -name VERILOG_FILE ../../verilog/controller/ctrlrom.v
|
||||||
|
set_global_assignment -name VERILOG_FILE ../../verilog/controller/controller.v
|
||||||
|
set_global_assignment -name VERILOG_FILE ../../verilog/filter/filter.v
|
||||||
|
set_global_assignment -name VERILOG_FILE ../../verilog/pwmdac/pwmdac.v
|
||||||
|
set_global_assignment -name VERILOG_FILE ../../verilog/source/source.v
|
||||||
|
set_global_assignment -name VERILOG_FILE ../../verilog/spmul/spmul.v
|
||||||
|
set_global_assignment -name VERILOG_FILE ../../verilog/sd2dac/sd2dac.v
|
||||||
|
set_global_assignment -name VERILOG_FILE ../../verilog/speech256_top/speech256_top.v
|
||||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
@ -5,6 +5,8 @@
|
|||||||
// http://www.moseleyinstruments.com
|
// http://www.moseleyinstruments.com
|
||||||
//
|
//
|
||||||
|
|
||||||
|
`define USE_SDDAC
|
||||||
|
|
||||||
module Speech256_DE0 (
|
module Speech256_DE0 (
|
||||||
CLOCK_50,
|
CLOCK_50,
|
||||||
SW,
|
SW,
|
||||||
@ -25,6 +27,10 @@ module Speech256_DE0 (
|
|||||||
reg [3:0] divcnt; // clock divider counter
|
reg [3:0] divcnt; // clock divider counter
|
||||||
reg [2:0] cur_state, next_state;
|
reg [2:0] cur_state, next_state;
|
||||||
|
|
||||||
|
reg [2:0] rom_addr;
|
||||||
|
reg [5:0] rom_data;
|
||||||
|
reg inc_rom_addr;
|
||||||
|
|
||||||
// debug signals for 16-bit DAC
|
// debug signals for 16-bit DAC
|
||||||
wire sample_stb;
|
wire sample_stb;
|
||||||
wire signed [15:0] sample_out;
|
wire signed [15:0] sample_out;
|
||||||
@ -36,7 +42,7 @@ module Speech256_DE0 (
|
|||||||
.clk (clk),
|
.clk (clk),
|
||||||
.rst_an (rst_an),
|
.rst_an (rst_an),
|
||||||
.ldq (ldq),
|
.ldq (ldq),
|
||||||
.data_in (SW),
|
.data_in (rom_data),
|
||||||
.data_stb (data_stb),
|
.data_stb (data_stb),
|
||||||
.pwm_out (UART_TXD),
|
.pwm_out (UART_TXD),
|
||||||
.sample_out (sample_out),
|
.sample_out (sample_out),
|
||||||
@ -67,6 +73,8 @@ module Speech256_DE0 (
|
|||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
begin
|
begin
|
||||||
cur_state <= next_state;
|
cur_state <= next_state;
|
||||||
|
if (inc_rom_addr == 1)
|
||||||
|
rom_addr <= rom_addr + 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
//assign LEDG[9:0] = sample_out[15:6];
|
//assign LEDG[9:0] = sample_out[15:6];
|
||||||
@ -74,18 +82,23 @@ module Speech256_DE0 (
|
|||||||
assign LEDG[1] = ldq;
|
assign LEDG[1] = ldq;
|
||||||
assign LEDG[2] = SW[2];
|
assign LEDG[2] = SW[2];
|
||||||
assign LEDG[3] = SW[3];
|
assign LEDG[3] = SW[3];
|
||||||
|
assign LEDG[4] = 0;
|
||||||
|
|
||||||
always @(*)
|
always @(*)
|
||||||
begin
|
begin
|
||||||
// FSM defaults
|
// FSM defaults
|
||||||
data_stb <= 0;
|
data_stb <= 0;
|
||||||
|
inc_rom_addr <= 0;
|
||||||
next_state <= cur_state;
|
next_state <= cur_state;
|
||||||
|
|
||||||
case(cur_state)
|
case(cur_state)
|
||||||
S_IDLE:
|
S_IDLE:
|
||||||
begin
|
begin
|
||||||
if ((ldq == 1) && (BUTTON[0] == 1))
|
if ((ldq == 1) && (BUTTON[0] == 1))
|
||||||
|
begin
|
||||||
|
inc_rom_addr <= 1;
|
||||||
next_state <= S_ALLOPHONE;
|
next_state <= S_ALLOPHONE;
|
||||||
|
end
|
||||||
else
|
else
|
||||||
next_state <= S_IDLE;
|
next_state <= S_IDLE;
|
||||||
end
|
end
|
||||||
@ -97,13 +110,45 @@ module Speech256_DE0 (
|
|||||||
S_WAITDONE:
|
S_WAITDONE:
|
||||||
begin
|
begin
|
||||||
if (ldq == 0)
|
if (ldq == 0)
|
||||||
|
begin
|
||||||
|
inc_rom_addr <= 1;
|
||||||
next_state <= S_IDLE;
|
next_state <= S_IDLE;
|
||||||
end
|
end
|
||||||
|
end
|
||||||
default:
|
default:
|
||||||
begin
|
begin
|
||||||
next_state <= S_IDLE;
|
next_state <= S_IDLE;
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
|
// allophone ROM
|
||||||
|
// hello, world
|
||||||
|
case (rom_addr)
|
||||||
|
3'd0:
|
||||||
|
rom_data <= 6'h1B;
|
||||||
|
3'd1:
|
||||||
|
rom_data <= 6'h07;
|
||||||
|
3'd2:
|
||||||
|
rom_data <= 6'h2D;
|
||||||
|
3'd3:
|
||||||
|
rom_data <= 6'h35;
|
||||||
|
3'd4:
|
||||||
|
rom_data <= 6'h03;
|
||||||
|
3'd5:
|
||||||
|
rom_data <= 6'h2E;
|
||||||
|
3'd6:
|
||||||
|
rom_data <= 6'h1E;
|
||||||
|
3'd7:
|
||||||
|
rom_data <= 6'h33;
|
||||||
|
3'd8:
|
||||||
|
rom_data <= 6'h2D;
|
||||||
|
3'd9:
|
||||||
|
rom_data <= 6'h15;
|
||||||
|
3'd10:
|
||||||
|
rom_data <= 6'h03;
|
||||||
|
default:
|
||||||
|
rom_data <= 6'h00;
|
||||||
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -89,13 +89,13 @@ module CONTROLLER (
|
|||||||
.en (rom_en)
|
.en (rom_en)
|
||||||
);
|
);
|
||||||
|
|
||||||
parameter ROM_ADDR_ZERO = 3'b000, // zero the ROM address
|
localparam ROM_ADDR_ZERO = 3'b000, // zero the ROM address
|
||||||
ROM_ADDR_INC = 3'b001, // increment the ROM address
|
ROM_ADDR_INC = 3'b001, // increment the ROM address
|
||||||
ROM_ADDR_JMP = 3'b010, // jump to code
|
ROM_ADDR_JMP = 3'b010, // jump to code
|
||||||
ROM_ADDR_ALLO = 3'b011, // read allophone jump address
|
ROM_ADDR_ALLO = 3'b011, // read allophone jump address
|
||||||
ROM_ADDR_NOP = 3'b100;
|
ROM_ADDR_NOP = 3'b100;
|
||||||
|
|
||||||
parameter COEFF_CNT_ZERO = 2'b00, // zero coefficient counter
|
localparam COEFF_CNT_ZERO = 2'b00, // zero coefficient counter
|
||||||
COEFF_CNT_NOP = 2'b01, // do nothing
|
COEFF_CNT_NOP = 2'b01, // do nothing
|
||||||
COEFF_CNT_INC = 2'b10; // increment coefficient counter
|
COEFF_CNT_INC = 2'b10; // increment coefficient counter
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ module CONTROLLER (
|
|||||||
|
|
||||||
assign serve_next_allo_data = (dur_cnt == duration) ? 1 : 0;
|
assign serve_next_allo_data = (dur_cnt == duration) ? 1 : 0;
|
||||||
|
|
||||||
parameter S_IDLE = 4'd0,
|
localparam S_IDLE = 4'd0,
|
||||||
S_JMPADDR1 = 4'd1,
|
S_JMPADDR1 = 4'd1,
|
||||||
S_JMPADDR2 = 4'd2,
|
S_JMPADDR2 = 4'd2,
|
||||||
S_JMPADDR3 = 4'd3,
|
S_JMPADDR3 = 4'd3,
|
||||||
|
@ -20,6 +20,7 @@ module FILTER (
|
|||||||
start, // trigger processing of the input signal
|
start, // trigger processing of the input signal
|
||||||
done // goes to '1' when sig_out has valid data
|
done // goes to '1' when sig_out has valid data
|
||||||
);
|
);
|
||||||
|
|
||||||
parameter DEBUG = 0; //defult value
|
parameter DEBUG = 0; //defult value
|
||||||
|
|
||||||
//////////// CLOCK //////////
|
//////////// CLOCK //////////
|
||||||
@ -179,7 +180,7 @@ module FILTER (
|
|||||||
end
|
end
|
||||||
|
|
||||||
// FSM states
|
// FSM states
|
||||||
parameter S_IDLE = 4'b0000,
|
localparam S_IDLE = 4'b0000,
|
||||||
S_DUMMY1 = 4'b0001,
|
S_DUMMY1 = 4'b0001,
|
||||||
S_WAITMUL1 = 4'b0010,
|
S_WAITMUL1 = 4'b0010,
|
||||||
S_UPDATEC1 = 4'b0011,
|
S_UPDATEC1 = 4'b0011,
|
||||||
|
6
verilog/sd2dac/run_tb.bat
Normal file
6
verilog/sd2dac/run_tb.bat
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
mkdir bin
|
||||||
|
del bin\sd2dac.vvp
|
||||||
|
C:\iverilog\bin\iverilog -o bin\sd2dac.vvp -m va_math -g2005 -s SD2DAC_TB sd2dac.v sd2dac_tb.v
|
||||||
|
cd bin
|
||||||
|
C:\iverilog\bin\vvp sd2dac.vvp
|
||||||
|
cd ..
|
132
verilog/sd2dac/sd2dac.v
Normal file
132
verilog/sd2dac/sd2dac.v
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
//
|
||||||
|
// Second-order sigma-delta DAC
|
||||||
|
// The DAC has a pull interface.
|
||||||
|
//
|
||||||
|
// Number of input bits used: 12
|
||||||
|
//
|
||||||
|
// Niels Moseley - Moseley Instruments 2017
|
||||||
|
// http://www.moseleyinstruments.com
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Designed for a clock rate of 2.5 MHz
|
||||||
|
//
|
||||||
|
|
||||||
|
module SD2DAC (
|
||||||
|
clk,
|
||||||
|
rst_an,
|
||||||
|
din, // 16 bit signed data input
|
||||||
|
din_ack, // is high for 1 clock cycle after reading the din signal
|
||||||
|
dacout // 1-bit SD output signal
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
input signed [15:0] din;
|
||||||
|
input rst_an, clk;
|
||||||
|
output reg din_ack;
|
||||||
|
output reg dacout;
|
||||||
|
|
||||||
|
reg [15:0] din_reg; // data input register
|
||||||
|
reg [15:0] last_din; // previous input sample
|
||||||
|
//reg [15:0] delta;
|
||||||
|
|
||||||
|
reg [7:0] counter; // sample counter
|
||||||
|
reg signed [15:0] state1, state2; // integrator states
|
||||||
|
reg signed [15:0] new_state1, new_state2;
|
||||||
|
reg signed [15:0] state1_in, state2_in; // input to integrators
|
||||||
|
wire signed [15:0] state1_a, state2_a; // output of integrator adders
|
||||||
|
wire signed [16:0] quant_in;
|
||||||
|
|
||||||
|
reg quant_out;
|
||||||
|
|
||||||
|
always @(posedge clk or negedge rst_an)
|
||||||
|
begin
|
||||||
|
if (rst_an == 0)
|
||||||
|
begin
|
||||||
|
state1 <= 0;
|
||||||
|
state2 <= 0;
|
||||||
|
counter <= 0;
|
||||||
|
din_reg <= 0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
// clocked process
|
||||||
|
state1 <= new_state1;
|
||||||
|
state2 <= new_state2;
|
||||||
|
dacout <= quant_out;
|
||||||
|
counter <= counter + 1;
|
||||||
|
if (din_ack == 1)
|
||||||
|
begin
|
||||||
|
last_din <= din_reg;
|
||||||
|
din_reg <= {din[15], din[15:1]}; // div by 2!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign state1_a = state1 + state1_in;
|
||||||
|
assign state2_a = state2 + state2_in;
|
||||||
|
assign quant_in = $signed( { {3{din_reg[15]}}, din_reg[15:2]} ) + state2;
|
||||||
|
|
||||||
|
always @(*)
|
||||||
|
begin
|
||||||
|
// ------------------------------
|
||||||
|
// calculate new state 1
|
||||||
|
// ------------------------------
|
||||||
|
|
||||||
|
if (quant_out == 1)
|
||||||
|
// (din >> 2) - (quant_out >> 2)
|
||||||
|
state1_in <= $signed( { {2{din_reg[15]}}, din_reg[15:2]} ) - $signed(16'h1FFF);
|
||||||
|
else
|
||||||
|
state1_in <= $signed( { {2{din_reg[15]}}, din_reg[15:2]} ) + $signed(16'h1FFF);
|
||||||
|
|
||||||
|
// check for saturation:
|
||||||
|
// if operand sign bits are the same
|
||||||
|
// the result should have the same
|
||||||
|
// sign bit, if not, we need to
|
||||||
|
// saturate.
|
||||||
|
//
|
||||||
|
// 1000 + 1111 => 1000 (-8 + -1 saturates at -8)
|
||||||
|
// 0111 + 0001 => 0111 (7 + 1 saturates at 7)
|
||||||
|
//
|
||||||
|
if (state1[15] == state1_in[15])
|
||||||
|
begin
|
||||||
|
if (state1[15] != state1_a[15])
|
||||||
|
new_state1 <= state1[15] ? 16'h8000 : 16'h7FFF;
|
||||||
|
else
|
||||||
|
new_state1 <= state1_a;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
new_state1 <= state1_a;
|
||||||
|
|
||||||
|
// ------------------------------
|
||||||
|
// calculate new state 2
|
||||||
|
// ------------------------------
|
||||||
|
|
||||||
|
if (quant_out == 1)
|
||||||
|
// state1 - (quant_out >> 1)
|
||||||
|
state2_in <= state1 - $signed(16'h3FFF);
|
||||||
|
else
|
||||||
|
state2_in <= state1 + $signed(16'h3FFF);
|
||||||
|
|
||||||
|
if (state2[15] == state2_in[15])
|
||||||
|
begin
|
||||||
|
if (state2[15] != state2_a[15])
|
||||||
|
new_state2 <= state2[15] ? 16'h8000 : 16'h7FFF;
|
||||||
|
else
|
||||||
|
new_state2 <= state2_a;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
new_state2 <= state2_a;
|
||||||
|
|
||||||
|
// ------------------------------
|
||||||
|
// calculate quantizer
|
||||||
|
// ------------------------------
|
||||||
|
|
||||||
|
quant_out <= !quant_in[16];
|
||||||
|
|
||||||
|
if (counter == 8'h0)
|
||||||
|
din_ack <= 1;
|
||||||
|
else
|
||||||
|
din_ack <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
59
verilog/sd2dac/sd2dac_tb.v
Normal file
59
verilog/sd2dac/sd2dac_tb.v
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// PWMDAC testbench
|
||||||
|
//
|
||||||
|
// Niels Moseley - Moseley Instruments 2017
|
||||||
|
// http://www.moseleyinstruments.com
|
||||||
|
//
|
||||||
|
|
||||||
|
module SD2DAC_TB;
|
||||||
|
reg clk, rst_an;
|
||||||
|
reg signed [15:0] din;
|
||||||
|
wire dacout, din_ack;
|
||||||
|
|
||||||
|
real accu;
|
||||||
|
|
||||||
|
SD2DAC u_sd2dac (
|
||||||
|
.clk (clk),
|
||||||
|
.rst_an (rst_an),
|
||||||
|
.din (din),
|
||||||
|
.din_ack (din_ack),
|
||||||
|
.dacout (dacout)
|
||||||
|
);
|
||||||
|
|
||||||
|
integer fd;
|
||||||
|
|
||||||
|
initial
|
||||||
|
begin
|
||||||
|
fd = $fopen("dacout.sw","wb");
|
||||||
|
$dumpfile ("sd2dac.vcd");
|
||||||
|
$dumpvars;
|
||||||
|
clk = 0;
|
||||||
|
rst_an = 0;
|
||||||
|
din = 0;
|
||||||
|
accu = 0;
|
||||||
|
#3
|
||||||
|
rst_an = 1;
|
||||||
|
#1048576
|
||||||
|
$fclose(fd);
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
if (din_ack)
|
||||||
|
begin
|
||||||
|
accu = accu + 1.0/256.0;
|
||||||
|
if (accu > 1.0)
|
||||||
|
accu = -1.0;
|
||||||
|
din = $rtoi($sin(2.0*3.1415927*accu)*10000.0);
|
||||||
|
end
|
||||||
|
if (dacout == 1)
|
||||||
|
$fwrite(fd,"%u", 32'h7000_0000);
|
||||||
|
else
|
||||||
|
$fwrite(fd,"%u", 32'h9000_0000);
|
||||||
|
end
|
||||||
|
|
||||||
|
always
|
||||||
|
#5 clk = !clk;
|
||||||
|
|
||||||
|
endmodule
|
19
verilog/sd2dac/show_tb_results.m
Normal file
19
verilog/sd2dac/show_tb_results.m
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
%
|
||||||
|
% Show testbench results for sd2dac
|
||||||
|
%
|
||||||
|
% This is a MATLAB file
|
||||||
|
%
|
||||||
|
|
||||||
|
fileID = fopen('bin/dacout.sw');
|
||||||
|
A = fread(fileID,'*int32')';
|
||||||
|
fclose(fileID);
|
||||||
|
|
||||||
|
A = single(A)/2^31;
|
||||||
|
|
||||||
|
clf;
|
||||||
|
figure(1);
|
||||||
|
X = fft(A.*blackman(length(A))') / (length(A)/4);
|
||||||
|
semilogx(20*log10(abs(X)));
|
||||||
|
grid on;
|
||||||
|
axis([0 length(X)/2 -140 10]);
|
||||||
|
|
@ -72,14 +72,23 @@ module SPEECH256_TOP (
|
|||||||
.done (src_strobe)
|
.done (src_strobe)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
`ifdef USE_SDDAC
|
||||||
|
SD2DAC u_sd2dac (
|
||||||
|
.clk (clk),
|
||||||
|
.rst_an (rst_an),
|
||||||
|
.din ($signed({sig_filter[11:0],4'h0})), // add +24dB gain .. FIXME: add saturation ??
|
||||||
|
.din_ack (pwmdac_ack),
|
||||||
|
.dacout (pwm_out)
|
||||||
|
);
|
||||||
|
`else
|
||||||
PWMDAC u_pwmdac (
|
PWMDAC u_pwmdac (
|
||||||
.clk (clk),
|
.clk (clk),
|
||||||
.rst_an (rst_an),
|
.rst_an (rst_an),
|
||||||
//.din (sig_filter[15:8]),
|
|
||||||
.din (sig_filter[11:4]), // add +24dB gain .. FIXME: add saturation ??
|
.din (sig_filter[11:4]), // add +24dB gain .. FIXME: add saturation ??
|
||||||
.din_ack (pwmdac_ack),
|
.din_ack (pwmdac_ack),
|
||||||
.dacout (pwm_out)
|
.dacout (pwm_out)
|
||||||
);
|
);
|
||||||
|
`endif
|
||||||
|
|
||||||
CONTROLLER u_controller (
|
CONTROLLER u_controller (
|
||||||
.clk (clk),
|
.clk (clk),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user