一、串入并出移位寄存器
1.1、概念
串入并出移位寄存器:串行数据,经过几个时钟周期,
在移位寄存器中,最终输出并行的数据。
2.1、串入并出设计图
端口解释:
a) i_clk:串口时钟
b) i_rest:模块复位信号
c) i_data:串口输入端
d) i_ena:片选信号
e) i_full:模块输入缓冲器已满(提醒发送端停止发送)
f) o_ready:模块输出缓冲器已准备好数据(提醒并行接收端可以接收数据了)
g) o_cout[7:0]:并行数据输出端
h) i_ack:并行接端数据接收完成反馈信息(这时如果模块输入缓冲区有已接收的数据则可将数据传送至输出缓冲区进行发送)
二、实现代码
2.1、SIPO module:
module SIPO(o_ready,o_cout,i_ack,i_full,i_clk,i_rest,i_data,i_ena);
output o_ready,o_cout,i_full,i_ack;
input i_clk,i_rest,i_data,i_ena;
reg i_full,o_ready,i_ack;
reg [7:0] i_buffer;
wire [7:0] o_cout;
reg [7:0] o_cout_temp,o_buffer;
reg [2:0] i_flag;
//该模块采用双缓冲机制-输入缓冲和输出缓冲,
//在输出缓冲向外并行发送数据的同时 如果输入缓冲器不满则可继续串行接收数据;
//时序逻辑电路
always @(posedge i_clk or posedge i_rest)
begin
if(i_rest)
begin
o_cout_temp<=8'b0; //输出为0
i_full<=0; //模块输入缓冲器未满
o_ready<=0; //模块输出缓冲器未准备好数据
i_buffer<=0; //输入缓冲器置0
o_buffer<= 8'b0; //输出缓冲器置0
i_ack<=0; //输出未接收完数据
i_flag<=3'b000; //标记信号为0 没准备好
i_full<=8'b0; //输入缓冲标记为0 没准备好
end
else if(i_ena) //片选信号选通
begin
if(i_ack==0) //并行端未接收完成 前9个周期
begin
if(i_full==0 & o_ready==0) //模块输入缓存器未满 输出缓冲器没做好准备
begin
if(i_flag==3'b111) //输入buffer已经满了 提醒发送端停止发送
begin
o_buffer <= i_buffer; //输出buffer赋值为输入buffer 非阻塞赋值
i_full <=1;
end
else //一次输出完成
begin
i_buffer<={i_buffer[7:1],i_data}; //输去缓冲器置为输入缓冲器 阻塞赋值
i_flag<=i_flag + 3'b001;
end
end
else if(i_full==1 & o_ready==0)//输入buffer满了 赋值为输出buffer 非阻塞赋值
begin
o_cout_temp<=o_buffer;
o_ready<=1; //输出准备
end
else if(i_full==1 & o_ready==1) //输出buffer满了 赋值为输出
o_cout_temp<=o_buffer; // 赋值为输出
i_ack<=1; //输出有值了
i_full<=0;
end
else //并行接端数据接收完成反馈信息(这时如果模块输入缓冲区有已接收的数据则可将数据传送至输出缓冲区进行发送)
begin
if(i_full) //输入buffer满的
begin
o_buffer <= i_buffer;
o_cout_temp <= o_buffer;
i_full <= 0;
end
else
begin
i_buffer <= i_data;
i_full <=1 ;
end
end
end
else //高阻态
begin
i_full<=1'bz;
o_ready<=1'bz;
i_buffer<= 8'bz;
o_buffer<= 8'bz;
o_cout_temp<= 8'bz;
end
end
assign o_cout = o_cout_temp;
endmodule
2.2、test_SIFO module:
module test_SIPO;
reg i_clk_t,i_data_t,i_rest_t,i_ena_t;
wire o_ready_t,i_ack_t,i_full_t;
reg [7:0] i_buffer_t,o_buffer_t;
wire [7:0] o_cout_t;
SIPO mySIPO(
.o_ready(o_ready_t),
.o_cout(o_cout_t),
.i_ack(i_ack_t),
.i_full(i_full_t),
.i_clk(i_clk_t),
.i_rest(i_rest_t),
.i_data(i_data_t),
.i_ena(i_ena_t));
initial
begin
i_rest_t = 1; //rest signal
i_clk_t = 0;
i_data_t = 0;
i_ena_t =0;
#10 i_rest_t = 0;
#5 i_ena_t = 1;
end
always #5 i_clk_t = ~i_clk_t;
always #10 i_data_t = {$random}%2;
endmodule