Foreword:
This column aims to record high-frequency pen interview hand-torn code questions for digital front-end autumn recruits. All articles in this column provide principle analysis, codes and waveforms, and all codes have been verified by myself.
The directory is as follows:
1. Digital IC hand-tear code-frequency divider (any even number frequency division)
2. Digital IC hand-tear code-frequency divider (any odd frequency division)
3. Digital IC hand-tear code-frequency divider (any decimal frequency division)
4. Digital IC hand tearing code - asynchronous reset and synchronous release
5. Digital IC hand tear code - edge detection (rising edge, falling edge, double edge)
6. Digital IC hand tearing code-sequence detection (state machine writing method)
7. Digital IC hand tearing code-sequence detection (shift register writing method)
8. Digital IC tearing code - half adder, full adder
9. Digital IC hand tearing code - serial to parallel, parallel to serial
10. Digital IC hand tearing code-data bit width converter (width-narrow, narrow-width conversion)
11. Digital IC hand tearing code - finite state machine FSM - beverage machine
12. Digital IC hand tear code - handshake signal (READY-VALID)
14. Digital IC hand tearing code - Telink micro written test questions
15. Digital IC hand tearing code - Pingtouge technology final face hand tearing real question
16. Digital IC manual tearing code-Zhaoyi innovation written test real questions
18. Digital IC tearing code - dual-port RAM (dual-port-RAM)
...Continually updated
For more hand-tearing code questions, you can go to the digital IC hand-tearing code--question bank
Table of contents
topic description
The data is serially converted and processed, and 3780 serial bits are input, and each data occupies one clock cycle, and the input occupies a total of 3780 clocks. It is required to output 63 bits in parallel, and a total of 60 clocks are output. The timing diagram is as follows: 1 clock outputs 0, 60,...,3720 in parallel, and outputs the second clock in parallel as 1, 61,... 3721 as the bus as a whole, and the 60th clock outputs 59, 119,... 3779 in parallel Note that each parallel output only occupies one clock cycle , 60 clock cycles will complete the output. The relative delay relationship between output and input can be arbitrary.
problem solving ideas
This problem seems to be very simple at first glance, and the serial-to-parallel conversion is enough, but it actually involves a single-bit data location problem. Not only that, if the written code is not "one-time", it can withstand back-to-back transmission , and the test of intermittent transmission, the code still needs to be written to take all the circumstances into account.
Let’s rethink the meaning of the title. The title is to realize a serial-to-parallel conversion, input 1-bit data per cycle, and complete the input of 3780 1-bit data within 3780 cycles. Because the parallel output is performed after all the serial inputs are completed, we need to store 3780 serial inputs, which can be directly stored in RAM or registers. Parallel output, each output 63bit, total output 60 cycles, 60*63bit=3780bit.
The key here is that the adjacent bits of the parallel output are jumping, 0, 60, 120...; 1, 61, 121...; so it is particularly important to find the mapping relationship between the parallel output and the serial input. A one-dimensional array data_store of 60*63=3780 can be used to store the input serial data. My idea is to use an address addr to index the position stored in the one-dimensional array data_store each time, and then every 63 cycles is a loop, with a total of 60 loops. In one loop, a single bit is written into the one-dimensional array. Data and location are stored in 59, 119, 179,..., 3719, 3779 respectively. Every 63 cycles (after storing 63 bits of data), the one-dimensional array is shifted to the right by 1 bit (high bit on the left, low bit on the right). In this way, after 62 shifts, the first written single-bit data will be shifted to the lowest bit, the bit written at position 62 at the beginning will be shifted to position 0, and the bit written at position 3779 at the beginning , will be shifted to position 3717. Finally, after 60 loops, 3780 single-bit data have been input, and we can output high-bit data, pull the output_valid output valid signal high, and at the same time output 63bit once in a cycle, output 63bit 60 times, and complete the serial to parallel conversion.
reg [5:0] shiftcount;
always @(posedge clk)begin
if(data_in_ena && loop_row == 6'd0)begin
data_store[addr] <= serial_data;
end
else if(data_in_ena && loop_row != 6'd0 && count_row == 6'd0)begin
data_store <= {1'b0,data_store[3779:64],serial_data,data_store[62:1]}; //should shift 63 times 60bit shift one times
shiftcount <= shiftcount + 1'b1;
end
else if(data_in_ena && loop_row != 6'd0 && count_row > 6'd0)begin
data_store[addr] <= serial_data;
end
end
always @(posedge clk)begin
if(!rstn)begin
addr <= 12'd62;
shiftcount <= 6'd0;
end
else if(data_in_ena && count_row < 59)begin
addr <= 63*count_row+12'd125; //addr belongs to {62,125,188,...,3779}
end
else if(data_in_ena && count_row == 59)begin
addr <= 12'd62;
end
end
the code
module serial_to_parallel (
input clk ,
input rstn ,
input serial_data ,
input data_in_ena ,
output [62:0] parallel_data ,
output reg data_out_ena
);
reg [3779:0] data_store;
reg [11:0] addr;
reg [62:0] parallel_data_reg;
reg [5:0] count_column,count_row; //one column is once parallel_data
reg [5:0] loop_column,loop_row;
reg [5:0] output_count;
reg output_valid;
always @(posedge clk)begin //one loop ,save 63 bits data, so count_column belongs to [0,62]
if(!rstn)begin
count_column <= 6'd0;
end
else if(data_in_ena && count_column < 6'd62)begin
count_column <= count_column + 1'b1;
end
else if(data_in_ena && count_column == 6'd62)begin
count_column <= 6'd0;
end
end
always @(posedge clk)begin //count_row belongs to [0,59]
if(!rstn)begin
count_row <= 6'd0;
end
else if(data_in_ena && count_row < 6'd59)begin
count_row <= count_row + 1'b1;
end
else if(data_in_ena && count_row == 6'd59)begin
count_row <= 6'd0;
end
end
always @(posedge clk)begin //loop_column belongs to [0,59]
if(!rstn)begin
loop_column <= 6'd0;
end
else if(count_column == 6'd62 && loop_column < 6'd59)begin
loop_column <= loop_column + 1'b1;
end
else if(count_column == 6'd62 && loop_column == 6'd59)begin
loop_column <= 6'd0;
end
end
always @(posedge clk)begin //loop_row belongs to [0,62]
if(!rstn)begin
loop_row <= 6'd0;
end
else if(count_row == 6'd59 && loop_row < 6'd62)begin
loop_row <= loop_row + 1'b1;
end
else if(count_row == 6'd59 && loop_row == 6'd62)begin
loop_row <= 6'd0;
end
end
reg [5:0] shiftcount;
always @(posedge clk)begin
if(data_in_ena && loop_row == 6'd0)begin
data_store[addr] <= serial_data;
end
else if(data_in_ena && loop_row != 6'd0 && count_row == 6'd0)begin
data_store <= {1'b0,data_store[3779:64],serial_data,data_store[62:1]}; //should shift 63 times 60bit shift one times
shiftcount <= shiftcount + 1'b1;
end
else if(data_in_ena && loop_row != 6'd0 && count_row > 6'd0)begin
data_store[addr] <= serial_data;
end
end
always @(posedge clk)begin
if(!rstn)begin
addr <= 12'd62;
shiftcount <= 6'd0;
end
else if(data_in_ena && count_row < 59)begin
addr <= 63*count_row+12'd125; //addr belongs to {62,125,188,...,3779}
end
else if(data_in_ena && count_row == 59)begin
addr <= 12'd62;
end
end
//parallel output
genvar i ;
generate
for (i=0;i<=59;i=i+1)begin
always @(posedge clk)begin
if(output_valid == 1'b1)begin
case(output_count)
i:parallel_data_reg <= data_store[i*63+62:i*63];
endcase
end
end
end
endgenerate
always @(posedge clk)begin
if(!rstn)begin
output_valid <= 1'b0;
end
else if(count_column == 6'd62 && loop_column == 6'd59)begin
output_valid <= 1'b1;
end
else if(output_valid == 1'b1 && output_count == 6'd59)begin
output_valid <= 1'b0;
end
end
always @(posedge clk)begin
if(!rstn)begin
output_count <= 6'd0;
end
else if(output_valid == 1'b1 && output_count < 6'd59)begin
output_count <= output_count + 1'b1;
end
else begin
output_count <= 6'd0;
end
end
always @(posedge clk)begin
data_out_ena <= output_valid; //one beat late
end
assign parallel_data = parallel_data_reg;
endmodule
testbench
module serial_to_parallel_tb();
reg clk,rstn;
reg serial_data,data_in_ena;
wire [62:0] parallel_data;
wire data_out_ena;
always #5 clk = ~clk;
initial begin
clk <= 1'd0;
rstn <= 1'd0;
serial_data <= 1'b1;
#16
rstn <= 1'b1;
forever begin
repeat(3780)begin
#10
serial_data <= serial_data + 1'b1;
data_in_ena <= 1'b1;
end
repeat(60)begin
#10
data_in_ena <= 1'b0;
end
end
end
initial begin
#100000
$finish();
end
//dump fsdb
initial begin
$fsdbDumpfile("serial_to_parallel.fsdb");
$fsdbDumpvars(0);
end
serial_to_parallel u_serial_to_parallel(
.clk (clk) ,
.rstn (rstn) ,
.serial_data (serial_data) ,
.data_in_ena (data_in_ena) ,
.parallel_data (parallel_data) ,
.data_out_ena (data_out_ena)
);
endmodule
output waveform
Back-to-back transmission is supported, single-bit data is input in 3780 cycles, and then a valid signal is input and pulled low for 60 cycles. At this time, the output valid signal is pulled high, and 63-bit parallel data is output for 60 cycles.
For more hand-tearing code questions, you can go to the digital IC hand-tearing code--question bank