📄 onewire_master.vhd
字号:
crcok <= crcok_i;
-------------------------------------------------------------------
-- Register the data_valid signals
-------------------------------------------------------------------
regs: process (clk_1MHz, reset)
begin
if reset = '1' then
data_valid <= '0';
elsif clk_1MHz'event and clk_1MHz = '1' then
data_valid <= databyte_valid; -- the data_valid output connects
-- to the valid signal when
-- getting a byte of data
end if;
end process regs;
-------------------------------------------------------------------
-- Clock generation
-------------------------------------------------------------------
clk_50KHz <= not jc2_q(9); -- use the msb of JC2 to generate
-- 50KHz slow clock
-- use "not" here to generate rising
-- edge at proper position
-------------------------------------------------------------------
-- Several time slot identification signals
-------------------------------------------------------------------
-- Suppose the beginning of each state is time 0.
-- Use combination of JC1 and JC2, we can id any time slot during
-- each state as small as 1 us.
ts_60_to_80us <= jc1_q(1) and (not jc1_q(0));
ts_0_to_10us <= (not jc1_q(0)) and (not jc2_q(9));
ts_0_to_1us <= ts_0_to_10us and (not jc2_q(0)) ;
ts_14_to_15us <= (not jc1_q(0)) and jc2_q(4) and (not jc2_q(3));
-------------------------------------------------------------------
-- ROM Command data bit to transmit (write) to the one wire bus
-- Use SR1 to pick up each bit out of the Command data byte.
-------------------------------------------------------------------
tx_cmd_bit <= ReadROMCmd(0) when sr1_q(0) = '1'
else ReadROMCmd(1) when sr1_q(1) = '1'
else ReadROMCmd(2) when sr1_q(2) = '1'
else ReadROMCmd(3) when sr1_q(3) = '1'
else ReadROMCmd(4) when sr1_q(4) = '1'
else ReadROMCmd(5) when sr1_q(5) = '1'
else ReadROMCmd(6) when sr1_q(6) = '1'
else ReadROMCmd(7) when sr1_q(7) = '1'
else '0';
-------------------------------------------------------------------
-- Bidirectional iobuffer to control the direction of data flow on
-- the one-wire bus
-------------------------------------------------------------------
iobuf_i : iobuf
port map (
T => d_ctrl, -- control signal to switch in/out
IO => dq, -- connect to bidirectional one-wire bus
I => dout, -- data output to the bus
O => din); -- data input from the bus
-------------------------------------------------------------------
-- Shift Register 1
-- Used to count 8 bits in a byte of data
-------------------------------------------------------------------
sr1: SHReg
generic map (
circular => true, -- 8 bits in a row and scroll over
AsynReset=> false,
width => 8)
port map (
reset => sr1_reset, -- synchronous reset
clk => clk_50KHz,
en => sr1_en,
q => sr1_q);
-------------------------------------------------------------------
-- Shift Register 2
-- Used to count 8 bytes stored in the Serial Number Device
-------------------------------------------------------------------
sr2: SHReg
generic map (
circular => false,
AsynReset=> false,
width => 8)
port map (
reset => sr2_reset, -- synchronous reset
clk => clk_50KHz,
en => sr2_en,
q => sr2_q);
-------------------------------------------------------------------
-- Johnson Counter 1
-- This Johnson counter is used to deal with the time slots.
-- It chops one state into small time slots.Each is 20 us long,
-- total 4 slots.
-- The reason to use Johnson Counter is to save register bits.
-- n bits of Johnson counter can count for 2n values.
-- for the shift register, n bits can only count for n values
-- In addition, Johnson counter is fast since only NOT gates
-- are used in this counter.
-- It's driven by the slow clock (20us) in this system.
-------------------------------------------------------------------
jcnt1: JCounter
generic map (
width => 2,
AsynReset=> false)
port map (
reset => jc1_reset, -- synchronous reset
clk => clk_50KHz,
en => vcc,
q => jc1_q);
-------------------------------------------------------------------
-- Johnson Counter 2
-- (1) Use this counter to generate 20 us slow clock.
-- (2) It is also used to divide a period of time into time slots.
-- It counts for small time slot which
-- is 1 us wide, add up to total 20 slots.
-- It should be synchronized with JCount1.
-------------------------------------------------------------------
jcnt2: JCounter
generic map (
width => 10,
AsynReset=> true) -- asynchronous reset
port map (
reset => reset, -- asynchronous reset!
clk => clk_1MHz,
en => vcc,
q => jc2_q);
-------------------------------------------------------------------
-- Bit Register
-- It accumulates 8 bits of data according to the strobes of
-- bitreg_en, and output a byte of data.
-------------------------------------------------------------------
bitreg_i: BitReg
generic map ( numBits => 8)
port map (
clk => clk_1MHz, -- for each bit, use faster clock
reset => reset, -- asynchronous reset !
din => din, -- one bit
en => bitreg_en, -- std_logic_vector(7 downto 0)
dout => data_i); -- a byte
-- This is the enable signal for the BitReg. When a bit of data
-- is ready, the BitReg is enabled to load this bit of data
-- at corresponding bit. For example: bitreg_en = "00001000"
-- means the data bit will be stored into the register bit 3.
-- This enable strobe is asserted only one clock period of 1 us.
-- It's generated from the output of SR1, which is used to
-- count for 8 bits in a byte of data. It is also controlled by
-- the numberbits_valid, which indicates a valid data bit received
-- from the Serial Number Device.
bitreg_en <= sr1_q when (databit_valid='1') else (others=>'0');
-------------------------------------------------------------------
-- Byte Register
-- It accumulates 6 bytes of data (serial number) according to
-- the strobes of bytereg_en, and output the serial number.
-------------------------------------------------------------------
bytereg_i: ByteReg
generic map ( numBytes => 6)
port map (
clk => clk_50KHz, -- for each byte, can use slower clock
reset => reset, -- asynchronous reset !
din => data_i, -- one bit
en => bytereg_en, -- std_logic_vector(5 downto 0)
dout => sn_data); -- 48 bits parallel output
bytereg_en <= sr2_q(6 downto 1);
-- only enables for the 48 bits
-- serial number by bypassing
-- the first byte (family code)
-- and the last byte (crc code)
------------------------------------------------------------------------
-- Check CRC and Generate CRCOK signal
-- Use CRCReg to calculate CRC value
-- Latch crcok result when reach the last state (IDLE state)
--
-- Note: Use generic to turn on or off this CRC check circuit.
-- If CheckCRC is false, this circuit will be removed to save
-- register resources. And CRCOK output will be asserted high as
-- long as all the data are received. So it won't reflect the CRC
-- checking result.
------------------------------------------------------------------------
--
-- If we employ CRC check circuit,
--
crcgen : if CheckCRC = true generate
crcreg_i: CRCReg
generic map (
width => 8,
feedback1 => 4,
feedback2 => 5)
port map (
clk => clk_1MHz, -- for each bit, use faster clock
reset => reset, -- asynchronous reset !
d => din,
en => crcreg_en,
q => crcvalue_i);
-- This enable signal is generated for each data bit when we
-- receive the crc data from the one-wire device. It's 1us pulse.
-- use sr2_q(7) here to exclude the situation when we receive
-- the crc value from the one-wire device.
crcreg_en <= databit_valid and (not sr2_q(7));
-- Assert crcok signal when the last byte of data (crc value) is
-- received and it matches the caculated crc value from the CRCReg
crcokreg: process (clk_1MHz, reset)
begin
if reset = '1' then -- need asynchonous reset
crcok_i <= '0';
elsif clk_1MHz'event and clk_1MHz = '1' then
if sr2_q(7) = '1' and databyte_valid = '1' and data_i = crcvalue_i then
crcok_i <= '1';
end if;
end if;
end process crcokreg;
end generate crcgen;
--
-- If we do not use CRC check circuit,
--
nocrcgen : if CheckCRC = false generate
-- Assert crcok when the all the data has been received
crcokreg: process (clk_1MHz, reset)
begin
if reset = '1' then -- need asynchonous reset
crcok_i <= '0';
elsif clk_1MHz'event and clk_1MHz = '1' then
if sr2_q(7) = '1' and databyte_valid = '1'then
crcok_i <= '1';
end if;
end if;
end process crcokreg;
end generate nocrcgen;
----------------------------------------------------------------------------
-- The Presence Pulse Register
----------------------------------------------------------------------------
ppreg: process(clk_50KHz, reset)
begin
if reset = '1' then
din_pp <= '1';
elsif clk_50KHz'event and clk_50KHz = '1' then
if sr2_q(0) = '1' and thisState = RX_PRE_PLS then
din_pp <= din;
end if;
end if;
end process ppreg;
----------------------------------------------------------------------------
-- The FSM register
----------------------------------------------------------------------------
fsmr: process (clk_50KHz, reset)
begin -- process fsmr
if reset = '1' then -- asynchronous reset !
thisState <= INIT;
elsif clk_50KHz'event and clk_50KHz = '1' then
thisState <= nextState;
end if;
end process fsmr;
------------------------------------------------------------------------
-- State Mux
-- Combinational Logic for the state machine.
--
-- Any action in this state mux is synchronized with the 20 us clock
-- and a few of them are synchronized with the 1us clock.
--
-- The transition of the state will take effect on next
-- rising edge of the clock.
------------------------------------------------------------------------
statemux: process (thisState, din_pp, din, sr1_q, sr2_q,
ts_60_to_80us, ts_0_to_10us, ts_0_to_1us, ts_14_to_15us,
tx_cmd_bit, crcok_i)
begin
-- Default values assigned to these signals
-- Any signal without an assignment in the combinational logic
-- will use these default values.
nextState <= thisState; -- stay at current state by default
sr1_reset <= '1'; -- hold sr1 at reset by default
sr1_en <= '0';
sr2_reset <= '1'; -- hold sr2 at reset by default
sr2_en <= '0';
dout <= '1'; -- data output to the one-wire bus
d_ctrl <= '1'; -- read mode on the one-wire bus by default
databyte_valid <= '0'; -- data enable signal for a byte of data
databit_valid <= '0'; -- data valid strobe for a bit of data
jc1_reset <= '0'; -- hold jc1 at reset by default
-- Case statement as a Mux
case thisState is
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -