错题记录:
这是一道有关串行协议的题,在发送数据时,首先发送的是低位。
这道题我用了两种方法,第二种方法花了接近一天的时间才找到问题所在,主要是由于忽略了阻塞赋值和非阻塞赋值,这两者的差别造成的。
(1)阻塞赋值和非阻塞赋值
我一开始temp 《= {in,out_byte}; out_byte 《= temp[8:1]; 使用的是非阻塞赋值,这样是错误的,应该使用阻塞赋值。因为只有在阻塞赋值下,才是先进行temp = {in,out_byte};这一句的赋值,得到了新的temp以后,再顺利的完成预期中的out_byte= temp[8:1];的赋值。
(2)对沿触发型always块的理解误区
我之前一直认为,边沿触发的always块,代表的一定是时序逻辑,所以在always块内部只能使用“非阻塞赋值”(《= ),但是实际上,是可以使用 “阻塞赋值” (=)的。
- 阻塞赋值 表示 组合逻辑,非阻塞赋值 表示 时序逻辑。
- 沿触发的always块常常用于描述时序行为,但是在其内部,也是可以出现组合逻辑的。
题目:
现在,您已经有了一个有限的状态机,可以识别何时在串行比特流中正确接收字节,请添加一个数据路径,该路径将输出正确接收的数据字节。out_byte在完成时需要有效,否则就是不在乎。
请注意,串行协议首先发送最低有效位。
正确答案:(重点在于先发送最低有效位)
方法一:temp = {in,out_byte};//不断接收in,拼接在temp的前面。
out_byte = temp[8:1];//不断的取temp的高8位。
注意:不能写成out_byte = {in,out_byte}。因为这样会位宽不够,而导致只截取到了低八位的数据
方法二:out_byte <= {out_byte,in};//不断接收in,拼接在末位;
out_byte <={out_byte[0],out_byte[1],out_byte[2],out_byte[3],out_byte[4],
out_byte[5],out_byte[6],out_byte[7]}; //然后再交换各位的位置
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output [7:0] out_byte,
output done
); //
reg [8:0] temp;
reg [3:0] state,next_state;
parameter S0=0,S1=1,S2=2,S3=3,S4=4,S5=5,S6=6,S7=7,S8=8,S9=9,DONE=10,ERROR=11;
always@(*)begin
case(state)
S0: next_state = in?S0:S1;
S1: next_state = S2;
S2: next_state = S3;
S3: next_state = S4;
S4: next_state = S5;
S5: next_state = S6;
S6: next_state = S7;
S7: next_state = S8;
S8: next_state = S9;
S9: next_state = in?DONE:ERROR;
DONE: next_state = in?S0:S1;
ERROR: next_state = in?S0:ERROR;
endcase
end
always@(posedge clk)begin
if(reset)
state <= S0;
else
state <= next_state;
end
assign done = (state==DONE);
// Use FSM from Fsm_serial
always@(posedge clk)begin// New: Datapath to latch input bits. //方法一
if(reset)begin
out_byte <= 8'b0;//时序逻辑
temp <= 9'b0;
end
else if((S1<=state)&&(state<=S8))begin
temp = {in,out_byte};//这里应该是组合逻辑,原来错写为了temp 《= {in,out_byte};
temp = {in,out_byte};//这里应该是组合逻辑,原来错写为了temp 《= {in,out_byte};
end
else if(state==S9)
out_byte <= out_byte;//时序逻辑
end
// always@(posedge clk)begin// New: Datapath to latch input bits. //方法二
// if(reset)
// out_byte <= 8'b0;
// else if((S1<=state)&&(state<=S8))
// out_byte <= {out_byte,in};
// else if(state==S9)
// out_byte <= {out_byte[0],out_byte[1],out_byte[2],out_byte[3],out_byte[4],out_byte[5],out_byte[6],out_byte[7]};
// end
endmodule
成功的仿真:
报错的仿真: