In this week I was modifying the Wishbone switch so that it would gave correct signal outputs.
To give an overview, the strobe signal from the previous wire must be passed to the next wire after one clock cycle, until it reached the I/O port. As a result, the I/O would asset an acknowledgement signal, which would negate the current strobe signal. And the acknowledgement signal would be passed to the next wire after one clock cycle as well. This whole bus cycle was demonstrated in the following timing diagram.
To do so, I created three registers, which were io_stb_flag, reg io_ack_flag and down_stb_flag. Each of them had a different purpose to indicate a state.
When there was an input of an acknowledgement signal from the I/O, this would assert io_ack_flag. The io_ack_flag was used to assert up_ack_o during the next bus cycle, and the flag would be automatically reset to zero.
In addition, when the strobe signal was passed from upstream to downstream, this would assert down_stb_flag. When the down_stb_flag was asserted, the signal would not be passed from upstream again in the next clock cycle. Thus the flag was used as a state and there would be no unnecessary assertion of down_stb_o.
Similarly, when the data was passed from upstream to io port, this would assert io_stb_flag. When the io_stb_flag was asserted, the strobe signal would not be passed from upstream to I/O port during the next clock cycle.
Furthermore, Dr Shawn advised me not to implement multiplexer and demultiplexer. This was because using mux and demux would encounter several issues during the synthesis process. As a result, I had to modify the blocks into D-flip flops. A D-flip flop would consist of a reset, an enable, an input D and an output Q. An example of D flip flop was shown below.
always@(posedge clk_i)
begin
if (rst_i) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
io_adr_o <= {ADDR_WIDTH{1’b0}};
io_dat_o <= {DATA_WIDTH{1’b0}};
io_stb_flag <= 1’h0;
io_stb_o <= 1’h0;
// End of automatics
endelse if (up_stb_i & match_addr & ~io_stb_flag) begin
io_adr_o <= up_adr_i; // 32 bits addr
io_dat_o <= up_dat_i; // 32 bits data
io_stb_o <= up_stb_i; // iostream stb goes high
io_stb_flag <= 1’b1;
end
endalways@(posedge clk_i)
begin
if (rst_i) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
up_ack_o <= 1’h0;
up_dat_o <= {DATA_WIDTH{1’b0}};
// End of automatics
endelse if (down_ack_i) begin
up_dat_o <= down_dat_i; // 32 bits data
up_ack_o <= down_ack_i;
end
end
Additionally, I was studying a dual port RAM and figuring how to wrap it inside a Wishbone bus. Regarding the RAM, the width for the RAM was fixed at 8-bit. As a result, a total of four dual port RAMs should be instantiated inside the Wishbone bus, to give a word of 32 bits. On the other hand, I had to determine the number of address lines based on the file size, and the file size could be extracted using the command llvm-size {file}.
In conclusion, I managed to obtain an accurate result of a timing diagram and I would continue to work on the Wishbone RAM next week.
0 Comments