• 正文
  • 相关推荐
申请入驻 产业图谱

8086接口缓存与同步串行发送 VHDL ModelSim

01/19 11:03
146
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

项目信息

名称:8086接口缓存与同步串行发送 VHDL ModelSim

软件:ModelSim

语言:VHDL

代码功能

该工程实现一个带缓冲的串行发送模块:外部以8086兼容的片选/读写/地址信号写入8位数据,模块内部用环形缓冲区存储数据;在同步信号FS到来时,若缓冲区累计数据达到阈值,则按固定节拍把若干字节从高位到低位串行输出到TXD;若数据不足,则输出空闲字节用于占位,保证链路连续性。

代码实现思路

实现上把“并行写入”和“串行发送”分离:写入过程在2MHz时钟下对片选与写信号进行采样,将D总线数据写入数组并推进写指针;发送过程使用状态机等待FS的有效窗口,在满足“缓存中至少4字节”等条件后进入发送状态。每个字节通过位计数器控制移位输出,高位先出;当一个字节发送完成时产生读走脉冲推进读指针并更新待发送字节。这种结构既能适配不均匀的写入节奏,又能在同步场景下稳定地输出固定长度的帧数据。

代码结构

代码主体由三部分组成:1)环形缓冲区与读写指针,完成数据入队/出队统计;2)主状态机,决定当前输出空闲字节还是输出有效数据;3)位计数与移位逻辑,将字节转换为串行比特流。模块的关键接口是FS:FS有效时优先尝试输出有效数据帧;否则维持空闲字节输出。通过data_count限制出队条件,避免在帧发送过程中出现数据不完整。

1、程序文件

Testbench

2、程序编译

3、仿真图

部分代码

serial_data_tx.vhd

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;

entity serial_data_tx is
Port (
-- 8086兼容接口信号
WR_n    : inSTD_LOGIC;                    -- 写信号(低有效)
RD_n    : inSTD_LOGIC;                    -- 读信号(低有效)
D       : in STD_LOGIC_VECTOR(7 downto 0); -- 双向数据线
A0      : inSTD_LOGIC;                    -- 地址线
CS_n    : inSTD_LOGIC;                    -- 片选信号

-- 时钟和同步信号
CLK_2M: inSTD_LOGIC;                    -- 2.048MHz时钟
FS      : inSTD_LOGIC;                    -- 同步信号(低有效)

-- 串行输出
TXD     : out STD_LOGIC                     -- 串行数据输出
);
end serial_data_tx;

architecture Behavioral of serial_data_tx is
-- 数据缓冲区 - 存储4个字节
type data_buffer_type is array (0 to 7) of STD_LOGIC_VECTOR(7 downto 0);
signal data_buffer : data_buffer_type;
signal write_ptr : integer range 0 to 7 := 0;-- 写指针
signal read_ptr : integer range 0 to 7 := 0;-- 读指针
signal data_count : integer range 0 to 8 := 0; -- 缓冲区中数据个数
signal FS_D : STD_LOGIC:='0';
signal ram_rd : STD_LOGIC:='0';
signal send_data : integer range 0 to 7 := 0;
signal bit_count : integer range 0 to 7 := 0;--每个字节的位计数0~7
signal bit_count_d: integer range 0 to 7 := 0;
signal preread_byte : STD_LOGIC_VECTOR(7 downto 0) := X"7E"; --当前发送的字节
signal current_send_byte : STD_LOGIC_VECTOR(7 downto 0) := X"7E"; --当前发送的字节
signal tx_byte : STD_LOGIC_VECTOR(7 downto 0) := X"7E"; --发送的字节
-- 状态机
type state_type is (IDLE, SYNC_WAIT, TRANSMIT, TRANS_DATA, TRANS_IDLE);
signal current_state : state_type := IDLE;

begin
-- 8086兼容的读写接口
process(CLK_2M)
begin
if rising_edge(CLK_2M) then
-- 写操作:向数据缓冲区写入数据
if CS_n = '0' and WR_n = '0' and A0 = '0' then
if data_count < 8 then
data_buffer(write_ptr) <= D;
write_ptr <= (write_ptr + 1) mod 8;
data_count <= data_count + 1;
end if;
elsif ram_rd = '1' then --读走
if data_count > 0 then
data_count <= data_count - 1;
--read_ptr <= (read_ptr + 1) mod 8;
end if;
end if;
end if;
end process;

-- 主状态机
process(CLK_2M)
begin
if rising_edge(CLK_2M) then
-- 主状态机
case current_state is
when IDLE =>
current_state <= SYNC_WAIT;
when SYNC_WAIT => --等待FS
if FS = '0' then
current_state <= TRANSMIT;
else
current_state <= TRANS_IDLE;
end if;
when TRANSMIT => --发送
if data_count >= 4 then --buffer中够4字节
current_state <= TRANS_DATA;
else
current_state <= TRANS_IDLE;
end if;
when TRANS_DATA => --发送数据
if send_data = 3 and bit_count = 7 then --已经发送4个字节
current_state <= TRANS_IDLE;
else
current_state <= TRANS_DATA;
end if;
when TRANS_IDLE => --发送空闲字节
if FS = '0'then --and bit_count = 7
if(data_count >= 4 )then
current_state <= TRANS_DATA;
else
current_state <= TRANS_IDLE;
end if;
else
current_state <= TRANS_IDLE;
end if;
when others =>
current_state <= IDLE;
end case;
end if;
end process;

--控制send_data,发送的字节数
process(CLK_2M)
begin
if rising_edge(CLK_2M) then
case current_state is
when TRANSMIT =>
send_data <= 0; -- 重置发送字节计数
when TRANS_DATA =>
if bit_count = 7 then -- 一个字节发送完成
if send_data < 3 then
send_data <= send_data + 1;
else
send_data <= 0;
end if;
end if;
when TRANS_IDLE =>
send_data <= 0; -- 重置发送字节计数
when others =>
null;
end case;
end if;
end process;

--控制bit_count--每个字节的位计数
process(CLK_2M)
begin
if rising_edge(CLK_2M) then
case current_state is
when TRANSMIT =>
bit_count <= 0; -- 重置位计数
when TRANS_DATA | TRANS_IDLE =>
if bit_count = 7 then
bit_count <= 0; -- 一个字节发送完成,重置位计数
else
bit_count <= bit_count + 1; -- 位计数递增
end if;
when others =>
null;
end case;
end if;
end process;

--控制每次发送的字节内容
process(CLK_2M)
begin
if rising_edge(CLK_2M) then
-- 默认ram_rd为低电平
ram_rd <= '0';

case current_state is
-- when TRANSMIT =>
--进入发送状态时,准备第一个字节
-- if data_count >= 4 then
-- preread_byte <= data_buffer(read_ptr);
-- else
-- preread_byte <= X"7E"; -- 空闲字节
-- end if;
when TRANS_DATA =>
if bit_count = 0 then -- 当前字节发送完成,准备下一个字节
-- 产生ram_rd脉冲,表示读走一个数据
ram_rd <= '1';
read_ptr <= (read_ptr + 1) mod 8;
-- 准备下一个字节
preread_byte <= data_buffer(read_ptr);
end if;
when TRANS_IDLE =>
preread_byte <= X"7E"; -- 空闲字节
when others =>
null;
end case;
end if;
end process;

process(CLK_2M)
begin
if rising_edge(CLK_2M) then
bit_count_d<=bit_count;
current_send_byte<=preread_byte;
end if;
end process;
--                                                        tx_byte<=std_logic_vector(shift_left(unsigned (preread_byte),bit_count)); -- 数据左移
--                TXD <= tx_byte(7);--最终输出移位后信号的最高位

-- 控制将待发送的字节转换为串行输出,高位在前
process(current_state,preread_byte,bit_count_d)
begin
case current_state is
when IDLE | SYNC_WAIT =>
TXD <= '0'; -- 空闲时输出高电平
tx_byte<=X"7E";
when TRANSMIT =>
TXD <= '0'; -- 准备发送时输出高电平
when TRANS_DATA | TRANS_IDLE =>
---数据左移

 

【来源:www.hdlcode.com

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录