SystemC写UART发生模块

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.波形文件

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值