串行序列信号发生器、接收器的设计

使用quartus ii,vhdl描述法
完成一个串行序列信号发生器、接收器
一、设计并实现一个串行信号发生器,具体要求如下:

  1. SW7~SW0 作为并行数据输入端,用来设置要产生的序列;
  2. BTN3 为开始键(防抖),按下后产生串行时钟信号(周期为 2 秒,在 LD0
    上显示),并依次将 SW7~SW0 的值发送到串行数据输出端(每 2 秒发送
    1 位),并在 LD7 上显示;
  3. 串行时钟信号和串行数据输出端要满足以下时序关系:
    (1)不发送数据时,串行时钟信号(SCL)和串行数据输出端(SDA)保
    持高电平;
    (2)发送数据时,SCL 为高电平期间,SDA 的数据必须保持稳定,只有
    在 SCL 为低电平期间,数据端的状态才允许变化。
    (3)SCL 为高电平期间,SDA 由高电平向低电平的变化表示起始信号;
    SCL 为高电平期间,SDA 由低电平向高电平的变化表示终止信号。每次发送
    数据时,先发送起始信号,然后依次发送 8 位数据,再发送终止信号。
  4. 实验板上时钟选择 100Hz;
  5. 输出端口 SCL 连接到 94 脚,SDA 连接到 95 脚。
    二、设计并实现一个串行信号接收器,接收以上串行信
    号发生器发送的信号,具体要求如下:
  6. 接收 SCL 和 SDA 信号,并根据 D7~D0 的值在相应的数码管上显示数
    值;
  7. D7 表示数码管是否显示数值,在 LD15 上显示 D7 的值。D7=0,数码管
    不显示;D7=1,在相应的数码管上显示数值;
  8. D6-D4 表示地址,即在哪个数码管上显示,如 D6~D4=“011”,则在 DISP3
    上显示数值;
  9. D3-D0 表示数据,在相应的数码管上显示数值(0~F);
  10. 实验板上时钟选择 10Hz 或者 100Hz;
  11. 输入端口 SCL 连接到 94 脚,SDA 连接到 95 脚。
    发生器和接收器分别在不同project中完成

img

img

可以借鉴下
https://www.yjbys.com/biyelunwen/fanwen/zidonghua/368686.html

该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
以下是一个可能的串行信号发生器和接收器的设计,使用了VHDL语言和Quartus II工具。

串行信号发生器的设计:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity serial_generator is
    port(
        clk     : in std_logic;
        btn     : in std_logic;
        sw      : in std_logic_vector(7 downto 0);
        scl_out : out std_logic;
        sda_out : out std_logic;
        ld      : out std_logic_vector(7 downto 0)
    );
end entity;

architecture rtl of serial_generator is

    signal cnt     : integer range 0 to 19999999 := 0;
    signal counter : integer range 0 to 7 := 0;
    signal data    : std_logic_vector(7 downto 0) := (others => '0');
    signal start   : std_logic := '0';
    signal stop    : std_logic := '0';
    signal sda     : std_logic := '1';

begin

    -- 时钟分频,将100MHz分频为100Hz
    process(clk)
    begin
        if rising_edge(clk) then
            if cnt = 999999 then
                cnt <= 0;
            else
                cnt <= cnt + 1;
            end if;
        end if;
    end process;

    -- 按键去抖
    process(clk, btn)
    begin
        if rising_edge(clk) then
            if btn = '1' then
                start <= '1';
                counter <= 0;
            else
                start <= '0';
            end if;
        end if;
    end process;

    -- 产生串行时钟信号
    process(cnt)
    begin
        if cnt = 0 then
            scl_out <= not scl_out;
            ld(0) <= scl_out;
            if scl_out = '1' then
                if start = '1' then
                    sda <= '0';
                    start <= '0';
                elsif counter < 8 then
                    sda <= sw(counter);
                    counter <= counter + 1;
                elsif counter = 8 then
                    sda <= '1';
                    counter <= 9;
                else
                    sda <= '1';
                    stop <= '1';
                end if;
            end if;
        end if;
    end process;

    -- 输出串行数据
    sda_out <= sda;

end architecture;

串行信号接收器的设计:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity serial_receiver is
    port(
        clk     : in std_logic;
        scl_in  : in std_logic;
        sda_in  : in std_logic;
        d       : out std_logic_vector(7 downto 0);
        disp    : out std_logic_vector(3 downto 0);
        ld      : out std_logic_vector(15 downto 0)
    );
end entity;

architecture rtl of serial_receiver is

    signal cnt     : integer range 0 to 19999999 := 0;
    signal counter : integer range 0 to 7 := 0;
    signal data    : std_logic_vector(7 downto 0) := (others => '0');
    signal start   : std_logic := '0';
    signal stop    : std_logic := '0';
    signal sda     : std_logic := '1';

begin

    -- 时钟分频,将100MHz分频为10Hz或100Hz
    process(clk)
    begin
        if rising_edge(clk) then
            if cnt = 99999999 then
                cnt <= 0;
            else
                cnt <= cnt + 1;
            end if;
        end if;
    end process;

    -- 接收串行数据
    process(cnt)
    begin
        if cnt = 0 then
            if scl_in = '0' then
                if start = '0' then
                    start <= '1';
                    counter <= 0;
                elsif counter < 8 then
                    data(counter) <= sda_in;
                    counter <= counter + 1;
                elsif counter = 8 then
                    stop <= '1';
                    counter <= 9;
                else
                    stop <= '1';
                end if;
            else
                start <= '0';
                stop <= '0';
                counter <= 0;
            end if;
        end if;
    end process;

    -- 输出数据
    d <= data;
    if ld(7) = '1' then
        if d(7) = '1' then
            disp <= "011";
            ld(15 downto 8) <= "00000001";
            ld(7 downto 0) <= data;
        else
            disp <= "000";
            ld(15 downto 8) <= "00000000";
            ld(7 downto 0) <= (others => '0');
        end if;
    else
        disp <= "000";
        ld(15 downto 0) <= (others => '0');
    end if;

end architecture;

这两个设计都需要在Quartus II中编译、综合、生成比特流文件,并下载到实验板上进行测试。同时,还需要在实验板上连接SW7~SW0、BTN3、LD0、LD7、94脚和95脚等接口,以便与外界进行数据交互。


如果以上回答对您有所帮助,点击一下采纳该答案~谢谢

你好,引用chatgpt部分指引作答,这个project1实现一个串行信号发生器

library ieee;
use ieee.std_logic_1164.all;

entity serial_generator is
    port (
        SW : in std_logic_vector(7 downto 0); -- parallel data input
        BTN : in std_logic; -- start button
        CLK : in std_logic; -- system clock (100Hz)
        LD : out std_logic_vector(7 downto 0); -- LED display
        SCL : out std_logic; -- serial clock output (94 pin)
        SDA : out std_logic -- serial data output (95 pin)
    );
end entity serial_generator;

architecture rtl of serial_generator is

    type state_type is (idle, start, send, stop); -- state machine enumeration
    signal current_state, next_state : state_type; -- state machine signals
    signal counter : integer range 0 to 99; -- counter for serial clock generation
    signal shift_reg : std_logic_vector(7 downto 0); -- shift register for parallel data output

begin

    process (CLK, BTN)
    begin
        if BTN = '1' then -- reset the state machine and the counter when the button is pressed
            current_state <= idle;
            counter <= 0;
        elsif rising_edge(CLK) then -- update the state machine and the counter on the rising edge of system clock
            current_state <= next_state;
            counter <= counter + 1;
            if counter = 99 then -- reset the counter when it reaches the maximum value
                counter <= 0;
            end if;
        end if;
    end process;

    process (current_state, SW, counter)
    begin
        case current_state is
            when idle => -- idle state: do not send data,
                SCL <= '1'; -- keep the serial clock and data high
                SDA <= '1';
                LD(0) <= '0'; -- turn off the LED display
                LD(7) <= '0';
                if counter = 0 then -- check the counter value to determine when to start sending data
                    next_state <= start; -- go to the start state
                    shift_reg <= SW; -- load the parallel data into the shift register
                else
                    next_state <= idle; -- stay in the idle state
                end if;
            when start => -- start state: generate the start signal
                SCL <= '1'; -- keep the serial clock high
                SDA <= '0'; -- change the serial data from high to low
                LD(0) <= '1'; -- turn on the LED display to indicate the serial clock
                LD(7) <= '1'; -- turn on the LED display to indicate the serial data
                if counter = 49 then -- check the counter value to determine when to send the first bit of data
                    next_state <= send; -- go to the send state
                else
                    next_state <= start; -- stay in the start state
                end if;
            when send => -- send state: send the parallel data bit by bit
                SCL <= not SCL; -- toggle the serial clock
                SDA <= shift_reg(7); -- output the most significant bit of the shift register
                LD(0) <= SCL; -- display the serial clock on the LED
                LD(7) <= SDA; -- display the serial data on the LED
                if counter = 49 then -- check the counter value to determine when to shift the register
                    shift_reg <= '0' & shift_reg(7 downto 1); -- shift the register right by one bit
                    if shift_reg = "00000000" then -- check if all bits have been sent
                        next_state <= stop; -- go to the stop state
                    else
                        next_state <= send; -- stay in the send state
                    end if;
                else
                    next_state <= send; -- stay in the send state
                end if;
            when stop => -- stop state: generate the stop signal
                SCL <= '1'; -- keep the serial clock high
                SDA <= '1'; -- change the serial data from low to high
                LD(0) <= '1'; -- turn on the LED display to indicate the serial clock
                LD(7) <= '1'; -- turn on the LED display to indicate the serial data
                if counter = 49 then -- check the counter value to determine when to go back to idle state
                    next_state <= idle; -- go to the idle state
                else 
                    next_state <= stop; -- stay in the stop state 
                end if;
        end case;
    end process;

end architecture rtl;

这个project2实现一个串行信号接收器,接收以上串行信
号发生器发送的信号


library ieee;
use ieee.std_logic_1164.all;

entity serial_receiver is
    port (
        CLK : in std_logic; -- system clock (10Hz or 100Hz)
        RST : in std_logic; -- reset signal
        SCL : in std_logic; -- serial clock input (94 pin)
        SDA : in std_logic; -- serial data input (95 pin)
        LD : out std_logic_vector(15 downto 0); -- LED display
        DISP : out std_logic_vector(7 downto 0); -- seven-segment display
        AN : out std_logic_vector(3 downto 0) -- seven-segment display selector
    );
end entity serial_receiver;

architecture rtl of serial_receiver is

    type state_type is (idle, receive, display); -- state machine enumeration
    signal current_state, next_state : state_type; -- state machine signals
    signal counter : integer range 0 to 99; -- counter for system clock division
    signal clk_bps : std_logic; -- divided clock for serial data sampling
    signal shift_reg : std_logic_vector(7 downto 0); -- shift register for serial data storage
    signal start_flag, stop_flag : std_logic; -- flags for start and stop signals detection

begin

    process (CLK, RST)
    begin
        if RST = '1' then -- reset the state machine and the counter when the reset signal is high
            current_state <= idle;
            counter <= 0;
        elsif rising_edge(CLK) then -- update the state machine and the counter on the rising edge of system clock
            current_state <= next_state;
            counter <= counter + 1;
            if counter = 99 then -- reset the counter when it reaches the maximum value
                counter <= 0;
            end if;
        end if;
    end process;

    process (current_state, SCL, SDA, counter)
    begin
        case current_state is
            when idle => -- idle state: do not receive data,
                clk_bps <= '0'; -- keep the divided clock low
                LD(15) <= '0'; -- turn off the LED display
                AN <= "1111"; -- turn off the seven-segment display
                DISP <= "00000000"; -- clear the seven-segment display data
                if SCL = '1' and SDA = '0' then -- check if a start signal is detected
                    next_state <= receive; -- go to the receive state
                    shift_reg <= "00000000"; -- clear the shift register
                    start_flag <= '1'; -- set the start flag
                else
                    next_state <= idle; -- stay in the idle state
                    start_flag <= '0'; -- clear the start flag
                end if;
            when receive => -- receive state: receive the serial data bit by bit
                if counter = 0 then -- check the counter value to generate the divided clock
                    clk_bps <= '1'; -- set the divided clock high
                elsif counter = 49 then
                    clk_bps <= '0'; -- set the divided clock low
                end if;
                if rising_edge(clk_bps) then -- sample the serial data on the rising edge of divided clock
                    shift_reg <= SDA & shift_reg(7 downto 1); -- shift the register left by one bit and input the serial data
                    if SCL = '1' and SDA = '1' then -- check if a stop signal is detected
                        next_state <= display; -- go to the display state
                        stop_flag <= '1'; -- set the stop flag
                    else
                        next_state <= receive; -- stay in the receive state
                        stop_flag <= '0'; -- clear the stop flag
                    end if;
                else
                    next_state <= receive; -- stay in the receive state
                end if;
            when display => -- display state: display the received data on the seven-segment display
                clk_bps <= '0'; -- keep the divided clock low
                LD(15) <= shift_reg(7); -- display the D7 bit on the LED
                AN <= not shift_reg(6 downto 4); -- select the seven-segment display according to D6-D4 bits
                DISP <= to_bcd(shift_reg(3 downto 0)); -- convert the D3-D0 bits to BCD code and display on the seven-segment display
                next_state <= idle; -- go back to the idle state after displaying
        end case;
    end process;

    function to_bcd (bin : std_logic_vector(3 downto 0)) return std_logic_vector is -- a function to convert binary code to BCD code for seven-segment display
        variable bcd : std_logic_vector(7 downto 0);
    begin
        case bin is 
            when "0000" => bcd := "00000001"; -- 0
            when "0001" => bcd := "10011111"; -- 1
            when "0010" => bcd := "00100101"; -- 2
            when "0011" => bcd := "00001101"; -- 3 
            when "0100" => bcd := "10011011"; -- 4 
            when "0101" => bcd := "01001001"; -- 5 
            when "0110" => bcd := "01000001"; -- 6 
            when "0111" => bcd := "00011111"; -- 7 
            when "1000" => bcd := "00000001"; -- 8 
            when "1001" => bcd := "00001001"; -- 9 
            when others => bcd := "11111111"; -- blank 
        end case;
        return bcd;
    end function;

end architecture rtl;

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
这是一道比较具体的数字电路设计题目,需要用到FPGA开发工具Quartus II和VHDL语言进行描述和实现。具体实现流程如下:

  1. 实现串行序列信号发生器

根据题目要求,设计出顺序逻辑电路,用以将并行输入信号转换为串行输出信号。实现步骤如下:

  • 用SW7~SW0作为并行输入端口,利用其他按键作为控制信号端口;
  • 定义状态机,控制串行时钟信号的输出;
  • 定义状态转移条件,实现数据的传输;
  • 定义信号SDA和SCL的状态,实现起始和终止信令的传输;
  • 将数据传输到SDA输出端口,控制LD7的显示。

VHDL代码如下:

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity generate_sd_serial is
port (
  sw : in std_logic_vector(7 downto 0);
  btn : in std_logic;
  clk_100 : in std_logic;
  sda : out std_logic;
  scl : out std_logic;
  ld7 : out std_logic);
end generate_sd_serial;

architecture sd_serial of generate_sd_serial is
type state is (idle, start, transmit_data, stop);
signal current_state: state;
signal data_count: integer range 0 to 7;
signal transmit_data_now: std_logic;
signal send_start: std_logic;
signal send_stop: std_logic;
signal time_out_sig: std_logic;

begin
  process(clk_100, btn)
  begin
    if btn='1' then
      current_state <= start;
      data_count <= 0;
      send_start <= '1';
      send_stop <= '0';
    elsif clk_100='1' and clk_100'event then
      case current_state is
        when idle =>
          scl <= '1';
          sda <= '1';
          ld7 <= '0';
          data_count <= '0';
          send_start <= '0';
          send_stop <= '1';
        when start =>
          if send_start = '1' then
            scl <= '1';
            sda <= '0';
            if time_out_sig = 'Z' then
              time_out_sig <= '0';
            else
              time_out_sig <= next_time_out;
            end if;
          else
            current_state <= transmit_data;
          end if;
        when transmit_data =>
            scl <= '0';
            sda <= transmit_data_now;
            if data_count = 7 then
              current_state <= stop;
            else
              current_state <= transmit_data;
            end if;
            data_count <= data_count + 1;
        when stop =>
            scl <= '1';
            sda <= '1';
            ld7 <= '1';
            if time_out_sig = 'Z' then
              time_out_sig <= '0';
            else
              time_out_sig <= next_time_out;
            end if;
            if time_out_sig = '1' then
              current_state <= idle;
            else
              current_state <= start;
              send_start <= '1';
              send_stop <= '0';
              data_count <= 0;
            end if;
        end case;
    end if;
  end process;

  next_time_out <= NOT time_out_sig;

  with current_state select
          transmit_data_now <=
              sw(7) when transmit_data,
              sw(6) when transmit_data and data_count = 1,
              sw(5) when transmit_data and data_count = 2,
              sw(4) when transmit_data and data_count = 3,
              sw(3) when transmit_data and data_count = 4,
              sw(2) when transmit_data and data_count = 5,
              sw(1) when transmit_data and data_count = 6,
              sw(0) when transmit_data and data_count = 7,
              '0' when others;

  scl <= '1' when send_start = '1' or send_stop = '1' else '0';
end sd_serial;
  1. 实现串行序列信号接收器

根据题目要求,设计出逆序逻辑电路,用以将串行输入信号转换为并行输出信号。实现步骤如下:

  • 用SDA和SCL作为串行输入端口,利用其他端口作为控制信号端口;
  • 定义状态机,控制串行时钟信号的输入和顺序输出;
  • 定义状态转移条件,实现数据的接收和传输;
  • 定义信号D7~D0、ADDR和DISP的状态,控制LED数码管的显示。

VHDL代码如下:

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity receive_sd_serial is
port (
  clk_10 : in std_logic;
  clk_100 : in std_logic;
  sda : in std_logic;
  scl : in std_logic;
  ld15 : out std_logic;
  disp : out std_logic_vector(2 downto 0);
  d : out std_logic_vector(7 downto 0));
end receive_sd_serial;

architecture sd_serial of receive_sd_serial is
type state is (idle, start, receive_data, stop);
signal current_state: state;
signal data_count: integer range 0 to 7;
signal receive_data_now: std_logic;
signal start_bit_received: std_logic;
signal stop_bit_received: std_logic;
signal display: std_logic;
signal d_value: std_logic_vector(3 downto 0);

begin
  process(clk_100)
  begin
    if clk_100='1' and clk_100'event then
      case current_state is
        when idle =>
          ld15 <= '0';
          display <= '0';
          disp <= "000";
          data_count <= 0;
          start_bit_received <= '0';
          stop_bit_received <= '0';
          current_state <= start;
        when start =>
          if scl = '1' and sda = '0' and not start_bit_received then
            start_bit_received <= '1';
          end if;

          if scl = '0' and start_bit_received then
            receive_data_now <= sda;
            current_state <= receive_data;
          end if;
        when receive_data =>
          if scl = '1' then
            receive_data_now <= sda;
          end if;

          if scl = '0' then
            data_count <= data_count + 1;
          end if;

          if data_count = 7 then
            current_state <= stop;
          end if;
        when stop =>
          if scl = '1' and sda = '1' and not stop_bit_received then
            stop_bit_received <= '1';
          end if;

          if scl = '0' and stop_bit_received then
            ld15 <= '1';
            d_value <= std_logic_vector(to_unsigned(2#(d(3 downto 0)),4));
            if d(7) = '1' then
              disp <= "011";
              display <= '1';
            end if;
            if d(6) = '1' then
              disp <= "010";
              display <= '1';
            end if;
            if d(5) = '1' then
              disp <= "001";
              display <= '1';
            end if;
            if d(4) = '1' then
              disp <= "000";
              display <= '1';
            end if;
            if d(3) = '1' then
              disp <= "101";
              display <= '1';
            end if;
            if d(2) = '1' then
              disp <= "100";
              display <= '1';
            end if;
            if d(1) = '1' then
              disp <= "011";
              display <= '1';
            end if;
            if d(0) = '1' then
              disp <= "010";
              display <= '1';
            end if;
            current_state <= start;
            start_bit_received <= '0';
            stop_bit_received <= '0';
            data_count <= 0;
          end if;
        end case;
    end if;
  end process;

  d(3 downto 0) <= d_value;
end sd_serial;

以上就是本题目的详细解答和VHDL代码。需要注意的是,本题是针对特定的硬件设备而定的,所以代码不能直接用于其他设备上,需要针对不同设备进行修改。
如果我的回答解决了您的问题,请采纳!

以下答案由GPT-4.5Plus大模型(语音)与博主A努力中.......共同编写:

根据要求,串行序列发生器和接收器的VHDL设计思路如下:

一、串行序列发生器:

  1. 定义8位输入端口SW和2位输出端口LD,以及串行时钟SCL和数据SDA。
vhdl
port(
    SW: in std_logic_vector(7 downto 0);
    LD: out std_logic_vector(1 downto 0);
    SCL: out std_logic;
    SDA: out std_logic    
);

  1. 定义process,对BTN3(开始键)的事件进行检测,产生串行时钟信号,同步发送SW的并行数据。
vhdl
process(CLK)
begin
    if(BTN3'event and BTN3 = '1') then
        SCL <= '1';
        LD(0) <= '1';
       wait for 2000ms;
        for i in 0 to 7 loop
            SDA <= SW(i);  
            wait for 2000ms;   
        end loop;
        SCL <= '0'; 
    end if;
end process;

  1. 发送数据时,SCL为高电平且SDA保持稳定,SCL下降沿SDA状态改变,发送起始和终止信号。

二、串行序列接收器:

  1. 定义输入端口SCL、SDA和输出端口D、LD,D控制数码管显示,LD15显示D7。
vhdl
port(
    SCL: in std_logic; 
    SDA: in std_logic;
    D: out std_logic_vector(7 downto 0);
    LD: out std_logic_vector(15 downto 0)
);
  

  1. process检测SCL上升沿和下降沿,读取SDA状态保存到D,控制数码管显示和LD15。
vhdl
process(CLK)
begin
    if(SCL'event and SCL = '1') then 
        D(i) <= SDA;
        i <= i + 1;
    elsif(SCL'event and SCL = '0') then
        if(D(7) = '1') then 
            case D(6 downto 4) is
                when "001" => DISP1 <= D(3 downto 0);
                when "010" => DISP2 <= D(3 downto 0);
                ...
            end case; 
        end if;
        LD(15) <= D(7);
        i <= 0;
    end if;
end process;

  1. D7控制是否显示,D6-D4控制显示位数码管,D3-D0显示数据。

以上就是根据要求完成串行序列发生器和接收器的VHDL设计思路。通过定义端口和进程,实现发生器产生数据和控制信号,接收器读取数据控制数码管显示。如果在实现的过程中遇到问题,请在CSDN提问,我将继续解答和讨论。