赞
踩
串转并的使用环境非常多,在接口处用到最多,在某些模块的输入仅允许串行输入时,而总线上的数时并行的,那就需要通过串并转换,把并行的数据转换成串行的数据,包括在输出的时候,需要把串行的数据转换成并行的数据,才能送到总线中,使用方法都是用一个计数器来计数实现 。
用一个计数器count,每输入8个数,就输出一次,每周期dout_temp左移一位,然后再将输入的1bit串行据存入dout_temp的最低位。
module serial_to_parallel( input clk, input rst_n, input din_serial, input din_valid, output reg [7:0]dout_parallel, output reg dout_valid ); reg[7:0]din_tmp; reg[3:0]cnt; always@(posedge clk or negedge rst_n)begin if(!rst_n) cnt <= 0; else if(din_valid) cnt <= (cnt == 4'd8)?0:cnt+1'b1; else cnt <= 0; end always@(posedge clk or negedge rst_n)begin if(!rst_n) din_tmp <= 8'b0; else if(din_valid && cnt <= 4'd7) din_tmp <= {din_tmp[6:0],din_serial}; end always@(posedge clk or negedge rst_n)begin if(!rst_n)begin dout_valid <= 1'b0; dout_parallel <= 8'b0; end else if(cnt == 4'd8)begin dout_valid <= 1'b1; dout_parallel <= din_tmp; end else begin dout_valid <= 1'b0; end end endmodule
Testbench:
module serial_to_parallel_tb(); reg clk,rst_n; reg din_serial,din_valid; wire dout_valid; wire[7:0]dout_parallel; always #5 clk = ~clk; initial begin clk <= 1'b0; rst_n <= 1'b0; #15 rst_n <= 1'b1; din_valid <= 1'b1; din_serial <= 1'b1; #10 din_serial <= 1'b1; #10 din_serial <= 1'b1; #10 din_serial <= 1'b1; #10 din_serial <= 1'b0; #10 din_serial <= 1'b0; #10 din_serial <= 1'b0; #10 din_serial <= 1'b0; #10 din_valid <= 1'b0; #30 din_valid <= 1'b1; din_serial <= 1'b1; #10 din_serial <= 1'b1; #10 din_serial <= 1'b0; #10 din_serial <= 1'b0; #10 din_serial <= 1'b0; #10 din_serial <= 1'b0; #10 din_serial <= 1'b1; #10 din_serial <= 1'b1; #20 din_valid <= 1'b0; #50 $stop; end serial_to_parallel u0( .clk (clk) , .rst_n (rst_n) , .din_serial (din_serial) , .dout_parallel (dout_parallel) , .din_valid (din_valid) , .dout_valid (dout_valid) ); endmodule
仿真结果:
实现串并转换电路,输入端输入单bit数据,每当本模块接收到6个输入数据后,输出端输出拼接后的6bit数据。本模块输入端与上游的采用valid-ready双向握手机制,输出端与下游采用valid-only握手机制。数据拼接时先接收到的数据放到data_b的低位。
电路的接口如下图所示。valid_a用来指示数据输入data_a的有效性,valid_b用来指示数据输出data_b的有效性;ready_a用来指示本模块是否准备好接收上游数据,本模块中一直拉高;clk是时钟信号;rst_n是异步复位信号。
代码:
module s_to_p( input clk, input rst_n, input valid_a, input data_a, output reg ready_a, output reg valid_b, output reg [5:0]data_b ); always@(posedge clk or negedge rst_n)begin if(!rst_n) ready_a <= 1'b0; else ready_a <= 1'b1; end re[2:0]cnt; always@(posedge clk or negeedge rst_n)begin if(!rst_n) cnt <= 3'd0; else if(valid_a && ready_a) cnt <= cnt == 3'd5 ? 3'd0 : cnt + 1'b1; else cnt <= cnt; end reg [5:0]data_r; always@(posedge clk or negedge rst_n)begin if(!rst_n) data_r <= 6'd0; esle if(valid_a && ready_a) data_r <= {data_a,data_r[5:1]}; end always@(posedge clk or negedge rst_n)begin if(!rst_n)begin valid_b <= 1'b0; data_b <= 6'd0; end else if(cnt == 3'd5)begin data_b <= {data_a,data_r[5:1]}; valid_b <= 1'b1; end else valid_b <= 1'b0; end endmodule
并转串的原理和串转并差不多,都是用一个计数器来技术,根据串行和并行之间的关系来决定计数器计数的上下限。
在输入数据有效的时候din_valid为高时,把输入的数据寄存一下,寄存到din_parallel_temp中,然后再用一个计数器去检测输出,当计数器处在1~8的范围内时,让输出的串行数据等于输入的并行数据的最高位,然后每周期让并行数据左移一bit。这样,八周期后,就实现了并转串。
代码:
module parallel_to_serial( input clk, input rst_n, input [7:0] din_parallel, input din_valid, output reg dout_serial, output reg dout_valid ); reg[7:0]din_parallel_tmp; reg [3:0]cnt; always@(posedge clk or negedge rst_n)begin if(!rst_n) cnt <= 0; else if(din_valid) cnt <= cnt + 1'b1; else cnt <= 0; end always@(posedge clk or negedge rst_n)begin if(!rst_n)begin din_parallel_tmp <= 8'b0; dout_serial <= 1'b0; dout_valid <= 1'b0; end else if(din_valid && cnt == 0)begin din_parallel_tmp <= din_parallel; end else if((cnt >= 4'd1) && (cnt <= 4'd8))begin dout_serial <= din_parallel_tmp[7]; din_parallel_tmp <= din_parallel_tmp << 1; dout_valid <= 1'b1; end else begin dout_serial <= 1'b0; dout_valid <= 1'b0; end end endmodule
Testbench:
module parallel_to_serial_tb(); reg clk, rst_n; reg [7:0] din_parallel; reg din_valid; wire dout_valid,dout_serial; always #5 clk = ~clk; initial begin clk <= 1'b0; rst_n <= 1'b0; #15 rst_n <= 1'b1; din_valid <= 1'b1; din_parallel <= 8'b11110000; #80 din_valid <= 1'b0; #40 din_valid <= 1'b1; din_parallel <= 8'b10100011; #80 din_valid <= 1'b0; #50 $stop(); end parallel_to_serial u_parallel_to_serial( .clk (clk) , .rst_n (rst_n) , .din_parallel (din_parallel) , .din_valid (din_valid) , .dout_serial (dout_serial) , .dout_valid (dout_valid) ); endmodule
仿真结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。