📄 hdsdi_framer_mult.vhd
字号:
process(clk, rst)
begin
if rst = '1' then
offset_reg <= (others => '0');
elsif clk'event and clk = '1' then
if ce = '1' then
if trs_detected = '1' and frame_en = '1' then
offset_reg <= offset_val;
end if;
end if;
end if;
end process;
--
-- New start position detector
--
-- A comparison between offset_val and offset_reg determines if
-- the new offset is different than the current one. If there is
-- a mismatch and frame_en is not asserted, then the nsp output
-- will be asserted.
--
new_offset <= '1' when offset_val /= offset_reg else '0';
process(clk, rst)
begin
if rst = '1' then
nsp <= '1';
elsif clk'event and clk = '1' then
if ce = '1' then
if trs_detected = '1' then
nsp <= not frame_en and new_offset;
end if;
end if;
end if;
end process;
--
-- barrel_in: barrel shifter input register
--
-- This register implements a pipeline delay stage so that the
-- barrel shifter's data input matches the delay on the offset
-- input caused by the offset_reg.
--
process(clk, rst)
begin
if rst = '1' then
barrel_in <= (others => '0');
elsif clk'event and clk = '1' then
if ce = '1' then
barrel_in <= (dly_reg(18 downto 0) & dly_reg2);
end if;
end if;
end process;
--
-- Barrel shifter
--
-- The barrel shifter extracts a 20-bit field from the bs_in vector.
-- The bits extracted depend on the value of the offset_reg. The barrel
-- shifter shifts the 39-bit input vector left by 0 to 19 bit positions. If
-- the shift code is zero, then the resulting output is barrel_in[19:0]. On
-- the other extreme, if the shift code is 19, then the resulting output is
-- barrel_in[38:19].
--
-- This version of the barrel shifter is implemented in two levels. The top
-- level shifts the input vector either 0 or 12 bit positions right. The
-- bottom level shifts zero to 11 bit positions right. MULT18X18 blocks are
-- used to implement both levels.
--
--
-- Barrel shifter top level
--
-- This level of the barrel shifter will right shift the input vector either
-- 0 bit positions or 12 bit positions, depending on the sc_top bit.
--
-- Three 18X18 multipliers are used at the top level to implement 2:1 MUXes.
-- Each 18x18 multiplier can be used for 9 2:1 MUXes. A for loop creates an
-- input vector for the top level MUXes. Another for loop picks all the odd
-- outputs from the three MUXes for the 27-bit wide output vector to feed to
-- the next level of the barrel shifter.
--
-- The inputs to the A term of the multipliers are arranged like this:
--
-- BS_TOP_A: 8 20 7 19 6 18 5 17 4 16 3 15 2 14 1 13 0 12
-- BS_TOP_B: 17 29 16 28 15 27 14 26 13 25 12 24 11 23 10 22 9 21
-- BS_TOP_C: 26 38 25 37 24 36 23 35 22 34 21 33 20 32 19 31 18 30
--
-- If the sc_top shift code bit is zero, the a multiplier value of 1 is
-- input to the B term of each multiplier. This results in each input bit
-- going straight out to the corresponding output bit (i.e. bit 1 of the A
-- input appears on bit 1 of the P port.
--
process(barrel_in)
begin
for i in 0 to 26 loop
bs_in(i * 2) <= barrel_in(i + 12);
bs_in(i * 2 + 1) <= barrel_in(i);
end loop;
end process;
bstop_bin <= (1 => sc_top, 0 => not sc_top, others => '0');
BS_TOP_A : MULT18X18
port map (
A => bs_in(17 downto 0),
B => bstop_bin,
P => bstop_a);
BS_TOP_B : MULT18X18
port map (
A => bs_in(35 downto 18),
B => bstop_bin,
P => bstop_b);
BS_TOP_C : MULT18X18
port map (
A => bs_in(53 downto 36),
B => bstop_bin,
P => bstop_c);
process(bstop_a, bstop_b, bstop_c)
begin
for i in 0 to 8 loop
bstop(i) <= bstop_a(i * 2 + 1);
bstop(i + 9) <= bstop_b(i * 2 + 1);
bstop(i + 18) <= bstop_c(i * 2 + 1);
end loop;
end process;
--
-- Bottom level of barrel shifter
--
-- This level of the barrel shifter will shift the output of the top level
-- left 0 to 11 bits. Note, however, that it only needs to shift the vector
-- 7 bits to the left if the top level is doing a 12-bit left shift.
--
-- The bottom level of the barrel shifter is made of another three 18x18
-- multipliers. In this level, each multiplier implements seven 12:1 MUXes.
-- The inputs to A input of the multipliers are connected like this:
--
-- BS_BOT_A: bstop[17:0]
-- BS_BOT_B: bstop[24:7]
-- BS_BOT_C: {barrel_in[31:27], bstop[26:14]}
--
-- BS_BOT_C has its MS 5 bits connected directly to the MS 5 bits from the
-- barrel shifter's input vector rather than from the 2:1 MUXes of the top
-- level. This is because these bits positions are only used when shifting
-- left more than 7 bits which can only occur if the top level is not
-- shifting.
--
bsbot_bin <= ("000000" & sc_bot);
BS_BOT_A : MULT18X18
port map (
A => bstop(17 downto 0),
B => bsbot_bin,
P => bsbot_a);
BS_BOT_B : MULT18X18
port map (
A => bstop(24 downto 7),
B => bsbot_bin,
P => bsbot_b);
bsbotc_ain <= (barrel_in(31 downto 27) & bstop(26 downto 14));
BS_BOT_C : MULT18X18
port map (
A => bsbotc_ain,
B => bsbot_bin,
P => bsbot_c);
barrel_out <= (bsbot_c(16 downto 11) & bsbot_b(17 downto 11) & bsbot_a(17 downto 11));
--
-- Barrel shifter shift code generation
--
-- This logic takes the offset_reg value and produces shift codes for the
-- top and bottom level MUXes of the barrel shifter. sc_bot is 12-bit vector
-- that always has only one bit asserted. The value is dependent upon
-- offset_reg MOD 12, such that if this result is 0, then sc_bot = 2048. If
-- the result is 1, sc_bot = 1024. And so on, until the result is 11 and the
-- shift code is 1. sc_top is 0 for offset_reg values of 11 or less and 1
-- otherwise.
--
process(offset_reg)
begin
case offset_reg is
when "00000" =>
sc_top <= '0';
sc_bot <= "100000000000";
when "00001" =>
sc_top <= '0';
sc_bot <= "010000000000";
when "00010" =>
sc_top <= '0';
sc_bot <= "001000000000";
when "00011" =>
sc_top <= '0';
sc_bot <= "000100000000";
when "00100" =>
sc_top <= '0';
sc_bot <= "000010000000";
when "00101" =>
sc_top <= '0';
sc_bot <= "000001000000";
when "00110" =>
sc_top <= '0';
sc_bot <= "000000100000";
when "00111" =>
sc_top <= '0';
sc_bot <= "000000010000";
when "01000" =>
sc_top <= '0';
sc_bot <= "000000001000";
when "01001" =>
sc_top <= '0';
sc_bot <= "000000000100";
when "01010" =>
sc_top <= '0';
sc_bot <= "000000000010";
when "01011" =>
sc_top <= '0';
sc_bot <= "000000000001";
when "01100" =>
sc_top <= '1';
sc_bot <= "100000000000";
when "01101" =>
sc_top <= '1';
sc_bot <= "010000000000";
when "01110" =>
sc_top <= '1';
sc_bot <= "001000000000";
when "01111" =>
sc_top <= '1';
sc_bot <= "000100000000";
when "10000" =>
sc_top <= '1';
sc_bot <= "000010000000";
when "10001" =>
sc_top <= '1';
sc_bot <= "000001000000";
when "10010" =>
sc_top <= '1';
sc_bot <= "000000100000";
when "10011" =>
sc_top <= '1';
sc_bot <= "000000010000";
when others =>
sc_top <= '0';
sc_bot <= "100000000000";
end case;
end process;
--
-- Output registers
--
process(clk, rst)
begin
if rst = '1' then
c_int <= (others => '0');
y_int <= (others => '0');
elsif clk'event and clk = '1' then
if ce = '1' then
c_int <= barrel_out(9 downto 0);
y_int <= barrel_out(19 downto 10);
end if;
end if;
end process;
c <= c_int;
y <= y_int;
--
-- trs: trs output generation logic
--
-- The trs_out register is a 4-bit shift register which shifts everytime
-- the bit_cntr(0) bit is asserted. The trs output signal is the OR of
-- the four bits in this register so it becomes asserted when the first
-- character of the TRS symbol is output and remains asserted for the
-- following three characters of the TRS symbol.
--
process(clk, rst)
begin
if rst = '1' then
trs_out <= (others => '0');
elsif clk'event and clk = '1' then
if ce = '1' then
trs_out <= (trs_detected & trs_out(3 downto 1));
end if;
end if;
end process;
process(clk, rst)
begin
if rst = '1' then
trs <= '0';
elsif clk'event and clk = '1' then
if ce = '1' then
trs <= trs_out(3) or trs_out(2) or trs_out(1) or trs_out(0);
end if;
end if;
end process;
process(clk, rst)
begin
if rst = '1' then
xyz_int <= '0';
elsif clk'event and clk = '1' then
if ce = '1' then
xyz_int <= trs_out(0);
end if;
end if;
end process;
xyz <= xyz_int;
eav <= xyz_int and y_int(6);
sav <= xyz_int and not y_int(6);
--
-- TRS error detection
--
-- This code examines the protection bits in the XYZ word and asserts the
-- trs_err output if an err is detected.
--
trs_err <= xyz_int and (
(y_int(5) xor y_int(6) xor y_int(7)) or
(y_int(4) xor y_int(8) xor y_int(6)) or
(y_int(3) xor y_int(8) xor y_int(7)) or
(y_int(2) xor y_int(8) xor y_int(7) xor y_int(6)) or
not y_int(9) or y_int(1) or y_int(0));
end synth;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -