概述
1.UART原理部分可以参考其他博主。
UART.h头函数
#include <iostream>
#include "systemc.h"
#define BPS_CNT (50000000/9600) // 波特率9600
/*
*端口声明
*进行声明
*/
SC_MODULE(UART0) {
sc_in < bool > clk, start_flag , sys_rst_n; // 时钟、起始标识、复位信号
sc_in < sc_bv<8> > q ; // 8位数据的输入
sc_out < bool > tx_flag; // 发送过程标志,高电平则是发送数据的状态
sc_out < sc_bv<8> > q_output; // 右移一位后的结果
sc_out < sc_bv<1> > uart_txd; // 发送的1位数据,起始位、第0位,...,第8位,终止位
sc_signal < sc_bv<8> > tx_data;
sc_signal < sc_uint<4> > tx_cnt;
sc_signal < sc_uint<15> > bps_cnt;
void prc_outputs(); // 组合逻辑
void BPS_TIMER(); // 计数,即clock与波特率的转换
void load_data(); // 加载输入数据(时序逻辑)
SC_CTOR(UART0) {
SC_METHOD(prc_outputs); // 组合逻辑,把各个敏感信号都列出来哦
sensitive << tx_cnt << start_flag << sys_rst_n.neg();//<<current_state<< reg_enable << cnt_enable
SC_METHOD(load_data); // 同上
sensitive << start_flag << tx_cnt << bps_cnt << sys_rst_n.neg(); //<< count
SC_METHOD(BPS_TIMER); // 时序逻辑,敏感信号至于时钟有关
sensitive << clk.pos() << sys_rst_n.neg();
}
};
#include "UART.h"
// 组合逻辑,实现数据按位发送
// q_output:数据右移一位输出,可以把此端口屏蔽
void UART0::prc_outputs() {
sc_bv<8> q_temp;
if (!sys_rst_n) {
uart_txd = '1'; // 空闲状态,发送端为高电平
}
else if (start_flag) {
//cout << "ttx_cnt:" << tx_cnt.read() << endl;
switch (tx_cnt.read()) {
case 0:
uart_txd = '0';
q_output.write("00000000"); break; // 发送起始位
case 1:
uart_txd = tx_data.read().range(0, 0);
q_temp = ("0", tx_data.read().range(7, 1));
q_output.write(q_temp);
break;
case 2:
uart_txd = tx_data.read().range(1, 1);
q_temp = ("00", tx_data.read().range(7, 2));
q_output.write(q_temp);
break;
case 3:
uart_txd = tx_data.read().range(2, 2);
q_temp = ("000", tx_data.read().range(7, 3));
q_output.write(q_temp);
break;
case 4:
uart_txd = tx_data.read().range(3, 3);
q_temp = ("0000", tx_data.read().range(7, 4));
q_output.write(q_temp);
break;
case 5:
uart_txd = tx_data.read().range(4, 4);
q_temp = ("00000", tx_data.read().range(7, 5));
q_output.write(q_temp);
break;
case 6:
uart_txd = tx_data.read().range(5, 5);
q_temp = ("0000000", tx_data.read().range(7, 6));
q_output.write(q_temp);
break;
case 7:
uart_txd = tx_data.read().range(6, 6);
q_temp = ("0000000", tx_data.read().range(7, 7));
q_output.write(q_temp);
break;
case 8:
uart_txd = tx_data.read().range(7, 7);
q_temp = ("00000000");
q_output.write(q_temp);
break;
case 9: uart_txd = '1'; break; // 发送停止位
default: uart_txd = '1'; break;
}
}else {
uart_txd = '1';
}
}
计数线程,计数满则UART0::prc_outputs()中的case跳转一次
void UART0::BPS_TIMER() { // 时序逻辑
if (!sys_rst_n) {
bps_cnt = 0;
tx_cnt = 0;
}else if (bps_cnt.read() < BPS_CNT - 1) {
bps_cnt = bps_cnt.read() + 1;
tx_cnt = tx_cnt;
}else {
bps_cnt = 0;
tx_cnt = tx_cnt.read() + 1;
}
}
start_flag==1时,并行加载输入数据,且在发送状态时tx_flag设置为高电平。
void UART0::load_data() {
if (!sys_rst_n) {
tx_flag = false;
tx_data = "00000000";
}else if (start_flag) {
tx_flag = true;
tx_data = q.read();
}else if ((tx_cnt.read() == 9) && (bps_cnt.read() == BPS_CNT / 2)) {
tx_flag = false;
tx_data = "00000000";
tx_cnt = 0;
}else {
tx_flag = tx_flag;
tx_data = tx_data;
}
}
monitor模块,用于打印信息输出
#include "systemc.h"
SC_MODULE(monitor_s) {
sc_in < sc_bv<1> > m_uart_txd;
sc_in< sc_bv<8> > m_q, m_q_output;
sc_in< bool > m_sys_rst_n, m_start_flag, m_tx_flag, clk;
void prc_monitor(){
while (1) {
cout << "At time:" << sc_time_stamp();
cout << "t m_reset=" << m_sys_rst_n.read() << "t m_start_flag=" << m_start_flag.read();
cout << "t m_q=" << m_q.read() << "t m_q_output=" << m_q_output.read();
cout << "t m_tx_flag = " << m_tx_flag.read() << "tm_uart_txd = " << m_uart_txd << endl;
wait();
}
}
SC_CTOR(monitor_s) {
SC_THREAD(prc_monitor);
sensitive << m_sys_rst_n << m_q << m_tx_flag << m_q_output << m_start_flag << m_uart_txd;
}
};
main.cpp中完成端口绑定
#include "systemc.h"
#include "UART.h"
#include "monitor.h"
int sc_main(int argc, char **argv) {
sc_signal < sc_bv<1> > t_uart_txd;
sc_signal< sc_bv<8> > t_q, t_q_output;
sc_signal< bool > t_sys_rst_n, t_start_flag, t_tx_flag;
sc_clock clock("clock", 20, SC_NS);
cout << "straT: " << endl;
// 实例化端口,绑定
UART0 uart_send("UART_TEST");
uart_send.clk(clock);
uart_send.start_flag(t_start_flag);
uart_send.tx_flag(t_tx_flag);
uart_send.sys_rst_n(t_sys_rst_n);
uart_send.q(t_q);
uart_send.q_output(t_q_output);
uart_send.uart_txd(t_uart_txd);
// 实例化端口,绑定
monitor_s mol("mol_TEST");
mol.clk(clock);
mol.m_start_flag(t_start_flag);
mol.m_tx_flag(t_tx_flag);
mol.m_sys_rst_n(t_sys_rst_n);
mol.m_q(t_q);
mol.m_q_output(t_q_output);
mol.m_uart_txd(t_uart_txd);
// 给case进行验证
//t_sys_rst_n.write(false);
t_sys_rst_n.write(true);
t_sys_rst_n.write(false);
t_sys_rst_n.write(true);
t_start_flag.write(true);
t_q.write("11111111");
// 用于生成波形文件
sc_trace_file *tf = sc_create_vcd_trace_file("Top");
sc_trace(tf, uart_send.clk, "clk");
sc_trace(tf, uart_send.start_flag, "start_flag");
sc_trace(tf, uart_send.tx_flag, "tx_flag");
sc_trace(tf, uart_send.sys_rst_n, "sys_rst_n");
sc_trace(tf, uart_send.q, "q");
sc_trace(tf, uart_send.q_output, "q_output");
sc_trace(tf, uart_send.uart_txd, "uart_txd");
sc_start(1666522, SC_NS); // 设置仿真时间
sc_close_vcd_trace_file(tf);/// 关闭仿真文件
sc_stop(); // 仿真停止
return 0;
}
2.结果
3.波形文件
最后
以上就是善良枕头为你收集整理的SystemC写UART发生模块的全部内容,希望文章能够帮你解决SystemC写UART发生模块所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复