mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-02-02 14:50:52 +00:00
Moon Patrol Cleanup
This commit is contained in:
310
common/CPU/T80/k580vi53.v
Normal file
310
common/CPU/T80/k580vi53.v
Normal file
@@ -0,0 +1,310 @@
|
||||
//
|
||||
// K580VI53 timer implementation
|
||||
//
|
||||
// Copyright (c) 2016 Sorgelig
|
||||
//
|
||||
//
|
||||
// This source file is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// altera message_off 10240
|
||||
|
||||
|
||||
`default_nettype none
|
||||
|
||||
module k580vi53
|
||||
(
|
||||
// CPU bus
|
||||
input reset,
|
||||
input clk_sys,
|
||||
input [1:0] addr,
|
||||
input [7:0] din,
|
||||
output [7:0] dout,
|
||||
input wr,
|
||||
input rd,
|
||||
|
||||
// Timer signals
|
||||
input [2:0] clk_timer,
|
||||
input [2:0] gate,
|
||||
output [2:0] out,
|
||||
output [2:0] sound_active
|
||||
);
|
||||
|
||||
wire [7:0] dout0;
|
||||
wire [7:0] dout1;
|
||||
wire [7:0] dout2;
|
||||
|
||||
assign dout = dout0 & dout1 & dout2;
|
||||
|
||||
timer t0(reset, clk_sys, clk_timer[0], din, dout0, wr && (addr == 3) && (din[7:6] == 0), wr && (addr == 0), rd && (addr == 0), gate[0], out[0], sound_active[0]);
|
||||
timer t1(reset, clk_sys, clk_timer[1], din, dout1, wr && (addr == 3) && (din[7:6] == 1), wr && (addr == 1), rd && (addr == 1), gate[1], out[1], sound_active[1]);
|
||||
timer t2(reset, clk_sys, clk_timer[2], din, dout2, wr && (addr == 3) && (din[7:6] == 2), wr && (addr == 2), rd && (addr == 2), gate[2], out[2], sound_active[2]);
|
||||
|
||||
endmodule
|
||||
|
||||
module timer
|
||||
(
|
||||
input reset,
|
||||
input clk_sys,
|
||||
input clk_timer,
|
||||
input [7:0] din,
|
||||
output [7:0] dout,
|
||||
input wr_cw,
|
||||
input wr,
|
||||
input rd,
|
||||
input gate,
|
||||
output reg out,
|
||||
output reg sound_active
|
||||
);
|
||||
|
||||
reg [7:0] q;
|
||||
reg [7:0] cw;
|
||||
reg [15:0] counter;
|
||||
reg [15:0] ld_count;
|
||||
reg [7:0] load;
|
||||
reg pause;
|
||||
reg stop1;
|
||||
|
||||
|
||||
assign dout = q;
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
reg [15:0] l_counter;
|
||||
reg msbw, msbr; // according to Siemens doc, read and write have indepenent msb flag.
|
||||
reg latched;
|
||||
|
||||
reg old_wr_cw, old_wr, old_rd;
|
||||
old_wr_cw <= wr_cw;
|
||||
old_wr <= wr;
|
||||
old_rd <= rd;
|
||||
|
||||
if(!old_wr_cw && wr_cw) begin
|
||||
msbw <=0;
|
||||
msbr <=0;
|
||||
if(!din[5:4]) begin
|
||||
if(!latched) begin
|
||||
latched <=1;
|
||||
l_counter <= counter;
|
||||
end
|
||||
end else begin
|
||||
cw <= din;
|
||||
latched <=0;
|
||||
stop1 <=1;
|
||||
pause<=1;
|
||||
end
|
||||
end
|
||||
|
||||
if(!old_wr && wr) begin
|
||||
case(cw[5:4])
|
||||
1: begin // high speed mode
|
||||
ld_count[7:0] <= check(din);
|
||||
ld_count[15:8] <= 0;
|
||||
stop1 <=0;
|
||||
load <=load + 1'd1;
|
||||
pause <=0;
|
||||
end
|
||||
2: begin // low precision mode
|
||||
ld_count[7:0] <= 0;
|
||||
ld_count[15:8] <= check(din);
|
||||
stop1 <=0;
|
||||
load <=load + 1'd1;
|
||||
pause <=0;
|
||||
end
|
||||
default: begin // full mode
|
||||
if(msbw) ld_count[15:8] <= check(din);
|
||||
else ld_count[7:0] <= check(din);
|
||||
msbw <= ~msbw;
|
||||
pause <= ~msbw;
|
||||
if(msbw) begin
|
||||
stop1 <=0;
|
||||
load <=load + 1'd1;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
if(!old_rd && rd) begin
|
||||
casex({latched, msbr, cw[5:4]})
|
||||
4'b0X01: q <=counter[7:0];
|
||||
4'b0X10: q <=counter[15:8];
|
||||
4'b0011: q <=counter[7:0];
|
||||
4'b0111: q <=counter[15:8];
|
||||
4'b1X01: begin q <=l_counter[7:0]; latched <=0; end
|
||||
4'b1X10: begin q <=l_counter[15:8]; latched <=0; end
|
||||
4'b1011: q <=l_counter[7:0];
|
||||
4'b1111: begin q <=l_counter[15:8]; latched <=0; end
|
||||
endcase
|
||||
msbr <= ~msbr;
|
||||
end
|
||||
|
||||
if(!rd || reset) q <= 255;
|
||||
|
||||
if(reset) begin
|
||||
stop1 <=1;
|
||||
ld_count <=0;
|
||||
cw <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
function [15:0] minus1;
|
||||
input [15:0] value;
|
||||
begin
|
||||
if(!cw[0]) minus1 = value-1'd1;
|
||||
else begin
|
||||
minus1 = value;
|
||||
if(!minus1[3:0]) begin
|
||||
minus1[3:0] = 9;
|
||||
if(!minus1[7:4]) begin
|
||||
minus1[7:4] = 9;
|
||||
if(!minus1[11:8]) begin
|
||||
minus1[11:8] = 9;
|
||||
if(!minus1[15:12]) begin
|
||||
minus1[15:12] = 9;
|
||||
end else minus1[15:12] = minus1[15:12]-1'd1;
|
||||
end else minus1[11:8] = minus1[11:8]-1'd1;
|
||||
end else minus1[7:4] = minus1[7:4]-1'd1;
|
||||
end else minus1[3:0] = minus1[3:0]-1'd1;
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
||||
function [7:0] check;
|
||||
input [7:0] value;
|
||||
begin
|
||||
if(!cw[0]) check = value;
|
||||
else begin
|
||||
check[3:0] = (value[3:0]>9) ? 4'd9 : value[3:0];
|
||||
check[7:4] = (value[7:4]>9) ? 4'd9 : value[7:4];
|
||||
end;
|
||||
end
|
||||
endfunction
|
||||
|
||||
reg stop2;
|
||||
wire stop = stop1 | stop2;
|
||||
|
||||
//
|
||||
// With bugs implemented:
|
||||
//
|
||||
// M0,M1,M4,M5 - counter doesn't stop at the end but wrap around instead.
|
||||
//
|
||||
// M1,M5 - setting of Control Word doesn't reset counter.
|
||||
// Counter continue to count old value after ccounter register is set.
|
||||
//
|
||||
always @(posedge clk_sys) begin
|
||||
reg [7:0] old_load;
|
||||
reg old_gate;
|
||||
reg start, count_en, m3state;
|
||||
reg [7:0] stop_delay;
|
||||
reg old_clk;
|
||||
|
||||
// cannot treat it as clock enable because timer clock
|
||||
// can be fed from output of other timer
|
||||
old_clk <= clk_timer;
|
||||
if(old_clk & ~clk_timer) begin
|
||||
stop2 <= stop1;
|
||||
|
||||
old_load <= load;
|
||||
old_gate <= gate;
|
||||
start <= stop;
|
||||
|
||||
// Assume sound is generated by mode 3 and mode 0(DAC emulation).
|
||||
sound_active <= (!cw[3:1] || (cw[2:1] == 2'b11)) && !stop;
|
||||
|
||||
casex(cw[3:1])
|
||||
3'b000: if(stop) begin out <=0; count_en <=0; end
|
||||
else begin
|
||||
if(start || (old_load != load)) begin
|
||||
counter <= ld_count;
|
||||
out <=0;
|
||||
count_en <=1;
|
||||
end else if(!pause && gate) begin
|
||||
counter <= minus1(counter);
|
||||
if(counter == 1) begin
|
||||
out <=1;
|
||||
count_en <=0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
3'b001: if(stop) begin out <=1; count_en <=0; end
|
||||
else begin
|
||||
if(!old_gate & gate) begin
|
||||
counter <= ld_count;
|
||||
out <=0;
|
||||
count_en <=1;
|
||||
end else begin
|
||||
counter <= minus1(counter);
|
||||
if((counter == 1) && count_en) begin
|
||||
out <=1;
|
||||
count_en <=0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
3'bX10: if(stop || !gate) out <=1;
|
||||
else begin
|
||||
if(start || (!old_gate & gate) || (counter <= 1)) begin
|
||||
counter <=ld_count;
|
||||
out <=1;
|
||||
end else begin
|
||||
counter <= minus1(counter);
|
||||
if(counter == 2) out <=0;
|
||||
end
|
||||
end
|
||||
|
||||
3'bX11: if(stop || !gate) begin out <=1; m3state <=1; end
|
||||
else begin
|
||||
if(start || (!old_gate & gate) || (counter <= 2)) begin
|
||||
counter <=ld_count;
|
||||
out <= m3state;
|
||||
m3state <= ~m3state;
|
||||
end else begin
|
||||
counter <= !counter[0] ? minus1(minus1(counter)) : out ? minus1(counter) : minus1(minus1(minus1(counter)));
|
||||
end
|
||||
end
|
||||
|
||||
3'b100: if(stop) begin out <=1; count_en <=0; end
|
||||
else begin
|
||||
out <=1;
|
||||
if(start) begin
|
||||
counter <=ld_count;
|
||||
count_en <=1;
|
||||
end else if(gate) begin
|
||||
counter <= minus1(counter);
|
||||
if((counter == 1) && count_en) begin
|
||||
out <=0;
|
||||
count_en <=0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
3'b101: if(stop) begin out <=1; count_en <=0; end
|
||||
else begin
|
||||
out <=1;
|
||||
if(!old_gate & gate) begin
|
||||
counter <=ld_count;
|
||||
out <=1;
|
||||
count_en <=1;
|
||||
end else begin
|
||||
counter <= minus1(counter);
|
||||
if((counter == 1) && count_en) begin
|
||||
out <=0;
|
||||
count_en <=0;
|
||||
end
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
225
common/IO/A6532.vhd
Normal file
225
common/IO/A6532.vhd
Normal file
@@ -0,0 +1,225 @@
|
||||
-- A6532 RAM-I/O-Timer (RIOT)
|
||||
-- Copyright 2006, 2010 Retromaster
|
||||
--
|
||||
-- This file is part of A2601.
|
||||
--
|
||||
-- A2601 is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License,
|
||||
-- or any later version.
|
||||
--
|
||||
-- A2601 is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with A2601. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity ramx8 is
|
||||
generic(addr_width : integer := 7);
|
||||
port(clk: in std_logic;
|
||||
r: in std_logic;
|
||||
d_in: in std_logic_vector(7 downto 0);
|
||||
d_out: out std_logic_vector(7 downto 0);
|
||||
a: in std_logic_vector(addr_width - 1 downto 0));
|
||||
end ramx8;
|
||||
|
||||
architecture arch of ramx8 is
|
||||
type ram_type is array (0 to 2**addr_width - 1) of
|
||||
std_logic_vector(7 downto 0);
|
||||
signal ram: ram_type;
|
||||
begin
|
||||
|
||||
process (clk, r, a)
|
||||
begin
|
||||
if (clk'event and clk = '1') then
|
||||
if (r = '1') then
|
||||
d_out <= ram(to_integer(unsigned(a)));
|
||||
else
|
||||
ram(to_integer(unsigned(a))) <= d_in;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end arch;
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_arith.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity A6532 is
|
||||
port(clk: in std_logic;
|
||||
ph2_en: in std_logic;
|
||||
r: in std_logic;
|
||||
rs: in std_logic;
|
||||
cs: in std_logic;
|
||||
irq: out std_logic;
|
||||
d: inout std_logic_vector(7 downto 0) := "ZZZZZZZZ";
|
||||
pa: inout std_logic_vector(7 downto 0);
|
||||
pb: inout std_logic_vector(7 downto 0);
|
||||
pa7: in std_logic;
|
||||
a: in std_logic_vector(6 downto 0));
|
||||
end A6532;
|
||||
|
||||
architecture arch of A6532 is
|
||||
|
||||
signal pa_reg: std_logic_vector(7 downto 0) := "00000000";
|
||||
signal pb_reg: std_logic_vector(7 downto 0) := "00000000";
|
||||
signal pa_ddr: std_logic_vector(7 downto 0) := "00000000";
|
||||
signal pb_ddr: std_logic_vector(7 downto 0) := "00000000";
|
||||
signal pa_in: std_logic_vector(7 downto 0);
|
||||
signal pb_in: std_logic_vector(7 downto 0);
|
||||
|
||||
signal timer: std_logic_vector(7 downto 0) := "00000000";
|
||||
signal timer_write: std_logic;
|
||||
signal timer_read: std_logic;
|
||||
signal timer_intr: std_logic := '0';
|
||||
signal timer_intvl: std_logic_vector(1 downto 0) := "11";
|
||||
signal timer_dvdr: std_logic_vector(10 downto 0) := "00000000001";
|
||||
signal timer_inc: std_logic;
|
||||
signal timer_irq_en: std_logic := '0';
|
||||
|
||||
signal edge_pol: std_logic := '0';
|
||||
signal edge_irq_en: std_logic := '0';
|
||||
signal edge_intr_lo: std_logic := '0';
|
||||
signal edge_intr_hi: std_logic := '0';
|
||||
signal edge_intr: std_logic;
|
||||
|
||||
signal intr_read: std_logic;
|
||||
|
||||
signal ram_d_out: std_logic_vector(7 downto 0);
|
||||
signal ram_r: std_logic;
|
||||
|
||||
begin
|
||||
|
||||
io: for i in 0 to 7 generate
|
||||
-- TEMPORARY FIX
|
||||
pa(i) <= pa_reg(i) when pa_ddr(i) = '1' else 'Z';
|
||||
pb(i) <= pb_reg(i) when pb_ddr(i) = '1' else 'Z';
|
||||
--pa(i) <= 'Z';
|
||||
--pb(i) <= 'Z';
|
||||
pa_in(i) <= pa(i);
|
||||
pb_in(i) <= pb(i) when pb_ddr(i) = '0' else pb_reg(i);
|
||||
end generate;
|
||||
|
||||
ram: work.ramx8 port map(clk, ram_r, d, ram_d_out, a);
|
||||
|
||||
ram_r <= (not rs and r) or rs or not cs;
|
||||
|
||||
timer_write <= (not r) and rs and a(2) and a(4) and cs;
|
||||
timer_read <= r and rs and a(2) and (not a(0)) and cs;
|
||||
intr_read <= r and rs and a(0) and a(2) and cs;
|
||||
|
||||
irq <= not ((timer_intr and timer_irq_en) or (edge_intr and edge_irq_en));
|
||||
edge_intr <= edge_intr_lo when edge_pol = '0' else edge_intr_hi;
|
||||
|
||||
process(clk, ph2_en, cs, r, rs, a, ram_d_out, pa_in, pa_ddr, pb_in, pb_ddr, timer, timer_intr, edge_intr)
|
||||
begin
|
||||
if r = '1' then
|
||||
if (cs = '0') then
|
||||
d <= "ZZZZZZZZ";
|
||||
elsif rs = '0' then
|
||||
d <= ram_d_out;
|
||||
elsif a(2) = '0' then
|
||||
case a(1 downto 0) is
|
||||
when "00" =>
|
||||
d <= pa_in;
|
||||
when "01" =>
|
||||
d <= pa_ddr;
|
||||
when "10" =>
|
||||
d <= pb_in;
|
||||
when "11" =>
|
||||
d <= pb_ddr;
|
||||
when others =>
|
||||
null;
|
||||
end case;
|
||||
elsif a(0) = '0' then
|
||||
d <= timer;
|
||||
elsif a(0) = '1' then
|
||||
d <= timer_intr & edge_intr & "000000";
|
||||
else
|
||||
d <= "--------";
|
||||
end if;
|
||||
else
|
||||
d <= "ZZZZZZZZ";
|
||||
if (clk'event and clk = '1' and cs = '1' and ph2_en = '1') then
|
||||
if (rs = '1') then
|
||||
if a(2) = '0' then
|
||||
case a(1 downto 0) is
|
||||
when "00" =>
|
||||
--pa_reg <= d;
|
||||
when "01" =>
|
||||
pa_ddr <= d;
|
||||
when "10" =>
|
||||
pb_reg <= d;
|
||||
when "11" =>
|
||||
pb_ddr <= d;
|
||||
when others =>
|
||||
null;
|
||||
end case;
|
||||
elsif a(4) = '0' then
|
||||
edge_pol <= a(0);
|
||||
edge_irq_en <= a(1);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process(pa7, intr_read)
|
||||
begin
|
||||
if (intr_read = '1') then
|
||||
edge_intr_lo <= '0';
|
||||
elsif (pa7'event and pa7 = '1') then
|
||||
edge_intr_lo <= '1';
|
||||
end if;
|
||||
|
||||
if (intr_read = '1') then
|
||||
edge_intr_hi <= '0';
|
||||
elsif (pa7'event and pa7 = '0') then
|
||||
edge_intr_hi <= '1';
|
||||
end if;
|
||||
end process;
|
||||
|
||||
with timer_intvl select timer_inc <=
|
||||
timer_dvdr(0) when "00",
|
||||
timer_dvdr(3) when "01",
|
||||
timer_dvdr(6) when "10",
|
||||
timer_dvdr(10) when "11",
|
||||
'-' when others;
|
||||
|
||||
process(clk, ph2_en)
|
||||
begin
|
||||
if (clk'event and clk = '1' and ph2_en = '1') then
|
||||
if (timer_inc = '1') then
|
||||
timer_dvdr <= "00000000001";
|
||||
else
|
||||
timer_dvdr <= timer_dvdr + 1;
|
||||
end if;
|
||||
|
||||
if (timer_write = '1') then
|
||||
timer <= d - 1;
|
||||
timer_intvl <= a(1 downto 0);
|
||||
timer_irq_en <= a(3);
|
||||
timer_dvdr <= "00000000001";
|
||||
elsif (timer_intr = '0') then
|
||||
timer <= timer - timer_inc;
|
||||
elsif (not (timer = X"00")) then
|
||||
timer <= timer - 1;
|
||||
end if;
|
||||
|
||||
if (timer = X"00" and timer_inc = '1' and timer_intr = '0' and timer_write = '0') then
|
||||
timer_intr <= '1';
|
||||
elsif (timer_read = '1' or timer_write = '1') then
|
||||
timer_intr <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end arch;
|
||||
512
common/Sound/JT49/filter/firjt49.hex
Normal file
512
common/Sound/JT49/filter/firjt49.hex
Normal file
@@ -0,0 +1,512 @@
|
||||
FFF4
|
||||
FFF8
|
||||
FFFE
|
||||
0004
|
||||
000B
|
||||
0010
|
||||
0012
|
||||
0010
|
||||
000A
|
||||
0001
|
||||
FFF5
|
||||
FFE9
|
||||
FFE0
|
||||
FFDD
|
||||
FFE2
|
||||
FFF0
|
||||
0004
|
||||
001C
|
||||
0032
|
||||
0040
|
||||
0041
|
||||
0033
|
||||
0015
|
||||
FFED
|
||||
FFC2
|
||||
FF9E
|
||||
FF8C
|
||||
FF91
|
||||
FFB2
|
||||
FFEC
|
||||
0033
|
||||
007A
|
||||
00B0
|
||||
00C5
|
||||
00AE
|
||||
006B
|
||||
0004
|
||||
FF8D
|
||||
FF1E
|
||||
FED2
|
||||
FEC2
|
||||
FEFA
|
||||
FF79
|
||||
002A
|
||||
00EF
|
||||
019B
|
||||
0204
|
||||
0205
|
||||
018C
|
||||
009F
|
||||
FF5E
|
||||
FE03
|
||||
FCD7
|
||||
FC29
|
||||
FC3F
|
||||
FD48
|
||||
FF51
|
||||
0240
|
||||
05D2
|
||||
09A8
|
||||
0D4E
|
||||
1050
|
||||
124B
|
||||
12FB
|
||||
124B
|
||||
1050
|
||||
0D4E
|
||||
09A8
|
||||
05D2
|
||||
0240
|
||||
FF51
|
||||
FD48
|
||||
FC3F
|
||||
FC29
|
||||
FCD7
|
||||
FE03
|
||||
FF5E
|
||||
009F
|
||||
018C
|
||||
0205
|
||||
0204
|
||||
019B
|
||||
00EF
|
||||
002A
|
||||
FF79
|
||||
FEFA
|
||||
FEC2
|
||||
FED2
|
||||
FF1E
|
||||
FF8D
|
||||
0004
|
||||
006B
|
||||
00AE
|
||||
00C5
|
||||
00B0
|
||||
007A
|
||||
0033
|
||||
FFEC
|
||||
FFB2
|
||||
FF91
|
||||
FF8C
|
||||
FF9E
|
||||
FFC2
|
||||
FFED
|
||||
0015
|
||||
0033
|
||||
0041
|
||||
0040
|
||||
0032
|
||||
001C
|
||||
0004
|
||||
FFF0
|
||||
FFE2
|
||||
FFDD
|
||||
FFE0
|
||||
FFE9
|
||||
FFF5
|
||||
0001
|
||||
000A
|
||||
0010
|
||||
0012
|
||||
0010
|
||||
000B
|
||||
0004
|
||||
FFFE
|
||||
FFF8
|
||||
FFF4
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
0000
|
||||
3
common/Sound/JT49/filter/jt49_filters.qip
Normal file
3
common/Sound/JT49/filter/jt49_filters.qip
Normal file
@@ -0,0 +1,3 @@
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "jtframe_dcrm.v"]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "jtframe_fir.v"]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "jtframe_jt49_filters.v"]
|
||||
69
common/Sound/JT49/filter/jtframe_dcrm.v
Normal file
69
common/Sound/JT49/filter/jtframe_dcrm.v
Normal file
@@ -0,0 +1,69 @@
|
||||
/* This file is part of JT49.
|
||||
|
||||
JT49 is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
JT49 is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with JT49. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 25-11-2020
|
||||
|
||||
*/
|
||||
|
||||
// This is pretty much a copy of jt49_dcrm2
|
||||
|
||||
// DC removal filter
|
||||
// input is unsigned
|
||||
// output is signed
|
||||
|
||||
module jtframe_dcrm #(parameter
|
||||
SW = 8,
|
||||
SIGNED_INPUT = 0
|
||||
)(
|
||||
input rst,
|
||||
input clk,
|
||||
input sample,
|
||||
input [SW-1:0] din,
|
||||
output signed [SW-1:0] dout
|
||||
);
|
||||
|
||||
localparam DW=10; // width of the decimal portion
|
||||
|
||||
reg signed [SW+DW:0] integ, exact, error;
|
||||
//reg signed [2*(9+DW)-1:0] mult;
|
||||
// wire signed [SW+DW:0] plus1 = { {SW+DW{1'b0}},1'b1};
|
||||
reg signed [SW:0] pre_dout;
|
||||
// reg signed [SW+DW:0] dout_ext;
|
||||
reg signed [SW:0] q;
|
||||
|
||||
always @(*) begin
|
||||
exact = integ+error;
|
||||
q = exact[SW+DW:DW];
|
||||
pre_dout = { SIGNED_INPUT ? din[SW-1] : 1'b0, din } - q;
|
||||
//dout_ext = { pre_dout, {DW{1'b0}} };
|
||||
//mult = dout_ext;
|
||||
end
|
||||
|
||||
assign dout = pre_dout[SW-1:0];
|
||||
|
||||
always @(posedge clk)
|
||||
if( rst ) begin
|
||||
integ <= {SW+DW+1{1'b0}};
|
||||
error <= {SW+DW+1{1'b0}};
|
||||
end else if( sample ) begin
|
||||
/* verilator lint_off WIDTH */
|
||||
integ <= integ + pre_dout; //mult[SW+DW*2:DW];
|
||||
/* verilator lint_on WIDTH */
|
||||
error <= exact-{q, {DW{1'b0}}};
|
||||
end
|
||||
|
||||
endmodule
|
||||
106
common/Sound/JT49/filter/jtframe_fir.v
Normal file
106
common/Sound/JT49/filter/jtframe_fir.v
Normal file
@@ -0,0 +1,106 @@
|
||||
/* This file is part of JTFRAME.
|
||||
JTFRAME program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
JTFRAME program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with JTFRAME. If not, see <http://www.gnu.org/licenses/>.
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 22-11-2020
|
||||
*/
|
||||
|
||||
// Generic FIR filter for stereo signals
|
||||
// Max 127 coefficients
|
||||
|
||||
// Parameters
|
||||
// KMAX = number of coefficients (8 bit value)
|
||||
// COEFFS = hex file with filter coefficients
|
||||
|
||||
module jtframe_fir(
|
||||
input rst,
|
||||
input clk,
|
||||
input sample,
|
||||
input signed [15:0] l_in,
|
||||
input signed [15:0] r_in,
|
||||
output reg signed [15:0] l_out,
|
||||
output reg signed [15:0] r_out
|
||||
);
|
||||
|
||||
parameter [6:0] KMAX = 7'd68;
|
||||
parameter COEFFS = "filter.hex";
|
||||
|
||||
reg signed [15:0] ram[0:511]; // dual port RAM
|
||||
reg [6:0] pt_wr, pt_rd, cnt;
|
||||
reg st;
|
||||
reg signed [35:0] acc_l, acc_r;
|
||||
reg signed [15:0] coeff;
|
||||
reg signed [31:0] p_l, p_r;
|
||||
|
||||
function signed [35:0] ext;
|
||||
input signed [31:0] p;
|
||||
ext = { {4{p[31]}}, p };
|
||||
endfunction
|
||||
|
||||
function [6:0] loop_inc;
|
||||
input [6:0] s;
|
||||
loop_inc = s == KMAX-7'd1 ? 7'd0 : s+7'd1;
|
||||
endfunction
|
||||
|
||||
function signed [15:0] sat;
|
||||
input [35:0] a;
|
||||
sat = a[35:30] == {6{a[29]}} ? a[29:14] : { a[35], {15{~a[35]}} };
|
||||
endfunction
|
||||
|
||||
always@(posedge clk, posedge rst) begin
|
||||
if( rst ) begin
|
||||
l_out <= 16'd0;
|
||||
r_out <= 16'd0;
|
||||
pt_rd <= 7'd0;
|
||||
pt_wr <= 7'd0;
|
||||
cnt <= 7'd0;
|
||||
acc_l <= 36'd0;
|
||||
acc_r <= 36'd0;
|
||||
p_l <= 32'd0;
|
||||
p_r <= 32'd0;
|
||||
end else begin
|
||||
if( sample ) begin
|
||||
pt_rd <= pt_wr;
|
||||
cnt <= 0;
|
||||
ram[ { 2'd1, pt_wr } ] <= l_in;
|
||||
ram[ { 2'd2, pt_wr } ] <= r_in;
|
||||
pt_wr <= loop_inc( pt_wr );
|
||||
acc_l <= 36'd0;
|
||||
acc_r <= 36'd0;
|
||||
p_l <= 32'd0;
|
||||
p_r <= 32'd0;
|
||||
st <= 0;
|
||||
end else begin
|
||||
if( cnt < KMAX ) begin
|
||||
st <= ~st;
|
||||
if( st == 0 ) begin
|
||||
coeff <= ram[ {2'd0, cnt } ];
|
||||
end else begin
|
||||
p_l <= ram[ {2'd1, pt_rd } ] * coeff;
|
||||
p_r <= ram[ {2'd2, pt_rd } ] * coeff;
|
||||
acc_l <= acc_l + ext(p_l);
|
||||
acc_r <= acc_r + ext(p_r);
|
||||
cnt <= cnt+7'd1;
|
||||
pt_rd <= loop_inc( pt_rd );
|
||||
end
|
||||
end else begin
|
||||
l_out <= sat(acc_l);
|
||||
r_out <= sat(acc_r);
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
initial begin
|
||||
$readmemh( COEFFS, ram );
|
||||
end
|
||||
endmodule
|
||||
60
common/Sound/JT49/filter/jtframe_jt49_filters.v
Normal file
60
common/Sound/JT49/filter/jtframe_jt49_filters.v
Normal file
@@ -0,0 +1,60 @@
|
||||
/* This file is part of JTFRAME.
|
||||
JTFRAME program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
JTFRAME program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with JTFRAME. If not, see <http://www.gnu.org/licenses/>.
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 25-11-2020
|
||||
*/
|
||||
|
||||
module jtframe_jt49_filters(
|
||||
input rst,
|
||||
input clk,
|
||||
input [ 9:0] din0,
|
||||
input [ 9:0] din1,
|
||||
input [ 9:0] din2,
|
||||
input sample,
|
||||
output signed [15:0] dout
|
||||
);
|
||||
|
||||
localparam W=11,WD=16-W;
|
||||
|
||||
wire signed [W-1:0] dcrm_snd;
|
||||
reg [W-1:0] base_snd;
|
||||
wire signed [ 15:0] dcrm16 = { dcrm_snd, dcrm_snd[W-2:W-WD-1] };
|
||||
//assign dout = dcrm16;
|
||||
|
||||
always @(posedge clk, posedge rst ) begin
|
||||
if( rst ) begin
|
||||
base_snd <= {W{1'd0}};
|
||||
end else if(sample) begin
|
||||
base_snd <= { {W-10{1'b0}}, din0} + { {W-10{1'b0}}, din1} + { {W-10{1'b0}}, din2};
|
||||
end
|
||||
end
|
||||
|
||||
jtframe_dcrm #(.SW(W)) u_dcrm(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.sample ( sample ),
|
||||
.din ( base_snd ),
|
||||
.dout ( dcrm_snd )
|
||||
);
|
||||
|
||||
jtframe_fir #(.KMAX(126),.COEFFS("firjt49.hex")) u_fir(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.sample ( sample ),
|
||||
.l_in ( dcrm16 ),
|
||||
.r_in ( 16'd0 ),
|
||||
.l_out ( dout ),
|
||||
.r_out ( )
|
||||
);
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user