📄 anc_pkt_gen.vhd
字号:
next_state <= S_WAIT;
end case;
end process;
--
-- FSM: outputs
--
-- This block decodes the current state to generate the various outputs of
-- the FSM.
--
process(current_state, calc_udw_parity, send_pkt)
begin
-- Unless specifically assigned in the case statement, all FSM outputs
-- default to the values here..
pkt_rdy_out <= '0';
pmux_sel <= PMUXSEL_DID;
dmux_sel <= DMUXSEL_PGEN;
omux_sel <= OMUXSEL_DATA;
clr_checksum <= '0';
clr_udw_rd_cntr <= '0';
inc_udw_rd_cntr <= '0';
dec_dc <= '0';
pkt_end <= '0';
pkt_in_empty_x <= '0';
ld_out_reg <= '0';
case current_state is
when S_WAIT =>
pkt_in_empty_x <= '1';
omux_sel <= OMUXSEL_ADF0;
ld_out_reg <= '1';
when S_ADF1 =>
omux_sel <= OMUXSEL_ADF1;
pkt_rdy_out <= '1';
if (send_pkt = '1') then
ld_out_reg <= '1';
else
ld_out_reg <= '0';
end if;
when S_ADF2 =>
omux_sel <= OMUXSEL_ADF1;
ld_out_reg <= '1';
clr_checksum <= '1';
when S_DID =>
pmux_sel <= PMUXSEL_DID;
dmux_sel <= DMUXSEL_PGEN;
omux_sel <= OMUXSEL_DATA;
ld_out_reg <= '1';
when S_DBN =>
pmux_sel <= PMUXSEL_DBN;
dmux_sel <= DMUXSEL_PGEN;
omux_sel <= OMUXSEL_DATA;
ld_out_reg <= '1';
clr_udw_rd_cntr <= '1';
when S_DC =>
pmux_sel <= PMUXSEL_DC;
dmux_sel <= DMUXSEL_PGEN;
omux_sel <= OMUXSEL_DATA;
inc_udw_rd_cntr <= '1';
dec_dc <= '1';
ld_out_reg <= '1';
when S_UDW =>
pmux_sel <= PMUXSEL_UDW;
if (calc_udw_parity = '1') then
dmux_sel <= DMUXSEL_PGEN;
else
dmux_sel <= DMUXSEL_UDW;
end if;
omux_sel <= OMUXSEL_DATA;
inc_udw_rd_cntr <= '1';
dec_dc <= '1';
ld_out_reg <= '1';
when S_CHK =>
omux_sel <= OMUXSEL_CHK;
ld_out_reg <= '1';
when S_END =>
pkt_end <= '1';
when S_ABRT =>
omux_sel <= OMUXSEL_ADF0;
ld_out_reg <= '1';
when others =>
end case;
end process;
--
-- pmux
--
-- The pmux selects the input to the parity generator. There are four
-- inputs: DID register, DBN register, DC register, and UDW RAM.
--
process(pmux_sel, udw, did, dbn, dc)
begin
case pmux_sel is
when PMUXSEL_DID => pmux <= did;
when PMUXSEL_DBN => pmux <= dbn;
when PMUXSEL_DC => pmux <= dc;
when others => pmux <= udw(7 downto 0);
end case;
end process;
--
-- dmux
--
-- The dmux selects the data word to be sent to the omux and the checksum
-- generator. There are two inputs: the UDW RAM or the output of the pmux
-- via the parity geneator.
--
process(dmux_sel, pword, udw)
begin
if (dmux_sel = DMUXSEL_UDW) then
dmux <= udw;
else
dmux <= pword;
end if;
end process;
--
-- omux
--
-- The omux selects the value to send to the output of the module. There are
-- four inputs: all zeros (first ADF word), all ones (second & third ADF
-- words), the output of the dmux, or the checksum generator.
--
process(omux_sel, dmux, checksum)
begin
case omux_sel is
when OMUXSEL_ADF0 => omux <= ANC_ADF0;
when OMUXSEL_ADF1 => omux <= ANC_ADF1;
when OMUXSEL_DATA => omux <= dmux;
when others => omux <= (not checksum(8) & checksum);
end case;
end process;
--
-- parity bit generation
--
-- This code calculates the parity of bits 7:0 of the data word. The parity
-- bit is inserted at bit 8 of the data word and the inverse of the parity
-- bit is inserted at bit 9.
--
parity <= pmux(7) xor pmux(6) xor pmux(5) xor pmux(4) xor pmux(3) xor
pmux(2) xor pmux(1) xor pmux(0);
pword <= (not parity & parity & pmux(7 downto 0));
--
-- checksum calculator
--
-- This code generates a checksum for the ANC packet. The checksum is
-- cleared to zero prior to beginning the checksum calculation by the FSM
-- asserting the clr_checksum signal. The data word is added to the current
-- checksum continuously. The checksum is a 9-bit value and is computed by
-- summing all but the MSB of the data word with the current checksum value
-- and ignoring any carry bits.
--
process(clk,rst)
begin
if (rst = '1') then
checksum <= (others => '0');
elsif (clk'event and clk = '1') then
if (ce = '1') then
if (clr_checksum = '1') then
checksum <= (others => '0');
else
checksum <= std_ulogic_vector(std_logic_vector(checksum) +
std_logic_vector(dmux(8 downto 0)));
end if;
end if;
end if;
end process;
--
-- DID register
--
-- This register holds the DID word for the ANC packet. The DID register
-- loads from the data_in bus when ld_did is asserted. Only eight bits are
-- stored in the DID register. The module generates the correct parity bits
-- for the two MSBs of the DID word when inserted in the ANC packet.
--
process(clk,rst)
begin
if (rst = '1') then
did <= (others => '0');
elsif (clk'event and clk = '1') then
if (ce = '1') then
if (ld_did = '1' and pkt_in_empty_x = '1') then
did <= data_in(7 downto 0);
end if;
end if;
end if;
end process;
--
-- DBN/SDID register
--
-- This register holds the DBN or SDID word for the ANC packet. The DBN
-- register loads from the data_in bus when the ld_dbn signal is asserted.
-- Only eight bits are stored in the register. The module generates the
-- correct parity bits for the two MSBs of the DBN/SDID word when inserted
-- into the ANC packet.
--
process(clk, rst)
begin
if (rst = '1') then
dbn <= (others => '0');
elsif (clk'event and clk = '1') then
if (ce = '1') then
if (ld_dbn = '1' and pkt_in_empty_x = '1') then
dbn <= data_in(7 downto 0);
end if;
end if;
end if;
end process;
--
-- DC register/counter
--
-- This register holds the DC (data count) word for the ANC packet. It loads
-- from the data_in bus when the ld_dc signal is asserted. Only eight bits
-- are stored in the register. The DC register also acts as a down counter
-- as UDW words are output.
--
process(clk,rst)
begin
if (rst = '1') then
dc <= (others => '0');
elsif (clk'event and clk = '1') then
if (ld_dc = '1' and pkt_in_empty_x = '1') then
dc <= data_in(7 downto 0);
elsif (dec_dc = '1') then
dc <= std_ulogic_vector(std_logic_vector(dc) - 1);
end if;
end if;
end process;
dc_eq_0 <= '1' when dc = UBYTE_ZERO else '0';
--
-- UDW RAM
--
-- The UDW RAM holds the user data words. Data is written into the RAM by
-- placing the data on the data_in bus, the address on the udw_wr_adr bus,
-- and asserting the ld_udw signal. All 10-bits of the data_in bus are
-- written to the UDW RAM. However, if the calc_udw_parity signal is
-- asserted as the packet is being generated, the two MSBs of the UDW RAM
-- are ignored and instead, the parity generator is used to generate parity
-- bits for the two MSBs of the UDW.
--
-- Code is given to infer either a block RAM or a single-port distributed
-- RAM. Separate code is given for the distributed RAM so that a single-port
-- RAM will be inferred rather than a larger dual-port distributed RAM. In
-- order to keep the control timing of both cases identical, a register for
-- the read address is inserted for the distributed RAM case. The block RAM
-- case requires a read address register in order to infer the block RAM.
--
----------------------------------------------------------------------------
-- Infer dual-port block RAM
--
-- Uncomment the following code to infer block RAM for the UDW RAM
-- udw_wr_en <= ce and ld_udw and pkt_in_empty_x;
--
-- process(clk)
-- begin
-- if (clk'event and clk = '1') then
-- if (udw_wr_en = '1') then
-- udw_ram(conv_integer(udw_wr_adr)) <= data_in;
-- end if;
-- udw_rd_adr <= udw_rd_cntr;
-- end if;
-- end process;
--
-- udw <= udw_ram(conv_integer(udw_rd_adr));
----------------------------------------------------------------------------
----------------------------------------------------------------------------
-- Infer single-port distributed RAM
udw_wr_en <= ce and ld_udw and pkt_in_empty_x;
udw_adr <= udw_wr_adr when ((ld_udw and pkt_in_empty_x) = '1')
else udw_rd_cntr;
process(clk)
begin
if (clk'event and clk = '1') then
if (udw_wr_en = '1') then
udw_ram(conv_integer(udw_adr)) <= data_in;
end if;
udw <= udw_ram(conv_integer(udw_adr));
end if;
end process;
--------------------------------------------------------------------------------
--
-- UDW read counter
--
-- This eight-bit up counter generates read addresses into the UDW RAM to
-- read out the UDW words in correct order.
--
process(clk, rst)
begin
if (rst = '1') then
udw_rd_cntr <= (others => '0');
elsif (clk'event and clk = '1') then
if (ce = '1') then
if (clr_udw_rd_cntr = '1') then
udw_rd_cntr <= (others => '0');
elsif (inc_udw_rd_cntr = '1') then
udw_rd_cntr <= udw_rd_cntr + 1;
end if;
end if;
end if;
end process;
--
-- anc_out
--
-- This is the output register of the module. It loads from the omux
-- whenever the ld_out_reg signal is asserted.
--
process(clk,rst)
begin
if (rst = '1') then
anc_out <= (others => '0');
elsif (clk'event and clk = '1') then
if (ce = '1') then
if (ld_out_reg = '1') then
anc_out <= omux;
end if;
end if;
end if;
end process;
--
-- pkt_size
--
-- The pkt_size output is set to seven more than the size of they ANC
-- packet's payload (DC word).
--
pkt_size <= std_ulogic_vector(std_logic_vector(('0' & dc)) + 7);
pkt_in_empty <= pkt_in_empty_x;
end synth;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -