关于verilog实现的串并转换功能

关于verilog实现的串并转换功能,第1张

串并转换很简单,就是移位寄存器,后面最好跟一个锁存器,实现你所要求的功能需要四位移位寄存器和四位锁存器,锁存器的作用就是保持并行数据在移位时不发生变化:

module shift(nreset,clk,en,in,out)

input nreset,clk,en,in

output [3:0] out

reg [1:0] count//移位计数,控制并行数据更新,这里是4bit并行数据

reg [3:0] data

reg [3:0] out

/* 移位计数,用于并行数据输出,也可以外加一个脉冲控制数据边界,这里移位4bit就并行输出一次*/

always@(posedge clk or negedge nreset)

begin

if(~nreset)

count <= 2'b00

else if(en)

count <= count + 2'b01

end

//移位

always@(posedge clk or negedge nreset)

begin

if(~nreset)

data <= 4'b0000

eale if(en)

data <= {data[2:0],in}

end

//并行输出

always@(posedge clk or negedge nreset)

begin

if(~nreset)

out <= 4'b0000

else if(en &&(count==2'b11))

out <= data

end

endmodule

我编译、仿真过了,没有问题,你原有的out<={out,in}应该写成像这样data <= {data[2:0],in}这就是一个移位寄存器!

在做单片机的程序,由于串口不够,需要用IO口来模拟出一个串口。经过若干曲折并参考了一些现有的资料,基本上完成了。现在将完整的测试程序,以及其中一些需要总结的部分贴出来。

程序硬件平台:11.0592M晶振,

/***************************************************************

*在单片机上模拟了一个串口,使用P2.1作为发送端

*把单片机中存放的数据通过P2.1作为串口TXD发送出去

***************************************************************/

#include <reg51.h>

#include <stdio.h>

#include <string.h>

typedef unsigned char uchar

int i

uchar code info[] =

{

0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55

}

sbit newTXD = P2^1//模拟串口的发送端设为P2.1

void UartInit()

{

SCON = 0x50 // SCON: serail mode 1, 8-bit UART

TMOD |= 0x21 // T0工作在方式1,十六位定时

PCON |= 0x80 // SMOD=1

TH0 = 0xFE // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=11.0592MHz

TL0 = 0x7F // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=11.0592MHz

//TH0 = 0xFD // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=18.432MHz

//TL0 = 0x7F // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=18.432MHz

}

void WaitTF0(void)

{

while(!TF0)

TF0=0

TH0=0xFE // 定时器重装初值 fosc=11.0592MHz

TL0=0x7F // 定时器重装初值 fosc=11.0592MHz

//TH0 = 0xFD // 定时器重装初值 fosc=18.432MHz

//TL0 = 0x7F // 定时器重装初值 fosc=18.432MHz

}

void WByte(uchar input)

{

//发送启始位

uchar j=8

TR0=1

newTXD=(bit)0

WaitTF0()

//发送8位数据位

while(j--)

{

newTXD=(bit)(input&0x01) //先传低位

WaitTF0()

input=input>>1

}

//发送校验位(无)

//发送结束位

newTXD=(bit)1

WaitTF0()

TR0=0

}

void Sendata()

{

for(i=0i<sizeof(info)i++)//外层循环,遍历数组

{

WByte(info[i])

}

}

void main()

{

UartInit()

while(1)

{

Sendata()

}

}

##############################################################################

/***************************************************************

* 模拟接收程序,这个程序的作用从模拟串口接收数据,然后将这些数据发送到实际串口

*在单片机上模拟了一个串口,使用P3.2作为发送和接收端

*以P3.2模拟串口接收端,从模拟串口接收数据发至串口

***************************************************************/

#include<reg51.h>

#include<stdio.h>

#include<string.h>

typedef unsigned char uchar

//这里用来切换晶振频率,支持11.0592MHz和18.432MHz

//#define F18_432

#define F11_0592

uchar tmpbuf2[64]={0}

//用来作为模拟串口接收数据的缓存

struct

{

uchar recv :6 //tmpbuf2数组下标,用来将模拟串口接收到的数据存放到tmpbuf2中

uchar send :6 //tmpbuf2数组下标,用来将tmpbuf2中的数据发送到串口

}tmpbuf2_point={0,0}

sbit newRXD=P3^2 //模拟串口的接收端设为P3.2

void UartInit()

{

SCON=0x50 // SCON: serail mode 1, 8-bit UART

TMOD|=0x21 // TMOD: timer 1, mode 2, 8-bit reload,自动装载预置数(自动将TH1送到TL1)T0工作在方式1,十六位定时

PCON|=0x80 // SMOD=1

#ifdef F11_0592

TH1=0xE8 // Baud:2400 fosc=11.0592MHz 2400bps为从串口接收数据的速率

TL1=0xE8 // 计数器初始值,fosc=11.0592MHz 因为TH1一直往TL1送,所以这个初值的意义不大

TH0=0xFF // 定时器0初始值,延时208us,目的是令模拟串口的波特率为9600bps fosc=11.0592MHz

TL0=0xA0 // 定时器0初始值,延时208us,目的是令模拟串口的波特率为9600bps fosc=11.0592MHz

#endif

#ifdef F18_432

TH1=0xD8 // Baud:2400 fosc=18.432MHz 2400bps为从串口接收数据的速率

TL1=0xD8 // 计数器初始值,fosc=18.432MHz 因为TH1一直往TL1送,所以这个初值的意义不大

TH0=0xFF // 定时器0初始值,延时104us,目的是令模拟串口的波特率为9600bps fosc=18.432MHz

TL0=0x60 // 定时器0初始值,延时104us,目的是令模拟串口的波特率为9600bps fosc=18.432MHz

#endif

IE|=0x81 // 中断允许总控制位EA=1使能外部中断0

TF0=0

IT0=1 // 设置外部中断0为边沿触发方式

TR1=1 // 启动TIMER1,用于产生波特率

}

void WaitTF0(void)

{

while(!TF0)

TF0=0

#ifdef F11_0592

TH0=0xFF // 定时器重装初值 模拟串口的波特率为9600bps fosc=11.0592MHz

TL0=0xA0 // 定时器重装初值 模拟串口的波特率为9600bps fosc=11.0592MHz

#endif

#ifdef F18_432

TH0=0xFF

// 定时器重装初值 fosc=18.432MHz

TL0=0x60

// 定时器重装初值 fosc=18.432MHz

#endif

}

//接收一个字符

uchar RByte()

{

uchar Output=0

uchar i=8

TR0=1 //启动Timer0

#ifdef F11_0592

TH0=0xFF // 定时器重装初值 模拟串口的波特率为9600bps fosc=11.0592MHz

TL0=0xA0 // 定时器重装初值 模拟串口的波特率为9600bps fosc=11.0592MHz

#endif

#ifdef F18_432

TH0=0xFF // 定时器重装初值 fosc=18.432MHz

TL0=0x60 // 定时器重装初值 fosc=18.432MHz

#endif

TF0=0

WaitTF0()//等过起始位

//接收8位数据位

while(i--)

{

Output>>=1

if(newRXD)Output|=0x80 //先收低位

WaitTF0()//位间延时

}

TR0=0 //停止Timer0

return Output

}

//向COM1发送一个字符

void SendChar(uchar byteToSend)

{

SBUF=byteToSend

while(!TI)

TI=0

}

void main()

{

UartInit()

while(1)

{

if(tmpbuf2_point.recv!=tmpbuf2_point.send)//差值表示模拟串口接收数据缓存中还有多少个字节的数据未被处理(发送至串口)

{

SendChar(tmpbuf2[tmpbuf2_point.send++])

}

}

}

//外部中断0,说明模拟串口的起始位到来了

void Simulated_Serial_Start()interrupt 0

{

EX0=0 //屏蔽外部中断0

tmpbuf2[tmpbuf2_point.recv++]=RByte()//从模拟串口读取数据,存放到tmpbuf2数组中

IE0=0 //防止外部中断响应2次,防止外部中断函数执行2次

EX0=1 //打开外部中断0

}

51单片机超声波DIY

主要就是“shiftreg(15 downto 1) <= shiftreg(14 downto 0)”这句话的,其他是控制信号的。用count 来控制16位数据一次输出的。并串转换,你的程序是16位化为16个串行的时钟输出out<=shiftreg(15)。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/10990172.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-12
下一篇 2023-05-12

发表评论

登录后才能评论

评论列表(0条)

保存