📄 apbuart.vhd
字号:
v.rirqen := apbi.pwdata(2); v.txen := apbi.pwdata(1); v.rxen := apbi.pwdata(0); when "000011" => v.brate := apbi.pwdata(11 downto 0); v.scaler := apbi.pwdata(11 downto 0); when others => if flow /= 0 then v.rhold(conv_integer(r.rwaddr)) := apbi.pwdata(7 downto 0); if fifosize = 1 then v.rcnt(0) := '1'; else v.rwaddr := r.rwaddr + 1; v.rcnt := v.rcnt + 1; end if; end if; end case; end if;-- tx clock txclk := r.txclk + 1; if r.tick = '1' then v.txclk := txclk; v.txtick := r.txclk(2) and not txclk(2); end if;-- rx clock rxclk := r.rxclk + 1; if r.tick = '1' then v.rxclk := rxclk; v.rxtick := r.rxclk(2) and not rxclk(2); end if;-- filter rx data-- v.rxf := r.rxf(6 downto 0) & uarti.rxd;-- if ((r.rxf(7) & r.rxf(7) & r.rxf(7) & r.rxf(7) & r.rxf(7) & r.rxf(7) &-- r.rxf(7)) = r.rxf(6 downto 0))-- then v.rxdb(0) := r.rxf(7); end if; v.rxf(1 downto 0) := r.rxf(0) & uarti.rxd; -- meta-stability filter if r.tick = '1' then v.rxf(4 downto 2) := r.rxf(3 downto 1); end if; v.rxdb(0) := (r.rxf(4) and r.rxf(3)) or (r.rxf(4) and r.rxf(2)) or (r.rxf(3) and r.rxf(2));-- loop-back mode if r.loopb = '1' then v.rxdb(0) := r.tshift(0); ctsn := dready and not r.rsempty; elsif (flow = 1) then ctsn := r.ctsn(1); else ctsn := '0'; end if; rxd := r.rxdb(0);-- transmitter operation case r.txstate is when idle => -- idle state if (r.txtick = '1') then v.tsempty := '1'; end if; if ((r.txen and (not thempty) and r.txtick) and ((not ctsn) or not r.flow)) = '1' then v.txstate := data; v.tpar := r.parsel; v.tsempty := '0'; v.txclk := "00" & r.tick; v.txtick := '0'; v.tshift := "10" & r.thold(conv_integer(r.traddr)) & '0'; if fifosize = 1 then v.irq := r.irq or r.tirqen; v.tcnt(0) := '0'; else v.traddr := r.traddr + 1; v.tcnt := r.tcnt - 1; end if; end if; when data => -- transmit data frame if r.txtick = '1' then v.tpar := r.tpar xor r.tshift(1); v.tshift := '1' & r.tshift(10 downto 1); if r.tshift(10 downto 1) = "1111111110" then if r.paren = '1' then v.tshift(0) := r.tpar; v.txstate := cparity; else v.tshift(0) := '1'; v.txstate := stopbit; end if; end if; end if; when cparity => -- transmit parity bit if r.txtick = '1' then v.tshift := '1' & r.tshift(10 downto 1); v.txstate := stopbit; end if; when stopbit => -- transmit stop bit if r.txtick = '1' then v.tshift := '1' & r.tshift(10 downto 1); v.txstate := idle; end if; end case;-- writing of tx data register must be done after tx fsm to get correct-- operation of thempty flag if (apbi.psel(pindex) and apbi.penable and apbi.pwrite) = '1' then case paddr(3 downto 2) is when "00" => if fifosize = 1 then v.thold(0) := apbi.pwdata(7 downto 0); v.tcnt(0) := '1'; else v.thold(conv_integer(r.twaddr)) := apbi.pwdata(7 downto 0); if not (tfull = '1') then v.twaddr := r.twaddr + 1; v.tcnt := v.tcnt + 1; end if; end if;--pragma translate_off if CONSOLE = 1 then if first then L1:= new string'(""); first := false; end if; --' if apbi.penable'event then --' CH := character'val(conv_integer(apbi.pwdata(7 downto 0))); --' if CH = CR then std.textio.writeline(OUTPUT, L1); elsif CH /= LF then std.textio.write(L1,CH); end if; pt := now; end if; end if;--pragma translate_on when others => null; end case; end if;-- receiver operation case r.rxstate is when idle => -- wait for start bit if ((r.rsempty = '0') and not (rfull = '1')) then v.rsempty := '1'; v.rhold(conv_integer(r.rwaddr)) := r.rshift; if fifosize = 1 then v.rcnt(0) := '1'; else v.rwaddr := r.rwaddr + 1; v.rcnt := v.rcnt + 1; end if; end if; if (r.rxen and r.rxdb(1) and (not rxd)) = '1' then v.rxstate := startbit; v.rshift := (others => '1'); v.rxclk := "100"; if v.rsempty = '0' then v.ovf := '1'; end if; v.rsempty := '0'; v.rxtick := '0'; end if; when startbit => -- check validity of start bit if r.rxtick = '1' then if rxd = '0' then v.rshift := rxd & r.rshift(7 downto 1); v.rxstate := data; v.dpar := r.parsel; else v.rxstate := idle; end if; end if; when data => -- receive data frame if r.rxtick = '1' then v.dpar := r.dpar xor rxd; v.rshift := rxd & r.rshift(7 downto 1); if r.rshift(0) = '0' then if r.paren = '1' then v.rxstate := cparity; else v.rxstate := stopbit; v.dpar := '0'; end if; end if; end if; when cparity => -- receive parity bit if r.rxtick = '1' then v.dpar := r.dpar xor rxd; v.rxstate := stopbit; end if; when stopbit => -- receive stop bit if r.rxtick = '1' then v.irq := v.irq or r.rirqen; -- make sure no tx irqs are lost ! if rxd = '1' then v.parerr := r.parerr or r.dpar; v.rsempty := r.dpar; if not (rfull = '1') and (r.dpar = '0') then v.rsempty := '1'; v.rhold(conv_integer(r.rwaddr)) := r.rshift; if fifosize = 1 then v.rcnt(0) := '1'; else v.rwaddr := r.rwaddr + 1; v.rcnt := v.rcnt + 1; end if; end if; else if r.rshift = "00000000" then v.break := '1'; else v.frame := '1'; end if; v.rsempty := '1'; end if; v.rxstate := idle; end if; end case; if r.rxtick = '1' then v.rtsn := (rfull and not r.rsempty) or r.loopb; end if; v.txd := r.tshift(0) or r.loopb; if fifosize /= 1 then if thempty = '0' and v.tcnt = rcntzero then v.irq := v.irq or r.tirqen; end if; v.irq := v.irq or (r.tfifoirqen and r.txen and thalffull); v.irq := v.irq or (r.rfifoirqen and r.rxen and rhalffull); end if;-- reset operation if rst = '0' then v.frame := '0'; v.rsempty := '1'; v.parerr := '0'; v.ovf := '0'; v.break := '0'; v.tsempty := '1'; v.txen := '0'; v.rxen := '0'; v.txstate := idle; v.rxstate := idle; v.tshift(0) := '1'; v.extclken := '0'; v.rtsn := '1'; v.flow := '0'; v.txclk := (others => '0'); v.rxclk := (others => '0'); v.rcnt := (others => '0'); v.tcnt := (others => '0'); v.rwaddr := (others => '0'); v.twaddr := (others => '0'); v.rraddr := (others => '0'); v.traddr := (others => '0'); end if;-- update registers rin <= v;-- drive outputs uarto.txd <= r.txd; uarto.rtsn <= r.rtsn; uarto.scaler <= "000000" & r.scaler; apbo.prdata <= rdata; apbo.pirq <= irq; apbo.pindex <= pindex; end process; apbo.pconfig <= pconfig; regs : process(clk) begin if rising_edge(clk) then r <= rin; end if; end process;-- pragma translate_off bootmsg : report_version generic map ("apbuart" & tost(pindex) & ": Generic UART rev " & tost(REVISION) & ", fifo " & tost(fifosize) & ", irq " & tost(pirq));-- pragma translate_onend;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -