Advertisement
Guest User

Untitled

a guest
Nov 7th, 2023
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.17 KB | None | 0 0
  1.  
  2.  
  3.  
  4. // Verilog
  5. // - UART transmitter module.
  6. //
  7.  
  8. module uart_tx(
  9. input wire clk , // Top level system clock input.
  10. input wire resetn , // Asynchronous active low reset.
  11. output wire uart_txd , // UART transmit pin.
  12. output wire uart_tx_busy, // Module busy sending previous item.
  13. input wire uart_tx_en , // Send the data on uart_tx_data
  14. input wire [PAYLOAD_BITS-1:0] uart_tx_data // The data to be sent
  15. );
  16.  
  17. // ---------------------------------------------------------------------------
  18. // External parameters.
  19. //
  20.  
  21. //
  22. // Input bit rate of the UART line.
  23. parameter BIT_RATE = 9600; // bits / sec
  24. localparam BIT_P = 1_000_000_000 * 1/BIT_RATE; // nanoseconds
  25.  
  26. //
  27. // Clock frequency in hertz.
  28. parameter CLK_HZ = 50_000_000;
  29. localparam CLK_P = 1_000_000_000 * 1/CLK_HZ; // nanoseconds
  30.  
  31. //
  32. // Number of data bits recieved per UART packet.
  33. parameter PAYLOAD_BITS = 8;
  34.  
  35. //
  36. // Number of stop bits indicating the end of a packet.
  37. parameter STOP_BITS = 1;
  38.  
  39. // ---------------------------------------------------------------------------
  40. // Internal parameters.
  41. //
  42.  
  43. //
  44. // Number of clock cycles per uart bit.
  45. localparam CYCLES_PER_BIT = BIT_P / CLK_P;
  46.  
  47. //
  48. // Size of the registers which store sample counts and bit durations.
  49. localparam COUNT_REG_LEN = 1+$clog2(CYCLES_PER_BIT);
  50.  
  51. // ---------------------------------------------------------------------------
  52. // Internal registers.
  53. //
  54.  
  55. //
  56. // Internally latched value of the uart_txd line. Helps break long timing
  57. // paths from the logic to the output pins.
  58. reg txd_reg;
  59.  
  60. //
  61. // Storage for the serial data to be sent.
  62. reg [PAYLOAD_BITS-1:0] data_to_send;
  63.  
  64. //
  65. // Counter for the number of cycles over a packet bit.
  66. reg [COUNT_REG_LEN-1:0] cycle_counter;
  67.  
  68. //
  69. // Counter for the number of sent bits of the packet.
  70. reg [3:0] bit_counter;
  71.  
  72. //
  73. // Current and next states of the internal FSM.
  74. reg [2:0] fsm_state;
  75. reg [2:0] n_fsm_state;
  76.  
  77. localparam FSM_IDLE = 0;
  78. localparam FSM_START= 1;
  79. localparam FSM_SEND = 2;
  80. localparam FSM_STOP = 3;
  81.  
  82.  
  83. // ---------------------------------------------------------------------------
  84. // FSM next state selection.
  85. //
  86.  
  87. assign uart_tx_busy = fsm_state != FSM_IDLE;
  88. assign uart_txd = txd_reg;
  89.  
  90. wire next_bit = cycle_counter == CYCLES_PER_BIT;
  91. wire payload_done = bit_counter == PAYLOAD_BITS ;
  92. wire stop_done = bit_counter == STOP_BITS && fsm_state == FSM_STOP;
  93.  
  94. //
  95. // Handle picking the next state.
  96. always @(*) begin : p_n_fsm_state
  97. case(fsm_state)
  98. FSM_IDLE : n_fsm_state = uart_tx_en ? FSM_START: FSM_IDLE ;
  99. FSM_START: n_fsm_state = next_bit ? FSM_SEND : FSM_START;
  100. FSM_SEND : n_fsm_state = payload_done ? FSM_STOP : FSM_SEND ;
  101. FSM_STOP : n_fsm_state = stop_done ? FSM_IDLE : FSM_STOP ;
  102. default : n_fsm_state = FSM_IDLE;
  103. endcase
  104. end
  105.  
  106. // ---------------------------------------------------------------------------
  107. // Internal register setting and re-setting.
  108. //
  109.  
  110. //
  111. // Handle updates to the sent data register.
  112. integer i = 0;
  113. always @(posedge clk) begin : p_data_to_send
  114. if(!resetn) begin
  115. data_to_send <= {PAYLOAD_BITS{1'b0}};
  116. end else if(fsm_state == FSM_IDLE && uart_tx_en) begin
  117. data_to_send <= uart_tx_data;
  118. end else if(fsm_state == FSM_SEND && next_bit ) begin
  119. for ( i = PAYLOAD_BITS-2; i >= 0; i = i - 1) begin
  120. data_to_send[i] <= data_to_send[i+1];
  121. end
  122. end
  123. end
  124.  
  125.  
  126. //
  127. // Increments the bit counter each time a new bit frame is sent.
  128. always @(posedge clk) begin : p_bit_counter
  129. if(!resetn) begin
  130. bit_counter <= 4'b0;
  131. end else if(fsm_state != FSM_SEND && fsm_state != FSM_STOP) begin
  132. bit_counter <= {COUNT_REG_LEN{1'b0}};
  133. end else if(fsm_state == FSM_SEND && n_fsm_state == FSM_STOP) begin
  134. bit_counter <= {COUNT_REG_LEN{1'b0}};
  135. end else if(fsm_state == FSM_STOP&& next_bit) begin
  136. bit_counter <= bit_counter + 1'b1;
  137. end else if(fsm_state == FSM_SEND && next_bit) begin
  138. bit_counter <= bit_counter + 1'b1;
  139. end
  140. end
  141.  
  142.  
  143. //
  144. // Increments the cycle counter when sending.
  145. always @(posedge clk) begin : p_cycle_counter
  146. if(!resetn) begin
  147. cycle_counter <= {COUNT_REG_LEN{1'b0}};
  148. end else if(next_bit) begin
  149. cycle_counter <= {COUNT_REG_LEN{1'b0}};
  150. end else if(fsm_state == FSM_START ||
  151. fsm_state == FSM_SEND ||
  152. fsm_state == FSM_STOP ) begin
  153. cycle_counter <= cycle_counter + 1'b1;
  154. end
  155. end
  156.  
  157.  
  158. //
  159. // Progresses the next FSM state.
  160. always @(posedge clk) begin : p_fsm_state
  161. if(!resetn) begin
  162. fsm_state <= FSM_IDLE;
  163. end else begin
  164. fsm_state <= n_fsm_state;
  165. end
  166. end
  167.  
  168.  
  169. //
  170. // Responsible for updating the internal value of the txd_reg.
  171. always @(posedge clk) begin : p_txd_reg
  172. if(!resetn) begin
  173. txd_reg <= 1'b1;
  174. end else if(fsm_state == FSM_IDLE) begin
  175. txd_reg <= 1'b1;
  176. end else if(fsm_state == FSM_START) begin
  177. txd_reg <= 1'b0;
  178. end else if(fsm_state == FSM_SEND) begin
  179. txd_reg <= data_to_send[0];
  180. end else if(fsm_state == FSM_STOP) begin
  181. txd_reg <= 1'b1;
  182. end
  183. end
  184.  
  185. endmodule
  186.  
  187.  
  188.  
  189. //
  190. // Module: tb
  191. //
  192.  
  193. `timescale 1ns/1ns
  194. `define WAVES_FILE "./work/waves-tx.vcd"
  195.  
  196. module tb;
  197.  
  198. reg clk ; // Top level system clock input.
  199. reg resetn ;
  200.  
  201. wire uart_txd ; // UART transmit pin.
  202. wire uart_tx_busy; // Module busy sending previous item.
  203. reg uart_tx_en ;
  204. reg [7:0] uart_tx_data; // The recieved data.
  205.  
  206. //
  207. // Bit rate of the UART line we are testing.
  208. localparam BIT_RATE = 9600;
  209. localparam BIT_P = (1000000000/BIT_RATE);
  210.  
  211. //
  212. // Period and frequency of the system clock.
  213. localparam CLK_HZ = 50000000;
  214. localparam CLK_P = 1000000000/ CLK_HZ;
  215. localparam CLK_P_2 = 500000000/ CLK_HZ;
  216.  
  217.  
  218. //
  219. // Make the clock tick.
  220. always #CLK_P_2 clk=~clk;
  221.  
  222.  
  223. //
  224. // Sends a single byte down the UART line.
  225. task send_byte;
  226. input [7:0] to_send;
  227. begin
  228. $display("Send data %b at time %d", to_send,$time);
  229. uart_tx_data= to_send;
  230. uart_tx_en = 1'b1;
  231. end
  232. endtask
  233.  
  234.  
  235. //
  236. // Run the test sequence.
  237. reg [7:0] to_send;
  238. initial begin
  239. resetn = 1'b0;
  240. clk = 1'b0;
  241. #40 resetn = 1'b1;
  242.  
  243. $dumpfile(`WAVES_FILE);
  244. $dumpvars(0,tb);
  245.  
  246. repeat(20) begin
  247. to_send = $random;
  248. send_byte(to_send);
  249. #1000;
  250. wait(!uart_tx_busy);
  251. end
  252.  
  253. $display("BIT RATE : %db/s", BIT_RATE );
  254. $display("BIT PERIOD: %dns" , BIT_P );
  255. $display("CLK PERIOD: %dns" , CLK_P );
  256. $display("CYCLES/BIT: %d" , i_uart_tx.CYCLES_PER_BIT);
  257.  
  258. $display("Finish simulation at time %d", $time);
  259. $finish();
  260. end
  261.  
  262.  
  263. //
  264. // Instance of the DUT
  265. uart_tx #(
  266. .BIT_RATE(BIT_RATE),
  267. .CLK_HZ (CLK_HZ )
  268. ) i_uart_tx(
  269. .clk (clk ),
  270. .resetn (resetn ),
  271. .uart_txd (uart_txd ),
  272. .uart_tx_en (uart_tx_en ),
  273. .uart_tx_busy (uart_tx_busy ),
  274. .uart_tx_data (uart_tx_data )
  275. );
  276.  
  277. endmodule
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement