经过几天的调试终于有结果了,但是程序还有待优化。调试发现还是基础比较薄弱没有好好的看书,感觉还是要把夏宇闻的书好好看下。在夏宇闻书中写到:“若在同一个时钟的正跳沿下对寄存器组既进行输入又进行输出,很有可能由于门的延迟使输入条件还未确定时,就输出了下一个状态,这种情况会导致逻辑的紊乱。而利用上一个时钟为下一个时钟创造触发条件的方式是安全可靠的。在实际电路的实现中,采取了许多有效的措施来确保成立:1.全局时钟网络布线时尽量使各分支的时钟一致。2.采用平衡树结构,在每一级加入缓冲器,使达到每个触发器时钟端的时钟同步。”
我的程序中的ram_read的状态中,既对ram_output_data和rom_output_data赋值,又对其进行运算,导致数据有个延时。
1 ram_read: begin 2 if (ROM_count <= count3) begin 3 RAM_ADDR_R <= count2; 4 ROM_ADDR <= ROM_count; 5 ram_output_data <= ram_output; 6 rom_output_data <= rom_output; 7 da_data_ <= ram_output_data * rom_output_data + da_data_; 8 if (count2 == 0) begin 9 10 end 11 else begin 12 count2 <= count2 - 1; 13 end 14 ROM_count <= ROM_count + 1; 15 state <= ram_read; 16 end 17 else state <= state_data_output; 18 end 19 state_data_output: begin 20 da_data <= da_data_[31:16] + 16‘d32767; 21 state <= ram_write; 22 end 23 default: state <= ram_idle; 24 endcase 25 end
之前的ram_read的状态
后来将赋值和运算分两个状态后,数据少了一个延时,但是还是将之前的一个数据计算进去了。又在夏宇闻书中看到用非阻塞赋值是先存到一个隐藏的寄存器里,待下一个时钟来到输出,既第一次计算还是上一次存储的数据,所以我将RAM和ROM的地址做了下缓存之后再给出,结果就正确了。
1 ram_write: begin 2 if (ad_clk_pos) 3 begin 4 RAM_ADDR_W <= count1; 5 ram_wr <= 1‘b1; 6 da_data_ <= 32‘d0; 7 count4 <= 16‘d0; 8 ROM_count <= 5‘d0; 9 ram_output_data <= 16‘d0; 10 rom_output_data <= 16‘d0; 11 ram_data <= ad_data - 16‘d32767; 12 state <= ram_count; 13 end 14 end 15 ram_count: begin 16 if (count1 == 16‘d31) begin 17 count2 <= count1; 18 count3 <= count1; 19 count1 <= 16‘d0; 20 end 21 else begin 22 count2 <= count1; 23 count3 <= count1; 24 count1 <= count1 + 16‘d1; 25 end 26 // RAM_ADDR_R <= count2; 27 // ROM_ADDR <= ROM_count; 28 state <= ram_WR_END; 29 end 30 ram_WR_END: begin 31 ram_wr <= 1‘b0; 32 state <= ram_wait; 33 end 34 ram_wait: begin 35 RAM_ADDR_R <= count2; 36 ROM_ADDR <= ROM_count; 37 state <= ram_read; 38 end 39 ram_read: begin 40 if (ROM_count <= count3) begin 41 RAM_ADDR_R <= count2; 42 ROM_ADDR <= ROM_count; 43 state <= ram_dddd; 44 end 45 else state <= state_data_output; 46 47 end 48 ram_dddd: begin 49 if (count4 == 2) begin 50 count4 <= 16‘d0; 51 state <= ram_delay; 52 end 53 else begin 54 count4 <= count4 + 1; 55 state <= ram_dddd; 56 end 57 end 58 ram_delay:begin 59 ram_output_data <= ram_output; 60 rom_output_data <= rom_output; 61 state <= ram_process; 62 end 63 ram_process:begin 64 da_data_ <= ram_output_data * rom_output_data + da_data_; 65 if (count2 == 0) begin 66 67 end 68 else begin 69 count2 <= count2 - 16‘d1; 70 end 71 ROM_count <= ROM_count + 5‘d1; 72 state <= ram_read; 73 end 74 state_data_output: begin 75 da_data <= da_data_[31:16] + 16‘d32767; 76 state <= ram_write; 77 end 78 default: state <= ram_idle; 79 endcase 80 end
改进之后的状态机
此图是我改进之后的仿真信号图:
在这几天的调试过程中,遇到了很多小的问题,导致仿真出来的结果和自己预想的总是差了点,发现自己对verilog了解的太少了,还停留在C语言的调试状态下。
时间: 2024-10-20 10:35:31